src/thread/generic/SDL_syscond.c
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
equal deleted inserted replaced
1667:1fddae038bc8 1668:4da1ee79c9af
    38     SDL_sem *wait_done;
    38     SDL_sem *wait_done;
    39 };
    39 };
    40 
    40 
    41 /* Create a condition variable */
    41 /* Create a condition variable */
    42 SDL_cond *
    42 SDL_cond *
    43 SDL_CreateCond (void)
    43 SDL_CreateCond(void)
    44 {
    44 {
    45     SDL_cond *cond;
    45     SDL_cond *cond;
    46 
    46 
    47     cond = (SDL_cond *) SDL_malloc (sizeof (SDL_cond));
    47     cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
    48     if (cond) {
    48     if (cond) {
    49         cond->lock = SDL_CreateMutex ();
    49         cond->lock = SDL_CreateMutex();
    50         cond->wait_sem = SDL_CreateSemaphore (0);
    50         cond->wait_sem = SDL_CreateSemaphore(0);
    51         cond->wait_done = SDL_CreateSemaphore (0);
    51         cond->wait_done = SDL_CreateSemaphore(0);
    52         cond->waiting = cond->signals = 0;
    52         cond->waiting = cond->signals = 0;
    53         if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
    53         if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
    54             SDL_DestroyCond (cond);
    54             SDL_DestroyCond(cond);
    55             cond = NULL;
    55             cond = NULL;
    56         }
    56         }
    57     } else {
    57     } else {
    58         SDL_OutOfMemory ();
    58         SDL_OutOfMemory();
    59     }
    59     }
    60     return (cond);
    60     return (cond);
    61 }
    61 }
    62 
    62 
    63 /* Destroy a condition variable */
    63 /* Destroy a condition variable */
    64 void
    64 void
    65 SDL_DestroyCond (SDL_cond * cond)
    65 SDL_DestroyCond(SDL_cond * cond)
    66 {
    66 {
    67     if (cond) {
    67     if (cond) {
    68         if (cond->wait_sem) {
    68         if (cond->wait_sem) {
    69             SDL_DestroySemaphore (cond->wait_sem);
    69             SDL_DestroySemaphore(cond->wait_sem);
    70         }
    70         }
    71         if (cond->wait_done) {
    71         if (cond->wait_done) {
    72             SDL_DestroySemaphore (cond->wait_done);
    72             SDL_DestroySemaphore(cond->wait_done);
    73         }
    73         }
    74         if (cond->lock) {
    74         if (cond->lock) {
    75             SDL_DestroyMutex (cond->lock);
    75             SDL_DestroyMutex(cond->lock);
    76         }
    76         }
    77         SDL_free (cond);
    77         SDL_free(cond);
    78     }
    78     }
    79 }
    79 }
    80 
    80 
    81 /* Restart one of the threads that are waiting on the condition variable */
    81 /* Restart one of the threads that are waiting on the condition variable */
    82 int
    82 int
    83 SDL_CondSignal (SDL_cond * cond)
    83 SDL_CondSignal(SDL_cond * cond)
    84 {
    84 {
    85     if (!cond) {
    85     if (!cond) {
    86         SDL_SetError ("Passed a NULL condition variable");
    86         SDL_SetError("Passed a NULL condition variable");
    87         return -1;
    87         return -1;
    88     }
    88     }
    89 
    89 
    90     /* If there are waiting threads not already signalled, then
    90     /* If there are waiting threads not already signalled, then
    91        signal the condition and wait for the thread to respond.
    91        signal the condition and wait for the thread to respond.
    92      */
    92      */
    93     SDL_LockMutex (cond->lock);
    93     SDL_LockMutex(cond->lock);
    94     if (cond->waiting > cond->signals) {
    94     if (cond->waiting > cond->signals) {
    95         ++cond->signals;
    95         ++cond->signals;
    96         SDL_SemPost (cond->wait_sem);
    96         SDL_SemPost(cond->wait_sem);
    97         SDL_UnlockMutex (cond->lock);
    97         SDL_UnlockMutex(cond->lock);
    98         SDL_SemWait (cond->wait_done);
    98         SDL_SemWait(cond->wait_done);
    99     } else {
    99     } else {
   100         SDL_UnlockMutex (cond->lock);
   100         SDL_UnlockMutex(cond->lock);
   101     }
   101     }
   102 
   102 
   103     return 0;
   103     return 0;
   104 }
   104 }
   105 
   105 
   106 /* Restart all threads that are waiting on the condition variable */
   106 /* Restart all threads that are waiting on the condition variable */
   107 int
   107 int
   108 SDL_CondBroadcast (SDL_cond * cond)
   108 SDL_CondBroadcast(SDL_cond * cond)
   109 {
   109 {
   110     if (!cond) {
   110     if (!cond) {
   111         SDL_SetError ("Passed a NULL condition variable");
   111         SDL_SetError("Passed a NULL condition variable");
   112         return -1;
   112         return -1;
   113     }
   113     }
   114 
   114 
   115     /* If there are waiting threads not already signalled, then
   115     /* If there are waiting threads not already signalled, then
   116        signal the condition and wait for the thread to respond.
   116        signal the condition and wait for the thread to respond.
   117      */
   117      */
   118     SDL_LockMutex (cond->lock);
   118     SDL_LockMutex(cond->lock);
   119     if (cond->waiting > cond->signals) {
   119     if (cond->waiting > cond->signals) {
   120         int i, num_waiting;
   120         int i, num_waiting;
   121 
   121 
   122         num_waiting = (cond->waiting - cond->signals);
   122         num_waiting = (cond->waiting - cond->signals);
   123         cond->signals = cond->waiting;
   123         cond->signals = cond->waiting;
   124         for (i = 0; i < num_waiting; ++i) {
   124         for (i = 0; i < num_waiting; ++i) {
   125             SDL_SemPost (cond->wait_sem);
   125             SDL_SemPost(cond->wait_sem);
   126         }
   126         }
   127         /* Now all released threads are blocked here, waiting for us.
   127         /* Now all released threads are blocked here, waiting for us.
   128            Collect them all (and win fabulous prizes!) :-)
   128            Collect them all (and win fabulous prizes!) :-)
   129          */
   129          */
   130         SDL_UnlockMutex (cond->lock);
   130         SDL_UnlockMutex(cond->lock);
   131         for (i = 0; i < num_waiting; ++i) {
   131         for (i = 0; i < num_waiting; ++i) {
   132             SDL_SemWait (cond->wait_done);
   132             SDL_SemWait(cond->wait_done);
   133         }
   133         }
   134     } else {
   134     } else {
   135         SDL_UnlockMutex (cond->lock);
   135         SDL_UnlockMutex(cond->lock);
   136     }
   136     }
   137 
   137 
   138     return 0;
   138     return 0;
   139 }
   139 }
   140 
   140 
   157 	condition = true;
   157 	condition = true;
   158 	...
   158 	...
   159 	SDL_UnlockMutex(lock);
   159 	SDL_UnlockMutex(lock);
   160  */
   160  */
   161 int
   161 int
   162 SDL_CondWaitTimeout (SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
   162 SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
   163 {
   163 {
   164     int retval;
   164     int retval;
   165 
   165 
   166     if (!cond) {
   166     if (!cond) {
   167         SDL_SetError ("Passed a NULL condition variable");
   167         SDL_SetError("Passed a NULL condition variable");
   168         return -1;
   168         return -1;
   169     }
   169     }
   170 
   170 
   171     /* Obtain the protection mutex, and increment the number of waiters.
   171     /* Obtain the protection mutex, and increment the number of waiters.
   172        This allows the signal mechanism to only perform a signal if there
   172        This allows the signal mechanism to only perform a signal if there
   173        are waiting threads.
   173        are waiting threads.
   174      */
   174      */
   175     SDL_LockMutex (cond->lock);
   175     SDL_LockMutex(cond->lock);
   176     ++cond->waiting;
   176     ++cond->waiting;
   177     SDL_UnlockMutex (cond->lock);
   177     SDL_UnlockMutex(cond->lock);
   178 
   178 
   179     /* Unlock the mutex, as is required by condition variable semantics */
   179     /* Unlock the mutex, as is required by condition variable semantics */
   180     SDL_UnlockMutex (mutex);
   180     SDL_UnlockMutex(mutex);
   181 
   181 
   182     /* Wait for a signal */
   182     /* Wait for a signal */
   183     if (ms == SDL_MUTEX_MAXWAIT) {
   183     if (ms == SDL_MUTEX_MAXWAIT) {
   184         retval = SDL_SemWait (cond->wait_sem);
   184         retval = SDL_SemWait(cond->wait_sem);
   185     } else {
   185     } else {
   186         retval = SDL_SemWaitTimeout (cond->wait_sem, ms);
   186         retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
   187     }
   187     }
   188 
   188 
   189     /* Let the signaler know we have completed the wait, otherwise
   189     /* Let the signaler know we have completed the wait, otherwise
   190        the signaler can race ahead and get the condition semaphore
   190        the signaler can race ahead and get the condition semaphore
   191        if we are stopped between the mutex unlock and semaphore wait,
   191        if we are stopped between the mutex unlock and semaphore wait,
   192        giving a deadlock.  See the following URL for details:
   192        giving a deadlock.  See the following URL for details:
   193        http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
   193        http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
   194      */
   194      */
   195     SDL_LockMutex (cond->lock);
   195     SDL_LockMutex(cond->lock);
   196     if (cond->signals > 0) {
   196     if (cond->signals > 0) {
   197         /* If we timed out, we need to eat a condition signal */
   197         /* If we timed out, we need to eat a condition signal */
   198         if (retval > 0) {
   198         if (retval > 0) {
   199             SDL_SemWait (cond->wait_sem);
   199             SDL_SemWait(cond->wait_sem);
   200         }
   200         }
   201         /* We always notify the signal thread that we are done */
   201         /* We always notify the signal thread that we are done */
   202         SDL_SemPost (cond->wait_done);
   202         SDL_SemPost(cond->wait_done);
   203 
   203 
   204         /* Signal handshake complete */
   204         /* Signal handshake complete */
   205         --cond->signals;
   205         --cond->signals;
   206     }
   206     }
   207     --cond->waiting;
   207     --cond->waiting;
   208     SDL_UnlockMutex (cond->lock);
   208     SDL_UnlockMutex(cond->lock);
   209 
   209 
   210     /* Lock the mutex, as is required by condition variable semantics */
   210     /* Lock the mutex, as is required by condition variable semantics */
   211     SDL_LockMutex (mutex);
   211     SDL_LockMutex(mutex);
   212 
   212 
   213     return retval;
   213     return retval;
   214 }
   214 }
   215 
   215 
   216 /* Wait on the condition variable forever */
   216 /* Wait on the condition variable forever */
   217 int
   217 int
   218 SDL_CondWait (SDL_cond * cond, SDL_mutex * mutex)
   218 SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
   219 {
   219 {
   220     return SDL_CondWaitTimeout (cond, mutex, SDL_MUTEX_MAXWAIT);
   220     return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
   221 }
   221 }
   222 
   222 
   223 /* vi: set ts=4 sw=4 expandtab: */
   223 /* vi: set ts=4 sw=4 expandtab: */