MutexLock

Acquires a mutex

Syntax
   Declare Sub MutexLock ( ByVal id As Any Ptr )

Usage
   MutexLock( id )

Parameters
   id
      The Any Ptr handle of the mutex to be locked.

Description
   Mutexlock halts any other threads using a mutex "handle", generated by 
   MutexCreate, until the handle is unlocked with MutexUnlock.
   Such a halted thread has its execution suspended and does not consume 
   any CPU time until the mutex is unlocked.

   See MutexCreate for more general information on mutexes.

Example
   See also the examples in MutexCreate and also ThreadCreate.

   'Example of mutual exclusion for synchronization between 2 threads
   'by using 2 Mutexes only (by self lock and mutual unlock):
   'The Producer works one time, then the Consumer works one time.
   '
   'Principle of synchronisation by mutual exclusion
   '(initial condition: mut#A and mut#B locked)
   '
   '          Thread#A              XORs              Thread#B
   'Do_something#A_with_exclusion          MutexLock(mut#A)
   'MutexUnlock(mut#A)                       Do_something#B_with_exclusion
   '.....                                  MutexUnlock(mut#B)
   'MutexLock(mut#B)                       .....

   '----------------------------------------------------------------------

   Dim Shared produced As Any Ptr
   Dim Shared consumed As Any Ptr
   Dim consumer_id As Any Ptr
   Dim producer_id As Any Ptr

   Sub consumer ( ByVal param As Any Ptr )
      For i As Integer = 0 To 9
         MutexLock produced
         Print , ",consumer gets:" ; i
         MutexUnlock consumed
         Sleep 5, 1
      Next i
   End Sub

   Sub producer ( ByVal param As Any Ptr )
      For i As Integer = 0 To 9
         Print "Producer puts:" ; i;
         MutexUnlock produced
         MutexLock consumed
      Sleep 5, 1
   Next i
   End Sub

   produced = MutexCreate
   consumed = MutexCreate
   If ( produced = 0 ) Or ( consumed = 0 ) Then
      Print "Error creating mutexes! Exiting..."
      Sleep
      End
   End If

   MutexLock produced
   MutexLock consumed

   consumer_id = ThreadCreate ( @ consumer )
   producer_id = ThreadCreate ( @ producer )
   If ( producer_id = 0 ) Or ( consumer_id = 0 ) Then
      Print "Error creating threads! Exiting..."
      Sleep
      End
   End If

   ThreadWait consumer_id
   ThreadWait producer_id

   MutexDestroy consumed
   MutexDestroy produced

   Sleep

   ' 'Threadcreate' launches one time the user-defined Sub in a separate execution thread
   '    (which runs simultaneously with the rest of the main code).
   ' If you want obtain a periodically display from the thread,
   '    you must put (into the thread) a [Do...Loop] block with a 'Sleep x, 1' to adjust the display period
   '    and a flag to exit the loop (and terminate the thread).
   '
   ' Warning:
   ' - Each thread has not its own memory of cursor position, so for that and other reasons, it is mandatory
   '      to apply an exclusion between displaying from the main code (main thread) and displaying from the user thread,
   '      by using a 'Mutex' ([Mutexlock...Mutexunlock] block).
   '   At beginning of each display block both into main thread and user thread,
   '      the initial cursor position must also be re-initialized.
   ' - The input keywords (like keyboard, mouse) cannot be safely run when the screen is locked,
   '      therefore a such keyword must be outside of any [Screenlock...Screenunlock] block (outside this block in its own thread,
   '      and protected of block of another thread by a 'Mutex').
   '
   ' See below a rustic program, but showing all these constraints:

   Dim Shared As Any Ptr sync   '' pointer to Mutex
   Dim Shared As Byte quit = 0  '' flag to end user thread
   Dim As Any Ptr handle        '' pointer to thread handle

   Sub ProcedureThread (ByVal param As Any Ptr)  '' param not used in thread body
      Do
         MutexLock(sync)       '' Mutex for exclusion of displaying
            ScreenLock        '' keyword after Mutexlock
               Locate 1, 70  '' re-initialize cursor position
               Print Date
               Locate , 71
               Print Time;
            ScreenUnlock      '' keyword before Mutexunlock
         MutexUnlock(sync)     '' end exclusion
         Sleep 100, 1          '' ajust display period
      Loop Until quit <> 0      '' test for exit thread
   End Sub

   Screen 12
   Locate 1, 62
   Print "Date:"
   Locate , 62
   Print "Time:";
   Locate 15, 20
   Print "Mouse (position):"
   Locate , 20
   Print "Mouse (buttons) :";
   Locate 30, 2
   Print "<any_key> or <click on window close button>: exit";

   sync = MutexCreate                          '' create Mutex (before Threadcreate)
   handle = ThreadCreate(@ProcedureThread, 0)  '' launch thread

   Dim As String s
   Do
      MutexLock(sync)                     '' Mutex for exclusion of displaying
         Dim As Long x, y, b
         GetMouse x, y , , b             '' keyword outside [Screenlock...Screenunlock] and protected by Mutex
         ScreenLock                      '' keyword after Mutexlock
            Locate 15, 37               '' re-initialize cursor position
            Print Using "######"; x; y
            Locate , 43
            Print Using "##"; b;
         ScreenUnlock                    '' Keyword before Mutexunlock
         s = Inkey                       '' keyword outside [Screenlock...Screenunlock] and protected by Mutex
      MutexUnlock(sync)                   '' end exclusion
      Sleep 10, 1                         '' ajust display period
   Loop Until s <> ""
    
   quit = Not quit     '' order thread end
   ThreadWait(handle)  '' wait for thread end
   MutexDestroy(sync)  '' free Mutex

Dialect Differences
   * Threading is not allowed in the -lang qb dialect.

Platform Differences
   * The DOS version of FreeBASIC does not allow for threads, as the OS 
     does not support them.
   * In Linux the threads are always started in the order they are 
     created, this can't be assumed in Win32. It's an OS, not a FreeBASIC 
     issue. 

Differences from QB
   * New to FreeBASIC

See also
   * MutexCreate
   * MutexDestroy
   * MutexUnlock
   * ThreadCreate
   * ThreadWait

