Wait - Maple Help

 Wait
 wait for a condition variable to be signaled

 Calling Sequence Wait( condId, mutexId )

Parameters

 condId - (integer) condition variable identifier mutexId - (integer) mutex identifier

Description

 • The Wait command is called to pause the current thread until it is signaled by the condition variable condId.  The Wait command accepts a mutex identifier as mutexId.  The current thread must have obtained the lock on mutexId by calling the Threads[Mutex][Lock] command. When Wait is called, the thread is paused and mutexId is unlocked atomically.  When the thread is started again, it will re-obtain the lock on mutexId before the thread returns from Wait. Another thread can use the Signal or Broadcast commands with condId as the argument to restart a waiting thread. The Signal and Broadcast commands do not require having mutexId locked, however it is often a good idea to do so.  By locking mutexId while calling Signal or Broadcast you can guarantee that no threads are entering Wait at the same time.
 • For more information on using condition variables, see the Condition Variable help page.

Examples

This is an example of a Producer/Consumer pattern.

The Producer creates jobs (here represented by integers in the global table tab).  The Consumers remove a job, process it, then insert the result back into the table.

We have two condition variables and one mutex.  One condition variable (cp) is used for the Producer thread.  The Producer thread will pause on the producer condition variable if enough jobs are available for processing. The other condition variable (cc) is used for the Consumer threads.  When no jobs are available, the Consumer threads will pause on that condition variable until the Producer creates more jobs.

The mutex is used to protect access to the global variable tab.

 > Producer := proc( m, cp, cc, max, mindiff )     global tab, e;     local i,j,n;     Threads[Mutex][Lock]( m );     j := 0;     tab[ "maxjob" ] := mindiff;     tab[ "curjob" ] := 1;     for j from 1 to mindiff     do         tab[ j ] := 2*j;     end do;     Threads[ConditionVariable][Signal]( cp );     n := false;     while ( e )     do         j := tab[ "maxjob" ];         if ( j - tab[ "curjob" ] > mindiff/2 ) then             n := true;             Threads[ConditionVariable][Wait]( cp, m );         end if;         for i from j to tab[ "curjob" ] + mindiff         do             tab[ i ] := 2*i;         end do;         tab[ "maxjob" ] := tab[ "curjob" ] + mindiff;         if ( n ) then             Threads[ConditionVariable][Broadcast]( cc );             n := false;         end if;     end do;     Threads[Mutex][Unlock]( m ); end proc: Consumer := proc( m, cp, cc, max )     global tab, e;     local n, i, j, num;     num := 0;     Threads[Mutex][Lock]( m );     while ( num < max )     do         while ( tab[ "curjob" ] = tab[ "maxjob" ] )         do             Threads[ConditionVariable][Signal]( cp );             Threads[ConditionVariable][Wait]( cc, m );         end do;         n := tab[ "curjob" ];         j := tab[ n ];         tab[ "curjob" ] := n + 1;         Threads[Mutex][Unlock]( m );         j := add( i, i=1..j );         num := num+1;         Threads[Mutex][Lock]( m );         tab[ n ] := j;     end do;     Threads[Mutex][Unlock]( m ); end proc:
 > $\mathrm{tab}≔\mathrm{table}\left(\right):$
 > $m≔\mathrm{Threads}\left[\mathrm{Mutex}\right]\left[\mathrm{Create}\right]\left(\right)$
 ${m}{≔}{2}$ (1)
 > $\mathrm{cc}≔\mathrm{Threads}\left[\mathrm{ConditionVariable}\right]\left[\mathrm{Create}\right]\left(\right)$
 ${\mathrm{cc}}{≔}{1}$ (2)
 > $\mathrm{cp}≔\mathrm{Threads}\left[\mathrm{ConditionVariable}\right]\left[\mathrm{Create}\right]\left(\right)$
 ${\mathrm{cp}}{≔}{2}$ (3)
 > $e≔\mathrm{true}:$

Start the Producer thread. We wait on cp until the Producer thread has started.

 > $\mathrm{Threads}\left[\mathrm{Mutex}\right]\left[\mathrm{Lock}\right]\left(m\right)$
 > $\mathrm{id1}≔\mathrm{Threads}\left[\mathrm{Create}\right]\left(\mathrm{Producer}\left(m,\mathrm{cp},\mathrm{cc},31,10\right)\right)$
 ${\mathrm{id1}}{≔}{1}$ (4)
 > $\mathrm{Threads}\left[\mathrm{ConditionVariable}\right]\left[\mathrm{Wait}\right]\left(\mathrm{cp},m\right)$
 > $\mathrm{Threads}\left[\mathrm{Mutex}\right]\left[\mathrm{Unlock}\right]\left(m\right)$

Start the Consumer threads.  They will each consume 100 jobs and there are 5 threads so we should process 500 jobs.

 > $\mathrm{id2}≔\left[\mathrm{seq}\left(\mathrm{Threads}\left[\mathrm{Create}\right]\left(\mathrm{Consumer}\left(m,\mathrm{cp},\mathrm{cc},100\right)\right),i=1..5\right)\right]$
 ${\mathrm{id2}}{≔}\left[{2}{,}{3}{,}{4}{,}{5}{,}{6}\right]$ (5)

Wait for the Consumer threads to finish.

 > $\mathrm{Threads}\left[\mathrm{Wait}\right]\left(\mathrm{op}\left(\mathrm{id2}\right)\right)$
 > $\mathrm{Threads}\left[\mathrm{Mutex}\right]\left[\mathrm{Lock}\right]\left(m\right)$

 > $e≔\mathrm{false}:$
 > $\mathrm{Threads}\left[\mathrm{ConditionVariable}\right]\left[\mathrm{Signal}\right]\left(\mathrm{cp}\right)$
 > $\mathrm{Threads}\left[\mathrm{Mutex}\right]\left[\mathrm{Unlock}\right]\left(m\right)$
 > $\mathrm{Threads}\left[\mathrm{Wait}\right]\left(\mathrm{id1}\right)$

Check the number of processed jobs.

 > $\mathrm{print}\left(\mathrm{tab}\left["curjob"\right]\right)$
 ${501}$ (6)

Check the results of one job.

 > $\mathrm{print}\left(\mathrm{tab}\left[233\right]\right)$
 ${108811}$ (7)
 > $\mathrm{print}\left(\mathrm{add}\left(i,i=1..2\cdot 233\right)\right)$
 ${108811}$ (8)