ThreadPool.cpp revision d2a7f0d6883a6d3835642e7b282f05ed1c54fe63
1d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten/* 2d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * Copyright (C) 2010 The Android Open Source Project 3d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * 4d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * you may not use this file except in compliance with the License. 6d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * You may obtain a copy of the License at 7d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * 8d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * 10d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * See the License for the specific language governing permissions and 14d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten * limitations under the License. 15d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten */ 16d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 17d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten/* ThreadPool */ 18d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 19d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten#include "sles_allinclusive.h" 20d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 21d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten// Entry point for each worker thread 22d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 23d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic void *ThreadPool_start(void *context) 24d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 25d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ThreadPool *tp = (ThreadPool *) context; 26d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(NULL != tp); 27d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten for (;;) { 28d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten Closure *pClosure = ThreadPool_remove(tp); 29d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // closure is NULL when engine is being destroyed 30d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (NULL == pClosure) 31d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten break; 32d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten void (*handler)(Closure *); 33d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten handler = pClosure->mHandler; 34d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(NULL != handler); 35d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (*handler)(pClosure); 36d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 37d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten return NULL; 38d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 39d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 40d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten#define INITIALIZED_NONE 0 41d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten#define INITIALIZED_MUTEX 1 42d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten#define INITIALIZED_CONDNOTFULL 2 43d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten#define INITIALIZED_CONDNOTEMPTY 4 44d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten#define INITIALIZED_ALL 7 45d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 46d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic void ThreadPool_deinit_internal(ThreadPool *tp, unsigned initialized, unsigned nThreads); 47d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 48d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten// Initialize a ThreadPool 49d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten// maxClosures defaults to CLOSURE_TYPICAL if 0 50d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten// maxThreads defaults to THREAD_TYPICAL if 0 51d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 52d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn KastenSLresult ThreadPool_init(ThreadPool *tp, unsigned maxClosures, unsigned maxThreads) 53d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 54d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(NULL != tp); 55d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten memset(tp, 0, sizeof(ThreadPool)); 56d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mShutdown = SL_BOOLEAN_FALSE; 57d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten unsigned initialized = INITIALIZED_NONE; 58d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten unsigned nThreads = 0; 59d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten SLresult result; 60d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten result = err_to_result(pthread_mutex_init(&tp->mMutex, (const pthread_mutexattr_t *) NULL)); 61d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_RESULT_SUCCESS != result) 62d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten goto fail; 63d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten initialized |= INITIALIZED_MUTEX; 64d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten result = err_to_result(pthread_cond_init(&tp->mCondNotFull, (const pthread_condattr_t *) NULL)); 65d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_RESULT_SUCCESS != result) 66d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten goto fail; 67d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten initialized |= INITIALIZED_CONDNOTFULL; 68d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten result = err_to_result(pthread_cond_init(&tp->mCondNotEmpty, (const pthread_condattr_t *) NULL)); 69d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_RESULT_SUCCESS != result) 70d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten goto fail; 71d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten initialized |= INITIALIZED_CONDNOTEMPTY; 72d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mWaitingNotFull = 0; 73d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mWaitingNotEmpty = 0; 74d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (0 == maxClosures) 75d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten maxClosures = CLOSURE_TYPICAL; 76d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mMaxClosures = maxClosures; 77d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (0 == maxThreads) 78d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten maxThreads = THREAD_TYPICAL; 79d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mMaxThreads = maxThreads; 80d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (CLOSURE_TYPICAL >= maxClosures) { 81d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mClosureArray = tp->mClosureTypical; 82d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } else { 83d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mClosureArray = (Closure **) malloc((maxClosures + 1) * sizeof(Closure *)); 84d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (NULL == tp->mClosureArray) { 85d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten result = SL_RESULT_RESOURCE_ERROR; 86d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten goto fail; 87d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 88d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 89d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mClosureFront = tp->mClosureArray; 90d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mClosureRear = tp->mClosureArray; 91d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (THREAD_TYPICAL >= maxThreads) { 92d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mThreadArray = tp->mThreadTypical; 93d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } else { 94d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mThreadArray = (pthread_t *) malloc(maxThreads * sizeof(pthread_t)); 95d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (NULL == tp->mThreadArray) { 96d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten result = SL_RESULT_RESOURCE_ERROR; 97d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten goto fail; 98d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 99d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 100d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten unsigned i; 101d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten for (i = 0; i < maxThreads; ++i) { 102d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten result = err_to_result(pthread_create(&tp->mThreadArray[i], (const pthread_attr_t *) NULL, ThreadPool_start, tp)); 103d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_RESULT_SUCCESS != result) 104d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten goto fail; 105d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ++nThreads; 106d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 107d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mInitialized = initialized; 108d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten return SL_RESULT_SUCCESS; 109d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenfail: 110d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ThreadPool_deinit_internal(tp, initialized, nThreads); 111d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten return result; 112d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 113d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 114d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic void ThreadPool_deinit_internal(ThreadPool *tp, unsigned initialized, unsigned nThreads) 115d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 116d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(NULL != tp); 117d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // FIXME Cancel all pending operations 118d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Destroy all threads 119d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (0 < nThreads) { 120d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten int ok; 121d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(INITIALIZED_ALL == initialized); 122d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_mutex_lock(&tp->mMutex); 123d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 124d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mShutdown = SL_BOOLEAN_TRUE; 125d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_cond_broadcast(&tp->mCondNotEmpty); 126d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 127d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_cond_broadcast(&tp->mCondNotFull); 128d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 129d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_mutex_unlock(&tp->mMutex); 130d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 131d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten unsigned i; 132d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten for (i = 0; i < nThreads; ++i) { 133d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_join(tp->mThreadArray[i], (void **) NULL); 134d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(ok == 0); 135d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 136d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_mutex_lock(&tp->mMutex); 137d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 138d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == tp->mWaitingNotEmpty); 139d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_mutex_unlock(&tp->mMutex); 140d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 141d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Note that we can't be sure when mWaitingNotFull will drop to zero 142d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 143d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (initialized & INITIALIZED_CONDNOTEMPTY) 144d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (void) pthread_cond_destroy(&tp->mCondNotEmpty); 145d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (initialized & INITIALIZED_CONDNOTFULL) 146d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (void) pthread_cond_destroy(&tp->mCondNotFull); 147d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (initialized & INITIALIZED_MUTEX) 148d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (void) pthread_mutex_destroy(&tp->mMutex); 149d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mInitialized = INITIALIZED_NONE; 150d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (tp->mClosureTypical != tp->mClosureArray && NULL != tp->mClosureArray) { 151d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten free(tp->mClosureArray); 152d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mClosureArray = NULL; 153d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 154d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (tp->mThreadTypical != tp->mThreadArray && NULL != tp->mThreadArray) { 155d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten free(tp->mThreadArray); 156d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mThreadArray = NULL; 157d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 158d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 159d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 160d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenvoid ThreadPool_deinit(ThreadPool *tp) 161d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 162d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ThreadPool_deinit_internal(tp, tp->mInitialized, tp->mMaxThreads); 163d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 164d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 165d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenbool ThreadPool_add(ThreadPool *tp, Closure *closure) 166d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 167d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(NULL != tp); 168d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(NULL != closure); 169d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten int ok; 170d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_mutex_lock(&tp->mMutex); 171d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 172d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten for (;;) { 173d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten Closure **oldRear = tp->mClosureRear; 174d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten Closure **newRear = oldRear; 175d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (++newRear == &tp->mClosureArray[tp->mMaxClosures + 1]) 176d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten newRear = tp->mClosureArray; 177d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (newRear == tp->mClosureFront) { 178d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ++tp->mWaitingNotFull; 179d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_cond_wait(&tp->mCondNotFull, &tp->mMutex); 180d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 181d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (tp->mShutdown) { 182d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 < tp->mWaitingNotFull); 183d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten --tp->mWaitingNotFull; 184d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_mutex_unlock(&tp->mMutex); 185d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 186d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten return false; 187d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 188d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten continue; 189d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 190d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(NULL == *oldRear); 191d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten *oldRear = closure; 192d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (0 < tp->mWaitingNotEmpty) { 193d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten --tp->mWaitingNotEmpty; 194d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_cond_signal(&tp->mCondNotEmpty); 195d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 196d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 197d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten break; 198d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 199d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_mutex_unlock(&tp->mMutex); 200d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 201d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten return true; 202d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 203d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 204d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn KastenClosure *ThreadPool_remove(ThreadPool *tp) 205d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 206d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten Closure *pClosure; 207d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten int ok; 208d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_mutex_lock(&tp->mMutex); 209d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 210d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten for (;;) { 211d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten Closure **oldFront = tp->mClosureFront; 212d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (oldFront == tp->mClosureRear) { 213d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ++tp->mWaitingNotEmpty; 214d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_cond_wait(&tp->mCondNotEmpty, &tp->mMutex); 215d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 216d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (tp->mShutdown) { 217d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 < tp->mWaitingNotEmpty); 218d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten --tp->mWaitingNotEmpty; 219d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten pClosure = NULL; 220d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten break; 221d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 222d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten continue; 223d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 224d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten Closure **newFront = oldFront; 225d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (++newFront == &tp->mClosureArray[tp->mMaxClosures + 1]) 226d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten newFront = tp->mClosureArray; 227d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten pClosure = *oldFront; 228d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten tp->mClosureFront = newFront; 229d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (0 < tp->mWaitingNotFull) { 230d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten --tp->mWaitingNotFull; 231d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_cond_signal(&tp->mCondNotFull); 232d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 233d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 234d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten break; 235d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 236d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten ok = pthread_mutex_unlock(&tp->mMutex); 237d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(0 == ok); 238d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten return pClosure; 239d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 240