| #ifndef _RAR_THREADPOOL_ |
| #define _RAR_THREADPOOL_ |
| |
| namespace third_party_unrar { |
| |
| #ifndef RAR_SMP |
| const uint MaxPoolThreads=1; // For single threaded version. |
| #else |
| const uint MaxPoolThreads=32; |
| |
| |
| #ifdef _UNIX |
| #include <pthread.h> |
| #include <semaphore.h> |
| #endif |
| |
| // Undefine for debugging. |
| #define USE_THREADS |
| |
| #ifdef _UNIX |
| #define NATIVE_THREAD_TYPE void* |
| typedef void* (*NATIVE_THREAD_PTR)(void *Data); |
| typedef pthread_t THREAD_HANDLE; |
| typedef pthread_mutex_t CRITSECT_HANDLE; |
| #else |
| #define NATIVE_THREAD_TYPE DWORD WINAPI |
| typedef DWORD (WINAPI *NATIVE_THREAD_PTR)(void *Data); |
| typedef HANDLE THREAD_HANDLE; |
| typedef CRITICAL_SECTION CRITSECT_HANDLE; |
| #endif |
| |
| typedef void (*PTHREAD_PROC)(void *Data); |
| #define THREAD_PROC(fn) void fn(void *Data) |
| |
| uint GetNumberOfCPU(); |
| uint GetNumberOfThreads(); |
| |
| |
| class ThreadPool |
| { |
| private: |
| struct QueueEntry |
| { |
| PTHREAD_PROC Proc; |
| void *Param; |
| }; |
| |
| void CreateThreads(); |
| static NATIVE_THREAD_TYPE PoolThread(void *Param); |
| void PoolThreadLoop(); |
| bool GetQueuedTask(QueueEntry *Task); |
| |
| // Number of threads in the pool. Must not exceed MaxPoolThreads. |
| uint MaxAllowedThreads; |
| THREAD_HANDLE ThreadHandles[MaxPoolThreads]; |
| |
| // Number of actually created threads. |
| uint ThreadsCreatedCount; |
| |
| uint ActiveThreads; |
| |
| QueueEntry TaskQueue[MaxPoolThreads]; |
| uint QueueTop; |
| uint QueueBottom; |
| |
| bool Closing; // Set true to quit all threads. |
| |
| #ifdef _WIN_ALL |
| // Semaphore counting number of tasks stored in queue. |
| HANDLE QueuedTasksCnt; |
| |
| // Event signalling if no active tasks are performing now. |
| HANDLE NoneActive; |
| |
| #elif defined(_UNIX) |
| // Semaphores seem to be slower than conditional variables in pthreads, |
| // so we use the conditional variable to count tasks stored in queue. |
| uint QueuedTasksCnt; |
| pthread_cond_t QueuedTasksCntCond; |
| pthread_mutex_t QueuedTasksCntMutex; |
| |
| bool AnyActive; // Active tasks present flag. |
| pthread_cond_t AnyActiveCond; |
| pthread_mutex_t AnyActiveMutex; |
| #endif |
| |
| // Pool critical section. We use the single section for all branches |
| // to avoid deadlocks, when thread1 has section1 and wants section2 |
| // and thread2 has section2 and wants section1. |
| CRITSECT_HANDLE CritSection; |
| public: |
| ThreadPool(uint MaxThreads); |
| ~ThreadPool(); |
| void AddTask(PTHREAD_PROC Proc,void *Data); |
| void WaitDone(); |
| |
| #ifdef _WIN_ALL |
| static int ThreadPriority; |
| static void SetPriority(int Priority) {ThreadPriority=Priority;} |
| #endif |
| }; |
| |
| ThreadPool* CreateThreadPool(); |
| void DestroyThreadPool(ThreadPool *Pool); |
| |
| #endif // RAR_SMP |
| |
| } // namespace third_party_unrar |
| |
| #endif // _RAR_THREADPOOL_ |
| |