Skip to content

Commit

Permalink
Windows modTimer: a different approach to fixing #1058 (largely rever…
Browse files Browse the repository at this point in the history
…ts 8e571e and replaces it with a new implementation)
  • Loading branch information
andycarle committed Mar 24, 2023
1 parent 8e571eb commit 9f587ef
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 21 deletions.
4 changes: 0 additions & 4 deletions modules/base/timer/modTimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,7 @@ static void createTimer(xsMachine *the, int interval, int repeat)
ts.the = the;
ts.callback = xsToReference(xsArg(0));
ts.self = xsNewHostObject(NULL);
#if mxWindows
timer = modTimerAdd(interval, repeat, xs_timer_callback, &ts, sizeof(ts), the->window);
#else
timer = modTimerAdd(interval, repeat, xs_timer_callback, &ts, sizeof(ts));
#endif
if (!timer)
xsUnknownError("add failed");
xsRemember(((modTimerScript)modTimerGetRefcon(timer))->self);
Expand Down
5 changes: 0 additions & 5 deletions modules/base/timer/modTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,7 @@ typedef struct modTimerRecord modTimerRecord;
typedef struct modTimerRecord *modTimer;

typedef void (*modTimerCallback)(modTimer timer, void *refcon, int refconSize);

#if mxWindows
extern modTimer modTimerAdd(int firstInterval, int secondInterval, modTimerCallback cb, void *refcon, int refconSize, HWND targetWindow);
#else
extern modTimer modTimerAdd(int firstInterval, int secondInterval, modTimerCallback cb, void *refcon, int refconSize);
#endif
extern void modTimerReschedule(modTimer timer, int firstInterval, int secondInterval);
extern uint16_t modTimerGetID(modTimer timer);
extern int modTimerGetSecondInterval(modTimer timer);
Expand Down
46 changes: 40 additions & 6 deletions modules/base/timer/win/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,16 @@ static CRITICAL_SECTION gCS;
static void modTimerExecuteOne(modTimer timer);
static modTimer modTimerFindNative(UINT_PTR idEvent);
void modTimerWindowCallback(LPARAM timer);
static void destroyTimer(modTimer timer);
static void createTimerWindow(modTimer timer);
LRESULT CALLBACK modTimerWindowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam);

static VOID CALLBACK TimerProc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) {
modTimer timer;

timer = modTimerFindNative(uTimerID);
if (timer)
SendMessage(timer->window, WM_MODTIMER, (WPARAM)&modTimerWindowCallback, (LPARAM)timer);
SendMessage(timer->window, WM_MODTIMER, 0, (LPARAM)timer);
}

static void modCriticalSectionBegin()
Expand Down Expand Up @@ -105,7 +108,7 @@ static modTimer modTimerFindNative(UINT_PTR idEvent)
return walker;
}

modTimer modTimerAdd(int firstInterval, int secondInterval, modTimerCallback cb, void *refcon, int refconSize, HWND targetWindow)
modTimer modTimerAdd(int firstInterval, int secondInterval, modTimerCallback cb, void *refcon, int refconSize)
{
modTimer timer;

Expand All @@ -114,7 +117,7 @@ modTimer modTimerAdd(int firstInterval, int secondInterval, modTimerCallback cb,
initializedCriticalSection = TRUE;
}

timer = c_malloc(sizeof(modTimerRecord) + refconSize - 1);
timer = c_calloc(1, sizeof(modTimerRecord) + refconSize - 1);
if (!timer) return NULL;

timer->next = NULL;
Expand All @@ -124,15 +127,15 @@ modTimer modTimerAdd(int firstInterval, int secondInterval, modTimerCallback cb,
timer->useCount = 1;
timer->repeating = 0;
timer->cb = cb;
timer->window = targetWindow;
createTimerWindow(timer);
timer->refconSize = refconSize;
c_memmove(timer->refcon, refcon, refconSize);

if (firstInterval == 0)
firstInterval = 1;
timer->idEvent = timeSetEvent(firstInterval, 1, TimerProc, timer->id, TIME_ONESHOT);
if (!(timer->idEvent)) {
c_free(timer);
destroyTimer(timer);
return NULL;
}

Expand Down Expand Up @@ -220,7 +223,7 @@ void modTimerRemove(modTimer timer)
prev->next = walker->next;
if (timer->idEvent)
timeKillEvent(timer->idEvent);
c_free(timer);
destroyTimer(timer);
modInstrumentationAdjust(Timers, -1);
}
break;
Expand All @@ -236,3 +239,34 @@ void modTimerDelayMS(uint32_t ms)
Sleep(ms);
timeEndPeriod(1);
}

LRESULT CALLBACK modTimerWindowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_MODTIMER: {
modTimerWindowCallback(lParam);
return 0;
} break;
default:
return DefWindowProc(window, message, wParam, lParam);
}
}

static void createTimerWindow(modTimer timer)
{
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbWndExtra = sizeof(modTimer);
wcex.lpfnWndProc = modTimerWindowProc;
wcex.lpszClassName = "modTimerWindowClass";
RegisterClassEx(&wcex);
timer->window = CreateWindowEx(0, wcex.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
SetWindowLongPtr(timer->window, 0, (LONG_PTR)timer);
}

static void destroyTimer(modTimer timer)
{
if (timer->window)
DestroyWindow(timer->window);
c_free(timer);
}
4 changes: 0 additions & 4 deletions xs/platforms/win_xs.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@ LRESULT CALLBACK fxMessageWindowProc(HWND window, UINT message, WPARAM wParam, L
job = next;
}
} break;
case WM_MODTIMER: {
txMachine* the = (txMachine*)GetWindowLongPtr(window, 0);
(*((timerCallback)wParam))(lParam);
} break;
#ifdef mxDebug
case WM_XSBUG: {
txMachine* the = (txMachine*)GetWindowLongPtr(window, 0);
Expand Down
2 changes: 0 additions & 2 deletions xs/platforms/win_xs.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,4 @@ extern void fxQueueWorkerJob(void* machine, void* job);
#define MODDEF_XS_TEST 1
#endif

typedef void (*timerCallback)(LPARAM lParam);

#endif /* __WIN_XS__ */

0 comments on commit 9f587ef

Please sign in to comment.