Example (__cxchg -- Exchange Character 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 __cxchg is successful, the thread has locked the Lock semaphore and can change its State to Eating. It then calls __cxchg a second time to unlock the semaphore, and returns.

If __cxchg cannot lock the semaphore, another thread has it locked. The current thread then suspends itself briefly with 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. (Note that 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 unsigned char 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                    &&
             !__cxchg(&Lock, LOCKED)) {
               State[Ident] = Eating;
               __cxchg(&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.
         :
   **************************************************************************/
}