blob: bb3b59e247af6b6e4dba8a8aefd6a6f66b4dbf18 [file] [log] [blame]
#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_