(file) Return to once.c CVS log (file) (dir) Up to [OMI] / omi / pal

 1 krisbash 1.1 #include "once.h"
 2              #include "atomic.h"
 3              #include "lock.h"
 4              
 5              int __Once_Invoke(
 6                  _Inout_ Once* self,
 7                  _In_ OnceWorkerFunction func,
 8                  _In_ void* data)
 9              {
10                  volatile ptrdiff_t *state = (volatile ptrdiff_t*)&self->value;
11                  ptrdiff_t key = (ptrdiff_t)self;
12                  ptrdiff_t swapState;
13                  ptrdiff_t oldState;
14              
15              start:
16                  swapState = Atomic_CompareAndSwap(
17                      state,
18                      ONCE_STATE_NOTINVOKEDYET,
19                      ONCE_STATE_INVOKING);
20              
21                  if (swapState == ONCE_STATE_NOTINVOKEDYET)
22 krisbash 1.1     {
23                      /* This thread changed state to ONCE_STATE_INVOKING. */
24                      void* value;
25                      int result = (*func)(data, &value);
26                      *state = (result == 0) ? (ptrdiff_t)value : ONCE_STATE_NOTINVOKEDYET;
27                          
28                      CondLock_Broadcast(key);
29                      return result;
30                  }
31              
32                  for(;;)
33                  {
34                      oldState = *state;
35                      if (oldState == ONCE_STATE_INVOKING)
36                          CondLock_Wait(
37                                  key,
38                                  state,
39                                  ONCE_STATE_INVOKING,
40                                  CONDLOCK_DEFAULT_SPINCOUNT);
41                      else if (oldState == ONCE_STATE_NOTINVOKEDYET)
42                          goto start;
43 krisbash 1.1         else return 0;
44                  }
45              }

ViewCVS 0.9.2