threadpool.hpp 2.7 KB

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