aboutsummaryrefslogtreecommitdiff
path: root/Src/nu/threadpool/ThreadFunctions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/nu/threadpool/ThreadFunctions.cpp')
-rw-r--r--Src/nu/threadpool/ThreadFunctions.cpp79
1 files changed, 79 insertions, 0 deletions
diff --git a/Src/nu/threadpool/ThreadFunctions.cpp b/Src/nu/threadpool/ThreadFunctions.cpp
new file mode 100644
index 00000000..0ae23730
--- /dev/null
+++ b/Src/nu/threadpool/ThreadFunctions.cpp
@@ -0,0 +1,79 @@
+#include "ThreadFunctions.h"
+#include "threadpool_types.h"
+
+ThreadFunctions::ThreadFunctions(int create_function_list)
+{
+ if (create_function_list)
+ {
+ functions_semaphore = CreateSemaphore(0, 0, ThreadPoolTypes::MAX_SEMAPHORE_VALUE, 0);
+ InitializeCriticalSectionAndSpinCount(&functions_guard, 200);
+ }
+ else
+ functions_semaphore = 0;
+}
+
+ThreadFunctions::~ThreadFunctions()
+{
+ if (functions_semaphore)
+ {
+ CloseHandle(functions_semaphore);
+ DeleteCriticalSection(&functions_guard);
+ }
+}
+
+void ThreadFunctions::Add(HANDLE handle, api_threadpool::ThreadPoolFunc func, void *user_data, intptr_t id)
+{
+ Nullsoft::Utility::AutoLock l(guard);
+ Data *new_data = (Data *)calloc(1, sizeof(Data));
+ new_data->func = func;
+ new_data->user_data = user_data;
+ new_data->id = id;
+ data[handle] = new_data;
+}
+
+bool ThreadFunctions::Get(HANDLE handle, api_threadpool::ThreadPoolFunc *func, void **user_data, intptr_t *id)
+{
+ Nullsoft::Utility::AutoLock l(guard);
+ DataMap::iterator found = data.find(handle);
+ if (found == data.end())
+ return false;
+
+ const Data *d = found->second;
+ *func = d->func;
+ *user_data = d->user_data;
+ *id = d->id;
+ return true;
+}
+
+void ThreadFunctions::QueueFunction(api_threadpool::ThreadPoolFunc func, void *user_data, intptr_t id)
+{
+ Data *new_data = (Data *)calloc(1, sizeof(Data));
+ new_data->func = func;
+ new_data->user_data = user_data;
+ new_data->id = id;
+ EnterCriticalSection(&functions_guard);
+ functions_list.push_front(new_data);
+ LeaveCriticalSection(&functions_guard); // unlock before releasing the semaphore early so we don't lock convoy
+ ReleaseSemaphore(functions_semaphore, 1, 0);
+}
+
+bool ThreadFunctions::PopFunction(api_threadpool::ThreadPoolFunc *func, void **user_data, intptr_t *id)
+{
+ EnterCriticalSection(&functions_guard);
+ if (!functions_list.empty())
+ {
+ ThreadFunctions::Data *data = functions_list.back();
+ functions_list.pop_back();
+ LeaveCriticalSection(&functions_guard);
+ *func = data->func;
+ *user_data = data->user_data;
+ *id = data->id;
+ free(data);
+ return true;
+ }
+ else
+ {
+ LeaveCriticalSection(&functions_guard);
+ return false;
+ }
+}