1 #ifndef _RAR_THREADPOOL_ 2 #define _RAR_THREADPOOL_ 3 4 #ifndef RAR_SMP 5 const uint MaxPoolThreads=1; // For single threaded version. 6 #else 7 const uint MaxPoolThreads=32; 8 9 10 #ifdef _UNIX 11 #include <pthread.h> 12 #include <semaphore.h> 13 #endif 14 15 // Undefine for debugging. 16 #define USE_THREADS 17 18 #ifdef _UNIX 19 #define NATIVE_THREAD_TYPE void* 20 typedef void* (*NATIVE_THREAD_PTR)(void *Data); 21 typedef pthread_t THREAD_HANDLE; 22 typedef pthread_mutex_t CRITSECT_HANDLE; 23 #else 24 #define NATIVE_THREAD_TYPE DWORD WINAPI 25 typedef DWORD (WINAPI *NATIVE_THREAD_PTR)(void *Data); 26 typedef HANDLE THREAD_HANDLE; 27 typedef CRITICAL_SECTION CRITSECT_HANDLE; 28 #endif 29 30 typedef void (*PTHREAD_PROC)(void *Data); 31 #define THREAD_PROC(fn) void fn(void *Data) 32 33 uint GetNumberOfCPU(); 34 uint GetNumberOfThreads(); 35 36 37 class ThreadPool 38 { 39 private: 40 struct QueueEntry 41 { 42 PTHREAD_PROC Proc; 43 void *Param; 44 }; 45 46 void CreateThreads(); 47 static NATIVE_THREAD_TYPE PoolThread(void *Param); 48 void PoolThreadLoop(); 49 bool GetQueuedTask(QueueEntry *Task); 50 51 // Number of threads in the pool. Must not exceed MaxPoolThreads. 52 uint MaxAllowedThreads; 53 THREAD_HANDLE ThreadHandles[MaxPoolThreads]; 54 55 // Number of actually created threads. 56 uint ThreadsCreatedCount; 57 58 uint ActiveThreads; 59 60 QueueEntry TaskQueue[MaxPoolThreads]; 61 uint QueueTop; 62 uint QueueBottom; 63 64 bool Closing; // Set true to quit all threads. 65 66 #ifdef _WIN_ALL 67 // Semaphore counting number of tasks stored in queue. 68 HANDLE QueuedTasksCnt; 69 70 // Event signalling if no active tasks are performing now. 71 HANDLE NoneActive; 72 73 #elif defined(_UNIX) 74 // Semaphores seem to be slower than conditional variables in pthreads, 75 // so we use the conditional variable to count tasks stored in queue. 76 uint QueuedTasksCnt; 77 pthread_cond_t QueuedTasksCntCond; 78 pthread_mutex_t QueuedTasksCntMutex; 79 80 bool AnyActive; // Active tasks present flag. 81 pthread_cond_t AnyActiveCond; 82 pthread_mutex_t AnyActiveMutex; 83 #endif 84 85 // Pool critical section. We use the single section for all branches 86 // to avoid deadlocks, when thread1 has section1 and wants section2 87 // and thread2 has section2 and wants section1. 88 CRITSECT_HANDLE CritSection; 89 public: 90 ThreadPool(uint MaxThreads); 91 ~ThreadPool(); 92 void AddTask(PTHREAD_PROC Proc,void *Data); 93 void WaitDone(); 94 95 #ifdef _WIN_ALL 96 static int ThreadPriority; SetPriority(int Priority)97 static void SetPriority(int Priority) {ThreadPriority=Priority;} 98 #endif 99 }; 100 101 ThreadPool* CreateThreadPool(); 102 void DestroyThreadPool(ThreadPool *Pool); 103 104 #endif // RAR_SMP 105 106 #endif // _RAR_THREADPOOL_ 107 108