| /* | |
| * 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); |