Re: g_io_channel_win32_new_messages() WaitForSingleObject()
On Thu, 02 Apr 2009 19:49:48 -0500 Thomas Stover tho...@wsinnovations.com wrote: Some notes for anyone else who is just figuring out several things like myself: -a real new source would have a constructor that would do the allocation and setup -it would also have its own functions for setting up callbacks to source specific events -I think g_source_remove_poll() would be called in related destructor, so I suppose the GPollFD structure needs to be stored in MySource as well -I guess the destructor would be the closer_callback of the GSourceFuncs parameter -the GSourceFuncs and GPollFD variables are just copied by glib when they given as parameters, so they don't need to dynamic (or global/static like my last examples) I do not really understand what the issues are (that may be more my problem than yours) but first, yes you generally would store the GPollFD object in the source object by value if you are making your own custom polling source, and secondly since you do need to pass g_source_new() a GSourceFunc struct, the sensible way to implement that is to make the GSourceFunc object (which is just a struct of function pointers common to all source objects of that type) a static object - you don't have to, but it would be pointless doing it any other way because you may have more than one of the custom source objects in use at any one time which would otherwise result in duplicated GSourceFunc objects. Lastly, glib will correctly manage resources if you use the mechanisms which it provides. The finalize function you pass to GSourceFuncs should free any MySource data which happens to have been allocated on the heap (generally you would not have any). Everything else will be taken care of. In particular g_source_attach() increments the reference count on the source object, and after you have called g_source_attach() you can pass ownership of the MySource object to the main loop in the normal way by calling g_source_unref() on the MySource source object. The main loop will then automatically destroy your MySource object if either the dispatch function returns false, or if g_source_remove() is called on the source id returned by g_source_attach(). (The function you use to create your custom source object should return this ID so that users can do just that.) Chris ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_channel_win32_new_messages() WaitForSingleObject()
Man, I'm almost there. First, just ignore everything having to do with win32 services. I was misreading the msdn service example. The WaitFor*() is really done on an event. So here is a stripped down demo of the progress so far. It does what I want, but then crashes before ending the event loop gracefully, which means something needs to be different. I'm sure it has something to do with the size arg to g_source_new() call, since GSource is simply: typedef struct { } GSource; Clearly I have no idea what I even want to pass to it. === glib_win32_event_test.c = #include glib.h #include windows.h HANDLE windows_event = NULL; GPollFD g_poll_fd; GSourceFuncs g_source_funcs; int global_int = 0; gboolean my_source_prepare(GSource *source, gint *timeout_) { g_print(1) my_source_prepare()\n); *timeout_ = -1; return FALSE; } gboolean my_source_check(GSource *source) { g_print(1) my_source_check()\n); if(global_int) { g_print(1) bam!\n); return TRUE; } return FALSE; } gboolean timeout_callback(gpointer opaq) { g_print(1) still here...\n); return TRUE; } DWORD WINAPI thread_entry(LPVOID lpParameter) { g_print(2) I'm thread #%d\n, GetCurrentThreadId()); Sleep(4000); g_print(2) stuff is going to happen now..\n); global_int = 1; SetEvent(windows_event); g_print(2) I'm done\n); return 0; } int main(int argc, char **argv) { DWORD error_code; gchar *error_string; GMainLoop *main_loop; GSource *g_source; g_print(1) I'm thread #%d\n, GetCurrentThreadId()); if((windows_event = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { error_code = GetLastError(); error_string = g_win32_error_message(error_code); g_print(1) CreateEvent() failed, \%s\\n, error_string); g_free(error_string); return 1; } main_loop = g_main_loop_new(NULL, FALSE); g_timeout_add(1000, timeout_callback, NULL); g_poll_fd.events = 0; g_poll_fd.revents = G_IO_IN; g_poll_fd.fd = windows_event; memset(g_source_funcs, 0, sizeof(GSourceFuncs)); g_source_funcs.prepare = my_source_prepare; g_source_funcs.check = my_source_check; g_source = g_source_new(g_source_funcs, sizeof(GSource)); g_source_attach(g_source, NULL); g_source_add_poll(g_source, g_poll_fd); if(CreateThread(NULL, 0, thread_entry, NULL, 0, NULL) == NULL) { error_code = GetLastError(); error_string = g_win32_error_message(error_code); g_print(1) CreateThread() failed, \%s\\n, error_string); g_free(error_string); return 1; } g_main_loop_run(main_loop); return 0; } cmd.exe session output: 1) I'm thread #3444 1) my_source_prepare() 2) I'm thread #5064 1) my_source_check() 1) still here... 1) my_source_prepare() 1) my_source_check() 1) still here... 1) my_source_prepare() 1) my_source_check() 1) still here... 1) my_source_prepare() 2) stuff is going to happen now.. 2) I'm done 1) my_source_check() 1) bam! 1) still here... [crash and burn] = Thoughts? Tor Lillqvist wrote: It's best to experiment, as I said I don't recall the details by heart... and too busy to actually check now. --tml ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_channel_win32_new_messages() WaitForSingleObject()
Well if any lone googlers ever find this, and want to know what happened. I did fix it with this, but I still think the right way is to some how create a new structure that is inherits the GSourceFuncs and adds a place to store the event handle and the protected data (in this case global_int). If there was an example of how to create a source, or some doc on a source life cycle, that would be helpful. I did look at the source, but was quickly lost. I'm guessing the main loop architecture involves multiple sources, fds, and realization callbacks all being able to exist without extras. So for instance 1 fd could trigger 5 sources, which each result in glib calling a variable number of callbacks. If only there was more time to spend on these things #include glib.h #include windows.h HANDLE windows_event = NULL; GPollFD g_poll_fd; GSourceFuncs g_source_funcs; int global_int = 0; GMainLoop *main_loop; gboolean my_source_prepare(GSource *source, gint *timeout_) { g_print(1) my_source_prepare()\n); *timeout_ = -1; return FALSE; } gboolean my_source_check(GSource *source) { g_print(1) my_source_check()\n); if(global_int) { g_print(1) bam!\n); // g_source_remove_poll(source, g_poll_fd); return TRUE; } return FALSE; } gboolean my_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { g_print(1) my_source_dispatch()\n); if(callback == NULL) return FALSE; return callback(user_data); } gboolean my_source_callback(gpointer data) { g_print(1) my_source_callback()\n); g_main_loop_quit(main_loop); return FALSE; } gboolean timeout_callback(gpointer opaq) { g_print(1) still here...\n); return TRUE; } DWORD WINAPI thread_entry(LPVOID lpParameter) { g_print(2) I'm thread #%d\n, GetCurrentThreadId()); Sleep(4000); g_print(2) stuff is going to happen now..\n); global_int = 1; SetEvent(windows_event); g_print(2) I'm done\n); return 0; } int main(int argc, char **argv) { DWORD error_code; gchar *error_string; GSource *g_source; g_print(1) I'm thread #%d\n, GetCurrentThreadId()); if((windows_event = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { error_code = GetLastError(); error_string = g_win32_error_message(error_code); g_print(1) CreateEvent() failed, \%s\\n, error_string); g_free(error_string); return 1; } main_loop = g_main_loop_new(NULL, FALSE); g_timeout_add(1000, timeout_callback, NULL); g_poll_fd.events = 0; g_poll_fd.revents = G_IO_IN; g_poll_fd.fd = windows_event; memset(g_source_funcs, 0, sizeof(GSourceFuncs)); g_source_funcs.prepare = my_source_prepare; g_source_funcs.check = my_source_check; g_source_funcs.dispatch = my_source_dispatch; g_source = g_source_new(g_source_funcs, sizeof(GSource)); g_source_attach(g_source, NULL); g_source_add_poll(g_source, g_poll_fd); g_source_set_callback(g_source, my_source_callback, NULL, NULL); if(CreateThread(NULL, 0, thread_entry, NULL, 0, NULL) == NULL) { error_code = GetLastError(); error_string = g_win32_error_message(error_code); g_print(1) CreateThread() failed, \%s\\n, error_string); g_free(error_string); return 1; } g_main_loop_run(main_loop); return 0; } Thomas Stover wrote: Man, I'm almost there. First, just ignore everything having to do with win32 services. I was misreading the msdn service example. The WaitFor*() is really done on an event. So here is a stripped down demo of the progress so far. It does what I want, but then crashes before ending the event loop gracefully, which means something needs to be different. I'm sure it has something to do with the size arg to g_source_new() call, since GSource is simply: typedef struct { } GSource; Clearly I have no idea what I even want to pass to it. ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_channel_win32_new_messages() WaitForSingleObject()
On Thu, 02 Apr 2009 16:53:11 -0500 Thomas Stover tho...@wsinnovations.com wrote: Well if any lone googlers ever find this, and want to know what happened. I did fix it with this, but I still think the right way is to some how create a new structure that is inherits the GSourceFuncs and adds a place to store the event handle and the protected data (in this case global_int). If there was an example of how to create a source, or some doc on a source life cycle, that would be helpful. I did look at the source, but was quickly lost. I'm guessing the main loop architecture involves multiple sources, fds, and realization callbacks all being able to exist without extras. So for instance 1 fd could trigger 5 sources, which each result in glib calling a variable number of callbacks. If only there was more time to spend on these things I may be missing your point (I would have to read through the back-posts to make sense of it), but if you want to create your own source object to hold its own protected/private data, it is just this: struct MySource { GSource source; /* my data, such as a gpointer but it could be anything and as much member data as you want */ gpointer data; }; It is created with: MySource *my_source = (MySource*) g_source_new(source_funcs, sizeof(MySource)); /* initialise data */ my_source-data = my_object; For more information see this, in particular the section Creating new sources types: http://library.gnome.org/devel/glib/stable/glib-The-Main-Event-Loop.html An idle object may already do much of what you want. With windows, I think it uses a window event object under the hood. Chris ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_channel_win32_new_messages() WaitForSingleObject()
Chris Vine wrote: I may be missing your point (I would have to read through the back-posts to make sense of it), but if you want to create your own source object to hold its own protected/private data, it is just this: struct MySource { GSource source; /* my data, such as a gpointer but it could be anything and as much member data as you want */ gpointer data; }; It is created with: MySource *my_source = (MySource*) g_source_new(source_funcs, sizeof(MySource)); /* initialise data */ my_source-data = my_object; For more information see this, in particular the section Creating new sources types: http://library.gnome.org/devel/glib/stable/glib-The-Main-Event-Loop.html An idle object may already do much of what you want. With windows, I think it uses a window event object under the hood. Chris Dude! Yes! Your example above needs to be in that section you reference, which I missed even though I've been looking at that page all day. Now if I could just figure out how to make the g_main_loop_quit() work with out first calling g_main_loop_new(). Which would make sense to me except g_main_loop_quit() is apparently the only function that needs the g_main_loop_new() call. Even g_main_loop_run() will work with a NULL. The relationship between main loops, main contexts, defaults, and manually created ones is ambiguous at best. Anyway thanks Tor and Chris. Some notes for anyone else who is just figuring out several things like myself: -a real new source would have a constructor that would do the allocation and setup -it would also have its own functions for setting up callbacks to source specific events -I think g_source_remove_poll() would be called in related destructor, so I suppose the GPollFD structure needs to be stored in MySource as well -I guess the destructor would be the closer_callback of the GSourceFuncs parameter -the GSourceFuncs and GPollFD variables are just copied by glib when they given as parameters, so they don't need to dynamic (or global/static like my last examples) === updated conversational source (yes! no globals) === #include glib.h #include windows.h typedef struct { GSource source; HANDLE windows_event_handle; int integer; } MySource; gboolean my_source_prepare(GSource *source, gint *timeout_) { MySource *my_source = (MySource *) source; g_print(1) my_source_prepare()\n); *timeout_ = -1; return FALSE; } gboolean my_source_check(GSource *source) { MySource *my_source = (MySource *) source; g_print(1) my_source_check()\n); if(my_source-integer) { g_print(1) bam!\n); return TRUE; } return FALSE; } gboolean my_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { MySource *my_source = (MySource *) source; g_print(1) my_source_dispatch()\n); if(callback == NULL) return FALSE; return callback(user_data); } gboolean my_source_callback(gpointer data) { GMainLoop *main_loop = (GMainLoop *) data; g_print(1) my_source_callback()\n); g_main_loop_quit(main_loop); return FALSE; } gboolean timeout_callback(gpointer opaq) { g_print(1) still here...\n); return TRUE; } DWORD WINAPI thread_entry(LPVOID lpParameter) { MySource *my_source = (MySource *) lpParameter; g_print(2) I'm thread #%d\n, GetCurrentThreadId()); Sleep(4000); g_print(2) stuff is going to happen now..\n); my_source-integer = 1; SetEvent(my_source-windows_event_handle); g_print(2) I'm done\n); return 0; } int main(int argc, char **argv) { DWORD error_code; gchar *error_string; GPollFD g_poll_fd; GSourceFuncs g_source_funcs; GMainLoop *main_loop; MySource *my_source; g_print(1) I'm thread #%d\n, GetCurrentThreadId()); memset(g_source_funcs, 0, sizeof(GSourceFuncs)); g_source_funcs.prepare = my_source_prepare; g_source_funcs.check = my_source_check; g_source_funcs.dispatch = my_source_dispatch; my_source = g_source_new(g_source_funcs, sizeof(MySource)); g_source_attach(my_source, NULL); main_loop = g_main_loop_new(NULL, FALSE); g_source_set_callback(my_source, my_source_callback, main_loop, NULL); if((my_source-windows_event_handle = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { error_code = GetLastError(); error_string = g_win32_error_message(error_code); g_print(1) CreateEvent() failed, \%s\\n, error_string); g_free(error_string); return 1; } my_source-integer = 0; g_poll_fd.events = 0; g_poll_fd.revents = G_IO_IN; g_poll_fd.fd = my_source-windows_event_handle; g_source_add_poll(my_source, g_poll_fd); g_timeout_add(1000, timeout_callback, NULL); if(CreateThread(NULL, 0, thread_entry, (LPVOID) my_source, 0, NULL) == NULL) { error_code = GetLastError(); error_string = g_win32_error_message(error_code); g_print(1) CreateThread() failed, \%s\\n, error_string); g_free(error_string); return 1; } g_main_loop_run(main_loop); return 0; } === -- www.thomasstover.com ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org
Re: g_io_channel_win32_new_messages() WaitForSingleObject()
normal HANDLE and a waitable one even, that can be passed to WaitForSingleObject() and friends, then it should work to use it as the fd in a GPollFD. typedef struct { #if defined (G_OS_WIN32) GLIB_SIZEOF_VOID_P == 8 gint64 fd; #else gint fd; ok so on windows fd here is a pointer to a handle, Not a pointer to a HANDLE, but a HANDLE as such. (And it must be a waitable handle.) not the rutime lib's lookup table's integer index... You mean the C library's file descriptors? Indeed not. To use them, you need to use g_io_channel_win32_new_fd(). (Which then creates a GIOChannel, not a GPollFD. And it works only if your code uses the same C library as GLib does, normally msvcrt.dll.) any ideas what the revents mask should be? G_IO_IN I think. Very interesting. So presumably on windows poll() is really something like WaitForMultiple*()? Exactly. Check in gpoll.c. Which would mean what - a prepare that always returns FALSE w/ *timeout_ = 0, and a check that does what it what otherwise do if WaitForSingleObject() returned hot? It's best to experiment, as I said I don't recall the details by heart... and too busy to actually check now. --tml ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
g_io_channel_win32_new_messages() WaitForSingleObject()
Anyone know if you can use a win32 message io channel on arbitrary handles or just gdi windows or whatever the intended use of that is? I openly admit a don't get windows at all, so this maybe just really out there. Specifically, if I had handle returned from RegisterServiceCtrlHandler() (which as best as I can imagine in my linux centric reality is some sort alertable mutex like a futex) there are msdn examples showing WaitForSingleObject() used as an alternative to global variable polling. I'm just wondering if there is a path to glib event loop integration other than a timer and with an if statement inside. For those of you who never have to look at windows just use the above to make yourselves feel better today. For those of you that make all this stuff work on windows, I am truly grateful. ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_channel_win32_new_messages() WaitForSingleObject()
Anyone know if you can use a win32 message io channel on arbitrary handles Nope. It is just for window messages for the window indicated by the HWND parameter. Specifically, if I had handle returned from RegisterServiceCtrlHandler() (which as best as I can imagine in my linux centric reality is some sort alertable mutex like a futex) there are msdn examples showing WaitForSingleObject() used as an alternative to global variable polling. I have never used that service control API, no idea what it is used for even... But if MSDN says that the returned SERVICE_STATUS_HANDLE actually is a normal HANDLE and a waitable one even, that can be passed to WaitForSingleObject() and friends, then it should work to use it as the fd in a GPollFD. Unfortunately I don't actually know or understand the glib main loop API very well by heart, so I can't say off-hand what you then should do with such a GPollFD. Pass it to g_source_add_poll(), but for what GSource? You might need to implement your own GSource type with relevant callbacks to take care of that handle firing, and then pass such a GSource object to g_source_attach()? Sorry... --tml ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_channel_win32_new_messages() WaitForSingleObject()
Tor Lillqvist wrote: I have never used that service control API, no idea what it is used for even... oh, just the needlessly complex, 75 step, windows' equivalent to daemon() But if MSDN says that the returned SERVICE_STATUS_HANDLE actually is a normal HANDLE and a waitable one even, that can be passed to WaitForSingleObject() and friends, then it should work to use it as the fd in a GPollFD. typedef struct { #if defined (G_OS_WIN32) GLIB_SIZEOF_VOID_P == 8 gint64 fd; #else gint fd; #endif gushortevents; gushortrevents } GPollFD; ok so on windows fd here is a pointer to a handle, not the rutime lib's lookup table's integer index... any ideas what the revents mask should be? Unfortunately I don't actually know or understand the glib main loop API very well by heart, so I can't say off-hand what you then should do with such a GPollFD. Pass it to g_source_add_poll(), but for what GSource? You might need to implement your own GSource type with relevant callbacks to take care of that handle firing, and then pass such a GSource object to g_source_attach()? Sorry... --tml typedef struct { gboolean (*prepare) (GSource*source, gint *timeout_); gboolean (*check)(GSource*source); gboolean (*dispatch) (GSource*source, GSourceFunc callback, gpointeruser_data); void (*finalize) (GSource*source); /* Can be NULL */ /* For use by g_source_set_closure */ GSourceFunc closure_callback; GSourceDummyMarshal closure_marshal; /* Really is of type GClosureMarshal */ } GSourceFuncs; Very interesting. So presumably on windows poll() is really something like WaitForMultiple*()? Which would mean what - a prepare that always returns FALSE w/ *timeout_ = 0, and a check that does what it what otherwise do if WaitForSingleObject() returned hot? I'm going to try somethings... --- ww.thomasstover.com ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list