libclamunrar/threadpool.hpp
d39cb658
 #ifndef _RAR_THREADPOOL_
 #define _RAR_THREADPOOL_
 
 #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
 
 #endif // _RAR_THREADPOOL_