Many times we need to disable the active threads spawned by the fork. But while disabling a fork, one should always be careful, as it can cause an unexpected behaviour. This article explains the unexpected behaviour of disabling a fork, using the different scenarios.
Here, We have two threads, executes parallelly using fork-join_any and our intention is to disable a fork after completion of Thread 1.
Example 1] Disable fork and Disable label with single object of a class
Let’s start with a simple example, where we have a fork-join_any inside a class, which executes two threads parallelly. As in below example 1, a fork is disabled once Thread 1 is completed. This example will produce the same output if we use “disable kill_me” instead of “disable fork” at line number 9, where “kill_me” is a label of the fork (see line number: 4), which we want to disable.
For a single object of a class, “disable fork” and “disable label” works fine. But what if the class has multiple objects. Let’s see in the following examples (2 and 3).
Example 2] Disable fork with two objects of the class
Here, the code in example 1 is modified for the two objects of the class. In the class disable_fork, an additional variable “obj_id” is taken to identify that the main method inside the class is called using which object.
By looking at the output on the above image, both the objects complete Thread 1 and then disable their “own” fork. What if we use “disable label” (here, a label is kill_me) instead of disable fork?
Example 3] Disable label with two objects of the class
Here, at line 15, the “disable fork” is replaced by “disable kill_me”.
Oops, the “disable kill_me” of object 0 has also killed the fork of object 1. This is not the output we were expecting.
So, after looking at all the three examples, it seems that “disable fork” is safer than “disable label”. But “disable fork” is really safe in this context…..??? Let’s see Example 4.
Example 4] Disable fork with multiple forks in the same task
Here, we have added one more fork (join_none) in the main() task of the class. This new fork should not be disabled.
But, when we use disable fork, then it disables all the forks in the current scope.
From examples 3 and 4,
- if we use “disable label”, then it is visible across all the objects of the same class, so it disables all the forks with the same label in the different objects.
- If we use “disable fork”, then it disables all the forks in the current scope.
This problem is resolved in example 5.
Example 5] Safest way to use the disable fork
Here, we have wrapped the fork “kill_me” inside another fork-join.
Conclusion:
Always use an additional fork to wrap-up all the forks, you want to diable. This is a safe way, as it limits the scope of a disable fork.
P.S.: Please follow the below link if you want to play with all these five examples 🙂
EDAPlaygound_disable_fork