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