Hi Takashi Yano, > The result is as follows (submitted as v4 patch). > > int > pthread::once (pthread_once_t *once_control, void (*init_routine) (void)) > { > /* Sign bit of once_control->state is used as done flag. > Similary, the next significant bit is used as destroyed flag. */ > const int done = INT_MIN; /* 0b1000000000000000 */ > const int destroyed = INT_MIN >> 1; /* 0b1100000000000000 */ > if (once_control->state & done) > return 0; > > /* The type of &once_control->state is int *, which is compatible with > LONG * (the type of the pointer argument of InterlockedXxx()). */ > if ((InterlockedIncrement (&once_control->state) & done) == 0) > { > pthread_mutex_lock (&once_control->mutex); > if (!(once_control->state & done)) > { > init_routine (); > InterlockedOr (&once_control->state, done); > } > pthread_mutex_unlock (&once_control->mutex); > } > InterlockedDecrement (&once_control->state); > if (InterlockedCompareExchange (&once_control->state, > destroyed, done) == done) > pthread_mutex_destroy (&once_control->mutex); > return 0; > } > ... > I believe both codes are equivalent. Could you please check?
Yes, they are equivalent. This code is free of race conditions. (Let's hope I am not making a mistake again.) For legibility I would write the constant values as bit masks: 0x80000000 0xc0000000 and - following the habit that constant integers should have names in upper case - I would rename done → DONE destroyed → DESTROYED Bruno -- Problem reports: https://cygwin.com/problems.html FAQ: https://cygwin.com/faq/ Documentation: https://cygwin.com/docs.html Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple