123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- #include "ThreadLoop.h"
- #include <limits.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 = CreateSemaphoreW(0, 0, LONG_MAX, 0);
- kill_switch = CreateEvent(0, TRUE, FALSE, 0);
- }
- ThreadLoop::~ThreadLoop()
- {
- CloseHandle(procedure_notification);
- CloseHandle(kill_switch);
- }
- void ThreadLoop::RefillCache()
- {
- threadloop_node_t *cache_seed = (threadloop_node_t *)malloc(PROCEDURE_CACHE_SEED*sizeof(threadloop_node_t));
-
- if (cache_seed)
- {
- int i=PROCEDURE_CACHE_SEED;
- while (--i)
- {
- lifo_push(&procedure_cache, (queue_node_t *)&cache_seed[i]);
- }
- lifo_push(&cache_bases, (queue_node_t *)cache_seed);
- }
- else
- {
- Sleep(0); // yield and hope that someone else pops something off soon
- }
- }
- void ThreadLoop::Run()
- {
- HANDLE events[] = {kill_switch, procedure_notification};
- while (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0 + 1)
- {
- for (;;)
- {
- threadloop_node_t *apc = (threadloop_node_t *)mpscq_pop(&procedure_queue);
- if (apc == (threadloop_node_t *)1) /* special return value that indicates a busy list */
- {
- Sleep(0); // yield so that the thread that got pre-empted during push can finish
- }
- else
- {
- if (apc)
- {
- apc->func(apc->param1, apc->param2, apc->real_value);
- lifo_push(&procedure_cache, apc);
- }
- else
- {
- break;
- }
- }
- }
- }
- }
- void ThreadLoop::Step(unsigned int milliseconds)
- {
- HANDLE events[] = {kill_switch, procedure_notification};
- if (WaitForMultipleObjects(2, events, FALSE, milliseconds) == WAIT_OBJECT_0 + 1)
- {
- for (;;)
- {
- threadloop_node_t *apc = (threadloop_node_t *)mpscq_pop(&procedure_queue);
- if (apc == (threadloop_node_t *)1) /* special return value that indicates a busy list */
- {
- Sleep(0); // yield so that the thread that got pre-empted during push can finish
- }
- else
- {
- if (apc)
- {
- apc->func(apc->param1, apc->param2, apc->real_value);
- lifo_push(&procedure_cache, apc);
- }
- else
- {
- break;
- }
- }
- }
- }
- }
- void ThreadLoop::Step()
- {
- HANDLE events[] = {kill_switch, procedure_notification};
- if (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0 + 1)
- {
- for (;;)
- {
- threadloop_node_t *apc = (threadloop_node_t *)mpscq_pop(&procedure_queue);
- if (apc == (threadloop_node_t *)1) /* special return value that indicates a busy list */
- {
- Sleep(0); // yield so that the thread that got pre-empted during push can finish
- }
- else
- {
- if (apc)
- {
- apc->func(apc->param1, apc->param2, apc->real_value);
- lifo_push(&procedure_cache, apc);
- }
- else
- {
- break;
- }
- }
- }
- }
- }
- 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)
- {
- if (mpscq_push(&procedure_queue, apc) == 0)
- ReleaseSemaphore(procedure_notification, 1, 0);
- }
- void ThreadLoop::Kill()
- {
- SetEvent(kill_switch);
- }
|