Signal - Maple Help
For the best experience, we recommend viewing online help using Google Chrome or Microsoft Edge.

# Online Help

###### All Products    Maple    MapleSim

Threads[ConditionVariable]

 Signal
 start a thread waiting on a condition variable

 Calling Sequence Signal( condId )

Parameters

 condId - (integer) the condition variable identifier

Description

 • The Signal command wakes up one thread that is waiting on the condition variable identified by condId.  The Signal command does not guarantee which thread will be started.
 • The Signal command does not require the calling thread to hold a lock on the mutex that was used when the waiting threads called Wait.  However, holding the lock while calling Signal allows for a greater level of control over the scheduling of the signaled thread.
 • If no threads are waiting on the condition variable then nothing happens. Any threads calling Wait after the signal wait as normal.
 • 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}}_{\mathrm{Mutex}}}_{\mathrm{Create}}\left(\right)$
 ${m}{≔}{2}$ (1)
 > $\mathrm{cc}≔{{\mathrm{Threads}}_{\mathrm{ConditionVariable}}}_{\mathrm{Create}}\left(\right)$
 ${\mathrm{cc}}{≔}{1}$ (2)
 > $\mathrm{cp}≔{{\mathrm{Threads}}_{\mathrm{ConditionVariable}}}_{\mathrm{Create}}\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}}_{\mathrm{Mutex}}}_{\mathrm{Lock}}\left(m\right)$
 > $\mathrm{id1}≔{\mathrm{Threads}}_{\mathrm{Create}}\left(\mathrm{Producer}\left(m,\mathrm{cp},\mathrm{cc},31,10\right)\right)$
 ${\mathrm{id1}}{≔}{1}$ (4)
 > ${{\mathrm{Threads}}_{\mathrm{ConditionVariable}}}_{\mathrm{Wait}}\left(\mathrm{cp},m\right)$
 > ${{\mathrm{Threads}}_{\mathrm{Mutex}}}_{\mathrm{Unlock}}\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}}_{\mathrm{Create}}\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}}_{\mathrm{Wait}}\left(\mathrm{op}\left(\mathrm{id2}\right)\right)$
 > ${{\mathrm{Threads}}_{\mathrm{Mutex}}}_{\mathrm{Lock}}\left(m\right)$

Shutdown the Producer thread.

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

Check the number of processed jobs.

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

Check the results of one job.

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