winamp/Src/nu/threadpool/ThreadFunctions.cpp
2024-09-24 14:54:57 +02:00

80 lines
2.1 KiB
C++

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