1
0

ThreadPool.h 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #pragma once
  2. #include <windows.h>
  3. #include <bfc/platform/types.h>
  4. #include <vector>
  5. #include "../autolock.h"
  6. #include "ThreadID.h"
  7. #include "ThreadFunctions.h"
  8. #include "threadpool_types.h"
  9. /* random notes
  10. HANDLEs common to all threads
  11. WaitForMultipleObjectsEx() around these
  12. 0 - killswitch
  13. 1 - shared APC event. since threads might want to use APCs themselves, we'll use a different mechanism (thread-safe FIFO and an event). the intention is that APCs that can go on any thread will use this handle
  14. 2 - per thread APC event.
  15. parameters for "run my function" method
  16. function pointer, user data, flags
  17. flags:
  18. interrupt - for very short non-locking functions where it is safe to interrupt another thread, uses QueueUserAPC
  19. no_wait - spawn a new thread if all threads are busy
  20. com_multithreaded - all threads are created with CoInitialize(0), if you need a COINIT_MULTITHREADED thread, use this flag
  21. parameters for "add my handle" method
  22. handle, function pointer, user data, flags
  23. flags:
  24. single_thread - only one thread in the pool will wait on your object, useful if your handle is not auto-reset
  25. parameters for "function call repeat" - calls your function until you return 0
  26. function pointer, user data, flags
  27. flags:
  28. single_thread - keep calling on the same thread
  29. */
  30. class ThreadPool : public api_threadpool
  31. {
  32. public:
  33. static const char *getServiceName() { return "Thread Pool API"; }
  34. static const GUID getServiceGuid() { return ThreadPoolGUID; }
  35. public:
  36. // Owner API:
  37. ThreadPool();
  38. void Kill();
  39. // User API:
  40. /* If you have multiple events, APCs, etc and you need them to always run on the same thread
  41. you can reserve one */
  42. ThreadID *ReserveThread(int flags);
  43. /* Release a thread you've previously reserved */
  44. void ReleaseThread(ThreadID *thread_id);
  45. /* adds a waitable handle to the thread pool. when the event is signalled, your function ptr will get called
  46. user_data and id values get passed to your function.
  47. your function should return 1 to indicate that it can be removed
  48. flags, see api_threadpool */
  49. int AddHandle(ThreadID *threadid, HANDLE handle, api_threadpool::ThreadPoolFunc func, void *user_data, intptr_t id, int flags);
  50. void RemoveHandle(ThreadID *threadid, HANDLE handle);
  51. int RunFunction(ThreadID *threadid, api_threadpool::ThreadPoolFunc func, void *user_data, intptr_t id, int flags);
  52. size_t GetNumberOfThreads(); // total number of threads in the threadpool
  53. size_t GetNumberOfActiveThreads(); // number of threads that are currently being used (inside user function but not necessarily busy)
  54. private:
  55. enum
  56. {
  57. TYPE_MT = 0,
  58. TYPE_STA = 1,
  59. TYPE_MT_RESERVED = 2,
  60. TYPE_STA_RESERVED = 3,
  61. THREAD_TYPES = 4, // two thread types, single threaded apartment COM and multithreaded COM
  62. };
  63. private:
  64. static DWORD CALLBACK WatchDogThreadProcedure_stub(LPVOID param);
  65. ThreadID *CreateNewThread_Internal(int thread_type = 0);
  66. DWORD CALLBACK WatchDogThreadProcedure();
  67. static int GetThreadType(int flags, int reserved = 0);
  68. static void GetThreadTypes(int flags, bool types[THREAD_TYPES]);
  69. void RemoveHandle_Internal(size_t start, HANDLE handle); // recursive helper function for RemoveHandle()
  70. void AddHandle_Internal(size_t start, HANDLE handle, int flags); // recursive helper function for RemoveHandle()
  71. Nullsoft::Utility::LockGuard guard; // guards threads, any_thread_handles, and non_reserved_handles data structures
  72. typedef std::vector<ThreadID*> ThreadList;
  73. ThreadList threads;
  74. ThreadPoolTypes::HandleList any_thread_handles[THREAD_TYPES];
  75. HANDLE killswitch;
  76. HANDLE watchdog_thread_handle;
  77. volatile LONG num_threads_available[THREAD_TYPES];
  78. ThreadFunctions thread_functions;
  79. HANDLE max_load_event[THREAD_TYPES];
  80. protected:
  81. RECVS_DISPATCH;
  82. };