aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nu/win-amd64/ThreadLoop.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/replicant/nu/win-amd64/ThreadLoop.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/replicant/nu/win-amd64/ThreadLoop.cpp')
-rw-r--r--Src/replicant/nu/win-amd64/ThreadLoop.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/Src/replicant/nu/win-amd64/ThreadLoop.cpp b/Src/replicant/nu/win-amd64/ThreadLoop.cpp
new file mode 100644
index 00000000..4c78a431
--- /dev/null
+++ b/Src/replicant/nu/win-amd64/ThreadLoop.cpp
@@ -0,0 +1,70 @@
+#include "ThreadLoop.h"
+
+lifo_t ThreadLoop::procedure_cache = {0,};
+lifo_t ThreadLoop::cache_bases= {0,};
+
+#define PROCEDURE_CACHE_SEED 64
+ThreadLoop::ThreadLoop()
+{
+ mpscq_init(&procedure_queue);
+ procedure_notification = CreateSemaphore(0, 0, LONG_MAX, 0);
+ kill_switch = CreateEvent(0, TRUE, FALSE, 0);
+}
+
+void ThreadLoop::RefillCache()
+{
+ threadloop_node_t *cache_seed = (threadloop_node_t *)lifo_malloc(PROCEDURE_CACHE_SEED*sizeof(threadloop_node_t));
+ if (cache_seed)
+ {
+ memset(cache_seed, 0, PROCEDURE_CACHE_SEED*sizeof(threadloop_node_t));
+ for (int i=0;i<PROCEDURE_CACHE_SEED;i++)
+ {
+ lifo_push(&procedure_cache, &cache_seed[i]);
+ }
+ lifo_push(&cache_bases, cache_seed);
+ }
+}
+
+void ThreadLoop::Run()
+{
+ HANDLE events[] = {kill_switch, procedure_notification};
+ while (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0 + 1)
+ {
+ threadloop_node_t *apc;
+ for (;;)
+ {
+ apc = (threadloop_node_t *)mpscq_pop(&procedure_queue);
+ if (!apc)
+ {
+ Sleep(0);
+ continue;
+ }
+ apc->func(apc->param1, apc->param2, apc->real_value);
+ }
+ lifo_push(&procedure_cache, apc);
+ }
+}
+
+threadloop_node_t *ThreadLoop::GetAPC()
+{
+ threadloop_node_t *apc = 0;
+
+ do
+ {
+ apc = (threadloop_node_t *)lifo_pop(&procedure_cache);
+ if (!apc)
+ RefillCache();
+ } while (!apc);
+ return apc;
+}
+
+void ThreadLoop::Schedule(threadloop_node_t *apc)
+{
+ mpscq_push(&procedure_queue, apc);
+ ReleaseSemaphore(procedure_notification, 1, 0);
+}
+
+void ThreadLoop::Kill()
+{
+ SetEvent(kill_switch);
+}