diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/nu/threadpool/ThreadPool.h | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/nu/threadpool/ThreadPool.h')
-rw-r--r-- | Src/nu/threadpool/ThreadPool.h | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/Src/nu/threadpool/ThreadPool.h b/Src/nu/threadpool/ThreadPool.h new file mode 100644 index 00000000..f68efc12 --- /dev/null +++ b/Src/nu/threadpool/ThreadPool.h @@ -0,0 +1,98 @@ +#pragma once + +#include <windows.h> +#include <bfc/platform/types.h> +#include <vector> +#include "../autolock.h" +#include "ThreadID.h" +#include "ThreadFunctions.h" +#include "threadpool_types.h" +/* random notes + +HANDLEs common to all threads + +WaitForMultipleObjectsEx() around these +0 - killswitch +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 +2 - per thread APC event. + + +parameters for "run my function" method +function pointer, user data, flags +flags: +interrupt - for very short non-locking functions where it is safe to interrupt another thread, uses QueueUserAPC +no_wait - spawn a new thread if all threads are busy +com_multithreaded - all threads are created with CoInitialize(0), if you need a COINIT_MULTITHREADED thread, use this flag + +parameters for "add my handle" method +handle, function pointer, user data, flags +flags: +single_thread - only one thread in the pool will wait on your object, useful if your handle is not auto-reset + +parameters for "function call repeat" - calls your function until you return 0 +function pointer, user data, flags +flags: +single_thread - keep calling on the same thread +*/ + + +class ThreadPool : public api_threadpool +{ +public: + static const char *getServiceName() { return "Thread Pool API"; } + static const GUID getServiceGuid() { return ThreadPoolGUID; } +public: + // Owner API: + ThreadPool(); + void Kill(); + + // User API: + /* If you have multiple events, APCs, etc and you need them to always run on the same thread + you can reserve one */ + ThreadID *ReserveThread(int flags); + /* Release a thread you've previously reserved */ + void ReleaseThread(ThreadID *thread_id); + + /* adds a waitable handle to the thread pool. when the event is signalled, your function ptr will get called + user_data and id values get passed to your function. + your function should return 1 to indicate that it can be removed + flags, see api_threadpool */ + int AddHandle(ThreadID *threadid, HANDLE handle, api_threadpool::ThreadPoolFunc func, void *user_data, intptr_t id, int flags); + void RemoveHandle(ThreadID *threadid, HANDLE handle); + int RunFunction(ThreadID *threadid, api_threadpool::ThreadPoolFunc func, void *user_data, intptr_t id, int flags); + + size_t GetNumberOfThreads(); // total number of threads in the threadpool + size_t GetNumberOfActiveThreads(); // number of threads that are currently being used (inside user function but not necessarily busy) + +private: + enum + { + TYPE_MT = 0, + TYPE_STA = 1, + TYPE_MT_RESERVED = 2, + TYPE_STA_RESERVED = 3, + + THREAD_TYPES = 4, // two thread types, single threaded apartment COM and multithreaded COM + }; +private: + static DWORD CALLBACK WatchDogThreadProcedure_stub(LPVOID param); + ThreadID *CreateNewThread_Internal(int thread_type = 0); + DWORD CALLBACK WatchDogThreadProcedure(); + static int GetThreadType(int flags, int reserved = 0); + static void GetThreadTypes(int flags, bool types[THREAD_TYPES]); + void RemoveHandle_Internal(size_t start, HANDLE handle); // recursive helper function for RemoveHandle() + void AddHandle_Internal(size_t start, HANDLE handle, int flags); // recursive helper function for RemoveHandle() + + Nullsoft::Utility::LockGuard guard; // guards threads, any_thread_handles, and non_reserved_handles data structures + typedef std::vector<ThreadID*> ThreadList; + ThreadList threads; + ThreadPoolTypes::HandleList any_thread_handles[THREAD_TYPES]; + HANDLE killswitch; + HANDLE watchdog_thread_handle; + volatile LONG num_threads_available[THREAD_TYPES]; + ThreadFunctions thread_functions; + HANDLE max_load_event[THREAD_TYPES]; +protected: + RECVS_DISPATCH; +}; + |