Skip to content

Commit

Permalink
Windows modTimer: handle timer callbacks in the correct thread / with…
Browse files Browse the repository at this point in the history
… the correct Window handle (#1058)
  • Loading branch information
andycarle committed Mar 22, 2023
1 parent 731da6b commit 8e571eb
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 6 deletions.
4 changes: 4 additions & 0 deletions modules/base/timer/modTimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ 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
4 changes: 4 additions & 0 deletions modules/base/timer/modTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ 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
15 changes: 11 additions & 4 deletions modules/base/timer/win/timer.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2022 Moddable Tech, Inc.
* Copyright (c) 2016-2023 Moddable Tech, Inc.
*
* This file is part of the Moddable SDK Runtime.
*
Expand Down Expand Up @@ -38,6 +38,7 @@ struct modTimerRecord {
uint8_t rescheduled;
uint8_t repeating;
modTimerCallback cb;
HWND window;
uint32_t refconSize;
char refcon[1];
};
Expand All @@ -49,13 +50,14 @@ static CRITICAL_SECTION gCS;

static void modTimerExecuteOne(modTimer timer);
static modTimer modTimerFindNative(UINT_PTR idEvent);
void modTimerWindowCallback(LPARAM timer);

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

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

static void modCriticalSectionBegin()
Expand All @@ -68,6 +70,11 @@ static void modCriticalSectionEnd()
LeaveCriticalSection(&gCS);
}

void modTimerWindowCallback(LPARAM t) {
modTimer timer = (modTimer)t;
modTimerExecuteOne(timer);
}

static void modTimerExecuteOne(modTimer timer)
{
timer->rescheduled = 0;
Expand Down Expand Up @@ -98,7 +105,7 @@ static modTimer modTimerFindNative(UINT_PTR idEvent)
return walker;
}

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

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

// timer->idEvent = SetTimer(NULL, timer->id, firstInterval, TimerProc);
if (firstInterval == 0)
firstInterval = 1;
timer->idEvent = timeSetEvent(firstInterval, 1, TimerProc, timer->id, TIME_ONESHOT);
Expand Down
6 changes: 5 additions & 1 deletion xs/platforms/win_xs.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2022 Moddable Tech, Inc.
* Copyright (c) 2016-2023 Moddable Tech, Inc.
*
* This file is part of the Moddable SDK Runtime.
*
Expand Down Expand Up @@ -69,6 +69,10 @@ 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
5 changes: 4 additions & 1 deletion xs/platforms/win_xs.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017 Moddable Tech, Inc.
* Copyright (c) 2016-2023 Moddable Tech, Inc.
*
* This file is part of the Moddable SDK Runtime.
*
Expand Down Expand Up @@ -95,9 +95,12 @@ extern void fxQueueWorkerJob(void* machine, void* job);
#define WM_XSBUG WM_USER + 2
#define WM_CALLBACK WM_USER + 3
#define WM_WORKER WM_USER + 4
#define WM_MODTIMER WM_USER + 5

#ifdef mxDebug
#define MODDEF_XS_TEST 1
#endif

typedef void (*timerCallback)(LPARAM lParam);

#endif /* __WIN_XS__ */

0 comments on commit 8e571eb

Please sign in to comment.