Resume simulation when any 2 threads out of 3 get completed within fork-join_any

There are three parallel threads running in fork-join_any.
I want to come-out from that when any two threads get completed.
How to do this?

In reply to Sagar Shah:
You can use a semaphore that waits for 2 keys

semaphore s;

s = new(0);
fork
   begin : process1
    ...
    s.put(1);
   end
 begin : process2
    ...
    s.put(1);
   end
 begin : process3
    ...
    s.put(1);
 end
join_none
s.get(2);
disable fork; // kills remaining process
s = null; // removes semaphore (if you plan to reuse s)

In reply to dave_59:

Thanks for quick solution.
Today I came to know actual usage of semaphore.

Is there any solution possible without the use of semaphore?

In reply to amiya957:

There are other solutions like using a simple counter, but they are not considered “thread-safe”. They would work fine in most situations, but the LRM does not guarantee atomic execution when multiple processes are writing to the same variable. i.e. if two process simultaneously execute N=N+1, there is no guarantee that N winds up being incremented by 2.

With today’s tools, I would say this is an impossible situation, but as your code gets more complex, and as tools adopt multi-core technologies, it could happen. So it’s better to code it the safe way.

In reply to dave_59:

Hi Dave ,

Could it possible using Fine-Grain Process Control ? . Particularly " await " and
" process.status != FINISHED "

Also your suggestion regarding counters being " thread unsafe" is Certainly Crucial .
What I am curious to know is what could be the counter be incremented to ( if not by 2 ) .
Since its a blocking statement although there would be no atomic guarantee , wouldn’t the 2nd Incremental Statement always see the Updated Value ( i.e incremented by 1 ) ?

Not arguing , just curious to know

Thanks ,

AGIS

In reply to Etrx91:

Yes, there are a number of ways to accomplish the same, but all require access to a shared memory variable with some sort of process count. Incrementing a location in memory involves three steps: read, modify(increment), write. It’s a blocking assignment statement in the sense that within the same thread, these three steps must occur in order before the next statement executes. But there’s no guarantee that another process could be executing the same steps interweaved with each other.