### Example (__lxchg -- Exchange Integer Value with Memory)

This example creates five separate threads, each associated with a state. At most two threads can have a State of Eating at the same time. When a thread calls PickUpChopSticks, that function checks the states of the preceding threads to make sure they are not already Eating. If the call to __lxchg is successful, the thread has locked the Lock semaphore and can change its State to Eating. It then calls __lxchg a second time to unlock the semaphore, and returns.

If __lxchg cannot lock the semaphore, that means another thread has it locked. The current thread then suspends itself briefly with:

OS/2 | DosSleep
Windows | Sleep

and tries again. The semaphore is used to ensure that two threads cannot simultaneously change their State to Eating, which would cause a deadlock. (Although the semaphore solves the problem of deadlock, it is not an optimal solution; some threads may never get the semaphore or the State of Eating.)

Note: You must compile this example with the multithread (/Gm) option. The example runs in an infinite loop; press Ctrl-C to end it.

       #pragma strings(readonly)

    #if  (1 == __TOS_OS2__)
          #define   INCL_DOS                              /* For OS/2 */
          #include <os2.h>
          #define SLEEP  DosSleep(1)
    #else
         #include <windows.h>                          /* For Windows */
         #define SLEEP  Sleep(1)
    #endif

       #include <stdlib.h>
       #include <stdio.h>
       #include <builtin.h>

       typedef enum {
          Thinking,
          Eating,
          Hungry
       } States;

       #define UNLOCKED 0
       #define LOCKED   1
       #define NUM_PHILOSOPHERS 5

       static volatile int Lock;
       static States State[NUM_PHILOSOPHERS];
       static const int NameMap[NUM_PHILOSOPHERS] = {0, 1, 2, 3, 4};
       static const char * const Names[NUM_PHILOSOPHERS] = {"Plato",
                                                            "Socrates",
                                                            "Kant",
                                                            "Hegel",
                                                            "Nietsche"};

       void PickUpChopSticks(int Ident);
       void PutDownChopSticks(int Ident);
       void Think(int Ident);
       void Eat(int Ident);
       void _Optlink StartPhilosopher(void *pIdent);

       void _Optlink StartPhilosopher(void *pIdent)
       {
          int Ident = *(int *)pIdent;
          while (1) {
             State[Ident] = Hungry;
             printf("%s hungry.\n", Names[Ident]);
             PickUpChopSticks(Ident);
             Eat(Ident);
             PutDownChopSticks(Ident);
             Think(Ident);
          }
       }

       int main(int argc, char *argv[], char *envp[])
       {
          int           i;
          unsigned long tid;

          for (i = 0; i < NUM_PHILOSOPHERS; i++) {
             tid = _beginthread(StartPhilosopher, NULL, 8192, (void *)&NameMap[i]);
             if (tid == -1) {
                printf("Unable to start %s.\n", Names[i]);
             }
             else {
                printf("%s started with Thread Id = %d.\n", Names[i], tid);
             }
          }
    #if  (1 == __TOS_OS2__)
          DosWaitThread(&tid, DCWW_WAIT);
    #else
          WaitForSingleObject((HANDLE)tid, INFINITE);
    #endif
          return 0;
       }

       void PickUpChopSticks(int Ident)
       {
          while (1) {
             if (State[(Ident + NUM_PHILOSOPHERS - 1) % NUM_PHILOSOPHERS] != Eating &&
                 State[(Ident + 1) % NUM_PHILOSOPHERS] != Eating                    &&
                 !__lxchg(&Lock, LOCKED)) {
                   State[Ident] = Eating;
                   __lxchg(&Lock, UNLOCKED);
                   return;
             }
             else {
                SLEEP;
             }
          }
       }

       void PutDownChopSticks(int Ident)
       {
          State[Ident] = Thinking;
       }

       void Eat(int Ident)
       {
          printf("%s eating.\n", Names[Ident]);
          SLEEP;
       }

       void Think(int Ident)
       {
          printf("%s thinking.\n", Names[Ident]);
          SLEEP;

       /****************************************************************************
          The output should be similar to :

          Plato started with Thread Id = 2.
          Socrates started with Thread Id = 3.
          Kant started with Thread Id = 4.
          Hegel started with Thread Id = 5.
          Nietsche started with Thread Id = 6.
          Plato hungry.
          Plato eating.
          Socrates hungry.
          Kant hungry.
          Kant eating.
          Hegel hungry.
          Nietsche hungry.
          Kant thinking.
          Plato thinking.
          Plato hungry.
          Plato eating.
          Kant hungry.
          Kant eating.
             :

       ****************************************************************************/
    }