"Fossies" - the Fresh Open Source Software Archive

Member "apr-1.7.0/locks/win32/thread_cond.c" (21 Mar 2019, 5578 Bytes) of package /linux/www/apr-1.7.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "thread_cond.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.6.5_vs_1.7.0.

    1 /* Licensed to the Apache Software Foundation (ASF) under one or more
    2  * contributor license agreements.  See the NOTICE file distributed with
    3  * this work for additional information regarding copyright ownership.
    4  * The ASF licenses this file to You under the Apache License, Version 2.0
    5  * (the "License"); you may not use this file except in compliance with
    6  * the License.  You may obtain a copy of the License at
    7  *
    8  *     http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 #include "apr.h"
   18 #include "apr_private.h"
   19 #include "apr_general.h"
   20 #include "apr_strings.h"
   21 #include "apr_arch_thread_mutex.h"
   22 #include "apr_arch_thread_cond.h"
   23 #include "apr_portable.h"
   24 
   25 #include <limits.h>
   26 
   27 static apr_status_t thread_cond_cleanup(void *data)
   28 {
   29     apr_thread_cond_t *cond = data;
   30     CloseHandle(cond->semaphore);
   31     DeleteCriticalSection(&cond->csection);
   32     return APR_SUCCESS;
   33 }
   34 
   35 APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
   36                                                  apr_pool_t *pool)
   37 {
   38     apr_thread_cond_t *cv;
   39 
   40     cv = apr_pcalloc(pool, sizeof(**cond));
   41     if (cv == NULL) {
   42         return APR_ENOMEM;
   43     }
   44 
   45     cv->semaphore = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
   46     if (cv->semaphore == NULL) {
   47         return apr_get_os_error();
   48     }
   49 
   50     *cond = cv;
   51     cv->pool = pool;
   52     InitializeCriticalSection(&cv->csection);
   53     apr_pool_cleanup_register(cv->pool, cv, thread_cond_cleanup,
   54                               apr_pool_cleanup_null);
   55 
   56     return APR_SUCCESS;
   57 }
   58 
   59 APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
   60 {
   61     return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup);
   62 }
   63 
   64 static APR_INLINE apr_status_t thread_cond_timedwait(apr_thread_cond_t *cond,
   65                                                      apr_thread_mutex_t *mutex,
   66                                                      apr_interval_time_t timeout)
   67 {
   68     DWORD res;
   69     apr_status_t rv;
   70     unsigned int wake = 0;
   71     unsigned long generation;
   72     DWORD timeout_ms = 0;
   73 
   74     EnterCriticalSection(&cond->csection);
   75     cond->num_waiting++;
   76     generation = cond->generation;
   77     LeaveCriticalSection(&cond->csection);
   78 
   79     apr_thread_mutex_unlock(mutex);
   80 
   81     do {
   82         apr_interval_time_t t = timeout;
   83 
   84         do {
   85             if (t < 0) {
   86                 timeout_ms = INFINITE;
   87             }
   88             else if (t > 0) {
   89                 /* Given timeout is 64bit usecs whereas Windows timeouts are
   90                  * 32bit msecs and below INFINITE (2^32 - 1), so we may need
   91                  * multiple timed out waits...
   92                  */
   93                 if (t > apr_time_from_msec(INFINITE - 1)) {
   94                     timeout_ms = INFINITE - 1;
   95                     t -= apr_time_from_msec(INFINITE - 1);
   96                 }
   97                 else {
   98                     timeout_ms = (DWORD)apr_time_as_msec(t);
   99                     t = 0;
  100                 }
  101             }
  102             res = WaitForSingleObject(cond->semaphore, timeout_ms);
  103         } while (res == WAIT_TIMEOUT && t > 0);
  104 
  105         EnterCriticalSection(&cond->csection);
  106 
  107         if (cond->num_wake) {
  108             if (cond->generation != generation) {
  109                 cond->num_wake--;
  110                 cond->num_waiting--;
  111                 rv = APR_SUCCESS;
  112                 break;
  113             } else {
  114                 wake = 1;
  115             }
  116         }
  117         else if (res != WAIT_OBJECT_0) {
  118             cond->num_waiting--;
  119             rv = APR_TIMEUP;
  120             break;
  121         }
  122 
  123         LeaveCriticalSection(&cond->csection);
  124 
  125         if (wake) {
  126             wake = 0;
  127             ReleaseSemaphore(cond->semaphore, 1, NULL);
  128         }
  129     } while (1);
  130 
  131     LeaveCriticalSection(&cond->csection);
  132     apr_thread_mutex_lock(mutex);
  133 
  134     return rv;
  135 }
  136 
  137 APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
  138                                                apr_thread_mutex_t *mutex)
  139 {
  140     return thread_cond_timedwait(cond, mutex, (apr_interval_time_t)-1);
  141 }
  142 
  143 APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
  144                                                     apr_thread_mutex_t *mutex,
  145                                                     apr_interval_time_t timeout)
  146 {
  147     return thread_cond_timedwait(cond, mutex, timeout);
  148 }
  149 
  150 APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
  151 {
  152     unsigned int wake = 0;
  153 
  154     EnterCriticalSection(&cond->csection);
  155     if (cond->num_waiting > cond->num_wake) {
  156         wake = 1;
  157         cond->num_wake++;
  158         cond->generation++;
  159     }
  160     LeaveCriticalSection(&cond->csection);
  161 
  162     if (wake) {
  163         ReleaseSemaphore(cond->semaphore, 1, NULL);
  164     }
  165 
  166     return APR_SUCCESS;
  167 }
  168 
  169 APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
  170 {
  171     unsigned long num_wake = 0;
  172 
  173     EnterCriticalSection(&cond->csection);
  174     if (cond->num_waiting > cond->num_wake) {
  175         num_wake = cond->num_waiting - cond->num_wake;
  176         cond->num_wake = cond->num_waiting;
  177         cond->generation++;
  178     }
  179     LeaveCriticalSection(&cond->csection);
  180 
  181     if (num_wake) {
  182         ReleaseSemaphore(cond->semaphore, num_wake, NULL);
  183     }
  184 
  185     return APR_SUCCESS;
  186 }
  187 
  188 APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)