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