Scenario: An asynchronous task in a loop executes a method containing arguments that change as the program continues:
while(this._variable < 100)
{
this._variable++;
var aTask = Task.Factory.StartNew(() =>
{
aList.add(this._variable);
update(this._savePoint);
});
}
If the loop runs faster than the tasks complete, will the list add the current value of the variable or is the variable saved locally and the original value added?
In argument pass by value, the argument passing mechanism works by copying each argument into the subroutine area. if any changes to arguments within the subroutine, those changes will not be visible outside the subroutine.
SystemVerilog provides below means for passing arguments to functions and tasks, also, functions and tasks can have default argument values. In argument pass by value, the argument passing mechanism works by copying each argument into the subroutine area.
Any modifications to the argument value in a pass by reference can be avoided by using const keyword before ref, any attempt in changing the argument value in subroutine will lead to a compilation error. variables x and y are passed as an argument in the function call sum, changes to the argument x within the function, is visible outside.
Passing the parameters by values does not affect the original variable. Below is the example of Passing by Value: System.out.println (" Value (before change)="+p.a); System.out.println (" Value (after change)="+p.a); As we can see from the above output, the original values is not affected by the pass by value mechanism.
Closures close over variables, not values. Therefore, incrementing _variable
can alter the behavior of the task that refers to it.
You can prevent this by making a local copy:
while (this._variable < 100)
{
this._variable++;
int local = _variable;
var aTask = Task.Factory.StartNew(() =>
{
aList.add(local);
update(this._savePoint);
});
}
Or you could pass the value to the task as state:
while (this._variable < 100)
{
this._variable++;
var aTask = Task.Factory.StartNew(object state =>
{
aList.add((int)state);
update(this._savePoint);
}, this._variable);
}
These both work by copying the value of _variable
to a new temporary variable. In the first case the local
variable is defined inside the scope of the loop, so you get a new one for every iteration. In the second case, you make a copy of the value of _variable
when you pass it to the Task as the state
argument. If _variable
were a reference type, these solutions wouldn't work; you'd have to perform a clone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With