summaryrefslogtreecommitdiff
path: root/plugins/Clist_modern/src/modern_sync.cpp
blob: 50bec6b3dc7a8cd9888c9d036e23e25ec2555a14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "stdafx.h"
#include "modern_sync.h"

static INT_PTR SyncCaller(WPARAM proc, LPARAM lParam)
{
	typedef int(*P0PARAMFUNC)();
	typedef int(*P1PARAMFUNC)(WPARAM);
	typedef int(*P2PARAMFUNC)(WPARAM, LPARAM);
	typedef int(*P3PARAMFUNC)(WPARAM, LPARAM, LPARAM);
	typedef int(*P4PARAMFUNC)(WPARAM, LPARAM, LPARAM, LPARAM);

	LPARAM * params = (LPARAM *)lParam;
	int count = params[0];
	switch (count) {
	case 0:
		return ((P0PARAMFUNC)proc)();

	case 1:
		return ((P1PARAMFUNC)proc)((WPARAM)params[1]);

	case 2:
		return ((P2PARAMFUNC)proc)((WPARAM)params[1], (LPARAM)params[2]);

	case 3:
		return ((P3PARAMFUNC)proc)((WPARAM)params[1], (LPARAM)params[2], (LPARAM)params[3]);

	case 4:
		return ((P4PARAMFUNC)proc)((WPARAM)params[1], (LPARAM)params[2], (LPARAM)params[3], (LPARAM)params[4]);
	}
	return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////

struct SYNCCALLITEM
{
	WPARAM  wParam;
	LPARAM  lParam;
	int     nResult;
	HANDLE  hDoneEvent;
	PSYNCCALLBACKPROC pfnProc;
};

static void CALLBACK _SyncCallerUserAPCProc(void* param)
{
	SYNCCALLITEM* item = (SYNCCALLITEM*)param;
	item->nResult = item->pfnProc(item->wParam, item->lParam);
	SetEvent(item->hDoneEvent);
}

static int SyncCallAPCProxy(PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam)
{
	if (pfnProc == nullptr)
		return 0;

	if (GetCurrentThreadId() == g_dwMainThreadID)
		return pfnProc(wParam, lParam);

	SYNCCALLITEM item;
	item.wParam = wParam;
	item.lParam = lParam;
	item.pfnProc = pfnProc;
	item.nResult = 0;
	item.hDoneEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);

	CallFunctionAsync(_SyncCallerUserAPCProc, &item);

	WaitForSingleObject(item.hDoneEvent, INFINITE);
	CloseHandle(item.hDoneEvent);
	return item.nResult;
}

/////////////////////////////////////////////////////////////////////////////////////////

int DoCall(PSYNCCALLBACKPROC pfnProc, WPARAM, LPARAM lParam)
{
	return SyncCallAPCProxy(pfnProc, 0, lParam);
}

int SyncCall(void * vproc, int count, ...)
{
	LPARAM params[5];
	va_list va;
	params[0] = (LPARAM)count;
	va_start(va, count);
	for (int i = 0; i < count && i < _countof(params) - 1; i++)
		params[i + 1] = va_arg(va, LPARAM);

	va_end(va);
	return SyncCallAPCProxy(SyncCaller, (WPARAM)vproc, (LPARAM)params);
}