Skip to content

Commit

Permalink
windows: use waitable timers
Browse files Browse the repository at this point in the history
  • Loading branch information
eyelash committed Aug 30, 2024
1 parent d6b676a commit 3a860c7
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 57 deletions.
4 changes: 2 additions & 2 deletions demos/events.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static void mouse_button_press(float x, float y, int button, int modifiers, void
printf("mouse button press: {%f, %f} (modifiers: %X)\n", x, y, modifiers);
struct demo *demo = user_data;
if (demo->timer) {
gral_window_delete_timer(demo->window, demo->timer);
gral_timer_delete(demo->timer);
demo->timer = 0;
}
}
Expand Down Expand Up @@ -126,7 +126,7 @@ static void create_window(void *user_data) {
&focus_leave
};
demo->window = gral_window_create(demo->application, 600, 400, "gral events demo", &interface, demo);
demo->timer = gral_window_create_timer(demo->window, 1000, &timer, demo);
demo->timer = gral_timer_create(1000, &timer, demo);
}

static void open_empty(void *user_data) {
Expand Down
5 changes: 3 additions & 2 deletions gral.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,11 @@ void gral_window_show_open_file_dialog(struct gral_window *window, void (*callba
void gral_window_show_save_file_dialog(struct gral_window *window, void (*callback)(char const *file, void *user_data), void *user_data);
void gral_window_clipboard_copy(struct gral_window *window, char const *text);
void gral_window_clipboard_paste(struct gral_window *window, void (*callback)(char const *text, void *user_data), void *user_data);
struct gral_timer *gral_window_create_timer(struct gral_window *window, int milliseconds, void (*callback)(void *user_data), void *user_data);
void gral_window_delete_timer(struct gral_window *window, struct gral_timer *timer);
void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data);

struct gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data);
void gral_timer_delete(struct gral_timer *timer);


/*=========
FILE
Expand Down
42 changes: 21 additions & 21 deletions gral_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,25 @@ void gral_window_clipboard_paste(struct gral_window *window, void (*callback)(ch
gtk_clipboard_request_text(clipboard, paste_callback, callback_data);
}

typedef struct {
void (*callback)(void *user_data);
void *user_data;
} IdleCallbackData;
static gboolean idle_callback(gpointer user_data) {
IdleCallbackData *callback_data = user_data;
callback_data->callback(callback_data->user_data);
return G_SOURCE_REMOVE;
}
static void idle_destroy(gpointer user_data) {
g_slice_free(IdleCallbackData, user_data);
}
void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) {
IdleCallbackData *callback_data = g_slice_new(IdleCallbackData);
callback_data->callback = callback;
callback_data->user_data = user_data;
gdk_threads_add_idle_full(G_PRIORITY_DEFAULT_IDLE, idle_callback, callback_data, idle_destroy);
}

typedef struct {
void (*callback)(void *user_data);
void *user_data;
Expand All @@ -652,36 +671,17 @@ static void timer_destroy(gpointer user_data) {
g_slice_free(TimerCallbackData, callback_data);
}

struct gral_timer *gral_window_create_timer(struct gral_window *window, int milliseconds, void (*callback)(void *user_data), void *user_data) {
struct gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data) {
TimerCallbackData *callback_data = g_slice_new(TimerCallbackData);
callback_data->callback = callback;
callback_data->user_data = user_data;
return (struct gral_timer *)(intptr_t)g_timeout_add_full(G_PRIORITY_DEFAULT, milliseconds, timer_callback, callback_data, timer_destroy);
}

void gral_window_delete_timer(struct gral_window *window, struct gral_timer *timer) {
void gral_timer_delete(struct gral_timer *timer) {
g_source_remove((guint)(intptr_t)timer);
}

typedef struct {
void (*callback)(void *user_data);
void *user_data;
} IdleCallbackData;
static gboolean idle_callback(gpointer user_data) {
IdleCallbackData *callback_data = user_data;
callback_data->callback(callback_data->user_data);
return G_SOURCE_REMOVE;
}
static void idle_destroy(gpointer user_data) {
g_slice_free(IdleCallbackData, user_data);
}
void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) {
IdleCallbackData *callback_data = g_slice_new(IdleCallbackData);
callback_data->callback = callback;
callback_data->user_data = user_data;
gdk_threads_add_idle_full(G_PRIORITY_DEFAULT_IDLE, idle_callback, callback_data, idle_destroy);
}


/*=========
FILE
Expand Down
35 changes: 18 additions & 17 deletions gral_macos.m
Original file line number Diff line number Diff line change
Expand Up @@ -667,47 +667,48 @@ void gral_window_clipboard_paste(struct gral_window *window, void (*callback)(ch
}
}

@interface TimerCallbackObject: NSObject {
@interface MainThreadCallbackObject: NSObject {
@public
void (*callback)(void *user_data);
void *user_data;
}
@end
@implementation TimerCallbackObject
- (void)invoke:(NSTimer *)timer {
@implementation MainThreadCallbackObject
- (void)invoke:(id)object {
callback(user_data);
}
@end
struct gral_timer *gral_window_create_timer(struct gral_window *window, int milliseconds, void (*callback)(void *user_data), void *user_data) {
TimerCallbackObject *callback_object = [[TimerCallbackObject alloc] init];
void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) {
MainThreadCallbackObject *callback_object = [[MainThreadCallbackObject alloc] init];
callback_object->callback = callback;
callback_object->user_data = user_data;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:milliseconds/1000.0 target:callback_object selector:@selector(invoke:) userInfo:nil repeats:YES];
[callback_object performSelectorOnMainThread:@selector(invoke:) withObject:nil waitUntilDone:NO];
[callback_object release];
return (struct gral_timer *)timer;
}

void gral_window_delete_timer(struct gral_window *window, struct gral_timer *timer) {
[(NSTimer *)timer invalidate];
}

@interface MainThreadCallbackObject: NSObject {
@interface TimerCallbackObject: NSObject {
@public
void (*callback)(void *user_data);
void *user_data;
}
@end
@implementation MainThreadCallbackObject
- (void)invoke:(id)object {
@implementation TimerCallbackObject
- (void)invoke:(NSTimer *)timer {
callback(user_data);
}
@end
void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) {
MainThreadCallbackObject *callback_object = [[MainThreadCallbackObject alloc] init];

struct gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data) {
TimerCallbackObject *callback_object = [[TimerCallbackObject alloc] init];
callback_object->callback = callback;
callback_object->user_data = user_data;
[callback_object performSelectorOnMainThread:@selector(invoke:) withObject:nil waitUntilDone:NO];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:milliseconds/1000.0 target:callback_object selector:@selector(invoke:) userInfo:nil repeats:YES];
[callback_object release];
return (struct gral_timer *)timer;
}

void gral_timer_delete(struct gral_timer *timer) {
[(NSTimer *)timer invalidate];
}


Expand Down
34 changes: 19 additions & 15 deletions gral_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ struct WindowData {
struct gral_timer {
void (*callback)(void *user_data);
void *user_data;
HANDLE timer;
};


Expand Down Expand Up @@ -458,12 +459,6 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
case WM_KILLFOCUS:
window_data->iface.focus_leave(window_data->user_data);
return 0;
case WM_TIMER:
{
gral_timer *timer = (gral_timer *)wParam;
timer->callback(timer->user_data);
return 0;
}
case WM_SIZE:
{
WORD width = LOWORD(lParam);
Expand Down Expand Up @@ -1064,23 +1059,32 @@ void gral_window_clipboard_paste(gral_window *window, void (*callback)(char cons
CloseClipboard();
}

gral_timer *gral_window_create_timer(gral_window *window, int milliseconds, void (*callback)(void *user_data), void *user_data) {
void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) {
PostMessage((HWND)window, WM_USER, (WPARAM)callback, (LPARAM)user_data);
}

static void CALLBACK timer_completion_routine(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue) {
gral_timer *timer = (gral_timer *)lpArgToCompletionRoutine;
timer->callback(timer->user_data);
}

gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data) {
gral_timer *timer = new gral_timer();
timer->callback = callback;
timer->user_data = user_data;
SetTimer((HWND)window, (UINT_PTR)timer, milliseconds, NULL);
timer->timer = CreateWaitableTimer(NULL, FALSE, NULL);
LARGE_INTEGER due_time;
due_time.QuadPart = (LONGLONG)milliseconds * -10000;
SetWaitableTimer(timer->timer, &due_time, milliseconds, &timer_completion_routine, timer, FALSE);
return timer;
}

void gral_window_delete_timer(gral_window *window, gral_timer *timer) {
KillTimer((HWND)window, (UINT_PTR)timer);
void gral_timer_delete(gral_timer *timer) {
CancelWaitableTimer(timer->timer);
CloseHandle(timer->timer);
delete timer;
}

void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) {
PostMessage((HWND)window, WM_USER, (WPARAM)callback, (LPARAM)user_data);
}


/*=========
FILE
Expand Down Expand Up @@ -1206,7 +1210,7 @@ struct gral_directory_watcher {
}
void watch() {
const DWORD notify_filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY;
ReadDirectoryChangesW(directory, buffer, sizeof(buffer), FALSE, notify_filter, NULL, &overlapped, completion_routine);
ReadDirectoryChangesW(directory, buffer, sizeof(buffer), FALSE, notify_filter, NULL, &overlapped, &completion_routine);
}
void cancel() {
CancelIoEx(directory, &overlapped);
Expand Down

0 comments on commit 3a860c7

Please sign in to comment.