/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** \file ThreadPool.h ThreadPool interface */ /** Kind of closure */ typedef enum { CLOSURE_KIND_PPI, // void *, void *, int CLOSURE_KIND_PPII, // void *, void *, int, int CLOSURE_KIND_PIIPP // void *, int, int, void *, void * } ClosureKind; /** Closure handlers */ typedef void (*ClosureHandler_generic)(void *p1, void *p2, void *p3, int i1, int i2); typedef void (*ClosureHandler_ppi) (void *p1, void *p2, int i1); typedef void (*ClosureHandler_ppii) (void *p1, void *p2, int i1, int i2); typedef void (*ClosureHandler_piipp) (void *p1, int i1, int i2, void *p2, void *p3); /** \brief Closure represents a deferred computation */ typedef struct { union { ClosureHandler_ppi mHandler_ppi; ClosureHandler_ppii mHandler_ppii; ClosureHandler_piipp mHandler_piipp; } mHandler; ClosureKind mKind; void *mContext1; void *mContext2; void *mContext3; int mParameter1; int mParameter2; } Closure; /** \brief ThreadPool manages a pool of worker threads that execute Closures */ typedef struct { unsigned mInitialized; ///< Indicates which of the following 3 fields are initialized pthread_mutex_t mMutex; pthread_cond_t mCondNotFull; ///< Signalled when a client thread could be unblocked pthread_cond_t mCondNotEmpty; ///< Signalled when a worker thread could be unblocked SLboolean mShutdown; ///< Whether shutdown of thread pool has been requested unsigned mWaitingNotFull; ///< Number of client threads waiting to enqueue unsigned mWaitingNotEmpty; ///< Number of worker threads waiting to dequeue unsigned mMaxClosures; ///< Number of slots in circular buffer for closures, not counting spare unsigned mMaxThreads; ///< Number of worker threads Closure **mClosureArray; ///< The circular buffer of closures Closure **mClosureFront, **mClosureRear; /// Saves a malloc in the typical case #define CLOSURE_TYPICAL 15 Closure *mClosureTypical[CLOSURE_TYPICAL+1]; pthread_t *mThreadArray; ///< The worker threads #ifdef ANDROID // Note: if you set THREAD_TYPICAL to a non-zero value because you // want to use asynchronous callbacks, be aware that any value greater // than 1 can result in out-of-order callbacks on a given player, in the // current implementation. Thus you should probably configure 1 total or // change the implementation so that it uses at most 1 thread per player. #if defined(USE_ASYNCHRONOUS_PLAY_CALLBACK) || \ defined(USE_ASYNCHRONOUS_STREAMCBEVENT_PROPERTYCHANGE_CALLBACK) #define THREAD_TYPICAL 1 #else #define THREAD_TYPICAL 0 #endif #else // !ANDROID #define THREAD_TYPICAL 4 #endif pthread_t mThreadTypical[THREAD_TYPICAL]; } ThreadPool; extern SLresult ThreadPool_init(ThreadPool *tp, unsigned maxClosures, unsigned maxThreads); extern void ThreadPool_deinit(ThreadPool *tp); extern SLresult ThreadPool_add(ThreadPool *tp, ClosureKind kind, ClosureHandler_generic, void *cntxt1, void *cntxt2, void *cntxt3, int param1, int param2); extern Closure *ThreadPool_remove(ThreadPool *tp); extern SLresult ThreadPool_add_ppi(ThreadPool *tp, ClosureHandler_ppi handler, void *cntxt1, void *cntxt2, int param1); extern SLresult ThreadPool_add_ppii(ThreadPool *tp, ClosureHandler_ppii handler, void *cntxt1, void *cntxt2, int param1, int param2); extern SLresult ThreadPool_add_piipp(ThreadPool *tp, ClosureHandler_piipp handler, void *cntxt1, int param1, int param2, void *cntxt2, void *cntxt3);