Last active
July 8, 2019 08:24
-
-
Save flowerinthenight/48d81f079d64dabbad7fa80928159461 to your computer and use it in GitHub Desktop.
Using thread APC as FIFO queue to avoid using explicit locking/synchronization when enqueueing/dequeueing.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
typedef struct _param_t { | |
int code; | |
} param_t; | |
HANDLE hTerm = NULL; // terminate event | |
HANDLE hThr = NULL; // apc thread | |
HANDLE hReady = NULL; // apc thread ready event | |
// This is our FIFO queue thread. | |
DWORD __stdcall InternalApcDispatcher(LPVOID lpData) | |
{ | |
_tprintf(L"[%d] dispatcher started.\n", GetCurrentThreadId()); | |
SetEvent(hReady); | |
while (TRUE) { | |
// All we need to do here is to set this thread to alertable wait to be able to service | |
// user mode APCs. Clients will queue APCs to this thread for servicing. | |
if (WaitForSingleObjectEx(hTerm, INFINITE, TRUE) == WAIT_OBJECT_0) break; | |
} | |
return 0; | |
} | |
// Helper function to add work to our queue. | |
DWORD QueueWork(PAPCFUNC pFunction, ULONG_PTR pData) | |
{ | |
return QueueUserAPC(pFunction, hThr, pData); | |
} | |
// Sample work to be queued. | |
VOID CALLBACK APCProc(_In_ ULONG_PTR dwParam) | |
{ | |
int i = (int)dwParam; | |
_tprintf(L"threadid: %d, data: %d\n", GetCurrentThreadId(), i); | |
} | |
int main() | |
{ | |
hTerm = CreateEvent(NULL, TRUE, FALSE, NULL); | |
hReady = CreateEvent(NULL, TRUE, FALSE, NULL); | |
// create the FIFO queue thread | |
hThr = CreateThread(NULL, 0, InternalApcDispatcher, NULL, 0, NULL); | |
// wait for it to be ready | |
WaitForSingleObject(hReady, INFINITE); | |
// queue 10 work items with index as our data | |
for (int i = 0; i < 10; i++) { | |
QueueWork(APCProc, (ULONG_PTR)i); | |
} | |
// wait a bit to allow APC processing | |
Sleep(3000); | |
// close everything | |
SetEvent(hTerm); | |
CloseHandle(hTerm); | |
CloseHandle(hReady); | |
WaitForSingleObject(hThr, INFINITE); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment