winamp/Src/replicant/nu/win-amd64/ThreadLoop.cpp
2024-09-24 14:54:57 +02:00

71 lines
1.5 KiB
C++

#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);
}