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

Reply via email to