Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
Hi, "Please ignore anyone who says "I don't need it so you can't have it" - but, obviously, it has to be a solution that causes them no pain when/if it does go in, and your proposal sounds just like that to me." I do not know if it was addressed to me. But I will answer anyway. I not agaist IupPostMessage. Ok. I against windows only implementation proposal, which adds, unnecessary extra bagage to slow platform! IUP have a lots features like windows only, GTK only. Everything I request is use a PostMessage function in windows implementation. Which requires use IUP function IupSetAttributeHandle to work. Using PostMessage it is not necessary touch windows event loop and add filters hooks inside IUP Windows Driver. Anyway, Eric proposal add one skilled filter IWIN_POSTMESSAGE_ID. Now if anybody wants add more filters? Easily we will soon have array of filters inside windows loop. Best regards, Ranier Vilela -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
Hi there Eric, Thank you for looking at this - I just wanted to add my approval. I certainly get the point about battery life. The project I am currently working uses a background thread to handle a websocket feed, which arrives every 10s or so. While an IupTimer works, I run it at 10 times a second while my collaborator thinks it should be 100 times a second, so it consumes 100-1000 times as much power as it needs to. All I need is a way for a background thread to say "oi" when it has finished some calculation, downloaded a file, or received a websocket message - maybe I might want to be helpful and include an IupHandle in the message, often not - it is the responsibility of the main gui thread to map any such events to specific gui elements, and quite often not a 1:1 relationship anyway. Please ignore anyone who says "I don't need it so you can't have it" - but, obviously, it has to be a solution that causes them no pain when/if it does go in, and your proposal sounds just like that to me. Pete -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
Hi, "IUP should not be the solution to every problem. It would be like incorporating a cross-platform C-runtime into IUP when that is the wrong approach. IUP is great as it is and for specialized problems it will never be able to beat a mature third party app, and right now my favorite app for the kinds of issues you are discussing is ØMQ (http://zeromq.org), but I'm sure there are other apps out there that will do just fine." I think that IUP can be used in threads apps too. But. Without add framework, and extra bagage for this. Update GUI outside main thread, is very danger and can crash easily app. Gold rule, don't update GUI outside main thread! Use callbacks for this. Windows have a PostMessage function, that solves correctly this problem. IupPostMessage is welcome, but, whithout change behavior to non-threaded apps. Best Regards, Ranier Vilela -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
Hi, "This proposal is a tiny patch to IUP, one that nobody except the implementors will notice. It does not break current behavior or create any trade offs. But it solves real problems deal with the fact that the real world uses threads, even inside the native platforms. If you don't have this problem, then it doesn't matter because this change won't affect you." I can not agree. 99% percent of GUI app are non-threaded. Your patch, change this behavior add one function call to every message received by event loop, unnecessary, to non-threaded apps. Best regards, Ranier Vilela -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
Hi, "I think we're in agreement here. The idea of "IupPostMessage", inspired from Windows PostMessage solves this problem elegantly. The implementation specific ways to pull this off on each platform are hidden from the user perspective." Great. "From my "Idea 2" proposal, what I'm suggesting is the IUP API should be able to take *any* Ihandle*. // All I want to do is change my button's ACTIVE state. IupPostMessage(my_iup_button, 42, audio_data);" Use IUP style and tools. IupSetAttributeHandle(my_iup_button, "the_dialog", the_dialog); Now you have a native handler (windows handler) inside your button widget and easy use PostMessage to solve GUI update without add any cost and more unnecessary functions calls "This is more natural in how people may want to use it. I want to change the button. From an objective standpoint, if I just want to change the button, it makes no sense to think about a dialog. So I think it is less reasonable to demand that I do: // All I want to do is change my button's ACTIVE state. Why am I passing a dialog? IupPostMessage(some_dialog, 42, audio_data); And then in the callback, figure out how to get my_iup_button." Again, IUP have a style for this. "I don't think this is a legitimate or fair argument. Unless you can demonstrate in a real world context where this one call will have a measurable performance impact, the cost of this one instruction is a rounding error. (There's quite a bit of other stuff you would want to focus on first in the IUP codebase if you were worried about this minutia of performance.) Remember, we're talking about Windows where they've optimized the heck out of this low-level stuff and everybody is on powerful CPUs with branch-prediction and tons of cache. We're not talking about 6502's here." IUP have a lot slow algorithms: array dynamic implementation is very inefficient, hash string too. Add more inefficiencies do not help. Kiss please. Less is more. "I think we agree again." Good to know. "I merely argue that PostThreadMessage is a better, more general, and more correct solution than PostMessage. If PostMessage can be made to work and address the shortcomings I believe it has, then I would happily give it my blessing. Ultimately, this is an implementation issue. It's only constraint is what we want the public API to be able to handle. Nobody in the end is going to know the difference if we do it right." Again, Raymond Chen, explain: "The correct solution was illustrated last time." https://blogs.msdn.microsoft.com/oldnewthing/20050427-10/?p=35763 PostTheardMessage is the complicated and wrong way to solve this. "Again, I think that is a very unfair accusation to level against me. I have presented a working prototype, a specification of the feature, and a general implementation plan." I'm sorry, but technical arguments is welcome, bogus arguments not. "As part of the Windows specific implementation, I include explanation of why I think PostThreadMessage is better than PostMessage: because it allows us to construct a general API that takes any widget, allowing the user focus on any widget instead of a just a dialog. If I misunderstand how PostMessage works, and it can be used for arbitrary controls (e.g. the button and not just dialogs), then I will happily cede to that point. That is the thing I hope somebody will address, but so far, nobody has corrected that specific point." Again, using IUP style and tools. Add reference to your controls and you have all necessary to make the work. Best regards, Ranier Vilela -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
Eric, I'm afraid your comment bdelow does not make much sense to me. Also I did not suggest any polling. On Apr 19 2018, Eric Wing wrote: On 4/19/18, Jörg F. Wittenberger wrote: On Apr 19 2018, Eric Wing wrote: Since there seems to be so much concern and speculation about the size, complexity, and implementation of what the patch might look like, I went ahead and implemented a fully working version for Windows and GTK to provide something completely concrete to review. I'm afraid there was little concern or speculation about size and complexity. The only concerns I read where calling into question whether or not it was a good idea at all. Thus suggestions flowing your way how others would solve or have solved the issue. That is fair, up to a point. There was lengthy discussion on PostMessage vs. PostThreadMessage and the consequences of such. To respond to your previous post/solution...(the IupFlush clarification), your solution actually could work. I could create an IupTimer and externally poll. But this has a major downside in battery consumption...and the higher the responsiveness, the worst the consumption. Modern native event loops are highly optimized to not do work when nothing needs to be done. (Set a breakpoint after Windows GetMessage, and it is fascinating how often it just sits there not moving.) Polling though an external mechanism means burning cycles even when not needed, which also means modern CPUs which have automatic throttling can't usually do so in this scenario. This is why all the platforms designed their own event-loops and intertwined their GUI infrastructure with it, and why IUP had to abstract the native event loops in the first place. For the use cases I need, this unfortunately is not an acceptable trade-off. And I think in general, there is no good reason to have to make this trade-off. A cross-platform yet native solution is only a handful lines of code because the native platforms intended to solve this very problem already and expected you to use it. For the cases where polling and burning CPU is acceptable, those are typically games. There we are used to having non-native event loops... SDL is an example of providing such a loop. But even SDL has the capability of posting custom messages to its event queue to deal with these exact same kinds of threading issues. Thank you for the suggestion though. I understand you were sincerely trying to solve my problem. Thanks, Eric -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
On 4/19/18, Jörg F. Wittenberger wrote: > On Apr 19 2018, Eric Wing wrote: > >>Since there seems to be so much concern and speculation about the >>size, complexity, and implementation of what the patch might look >>like, I went ahead and implemented a fully working version for Windows >>and GTK to provide something completely concrete to review. > > I'm afraid there was little concern or speculation about size and > complexity. The only concerns I read where calling into question whether or > > not it was a good idea at all. Thus suggestions flowing your way how others > > would solve or have solved the issue. > That is fair, up to a point. There was lengthy discussion on PostMessage vs. PostThreadMessage and the consequences of such. To respond to your previous post/solution...(the IupFlush clarification), your solution actually could work. I could create an IupTimer and externally poll. But this has a major downside in battery consumption...and the higher the responsiveness, the worst the consumption. Modern native event loops are highly optimized to not do work when nothing needs to be done. (Set a breakpoint after Windows GetMessage, and it is fascinating how often it just sits there not moving.) Polling though an external mechanism means burning cycles even when not needed, which also means modern CPUs which have automatic throttling can't usually do so in this scenario. This is why all the platforms designed their own event-loops and intertwined their GUI infrastructure with it, and why IUP had to abstract the native event loops in the first place. For the use cases I need, this unfortunately is not an acceptable trade-off. And I think in general, there is no good reason to have to make this trade-off. A cross-platform yet native solution is only a handful lines of code because the native platforms intended to solve this very problem already and expected you to use it. For the cases where polling and burning CPU is acceptable, those are typically games. There we are used to having non-native event loops... SDL is an example of providing such a loop. But even SDL has the capability of posting custom messages to its event queue to deal with these exact same kinds of threading issues. Thank you for the suggestion though. I understand you were sincerely trying to solve my problem. Thanks, Eric -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
On Apr 19 2018, Eric Wing wrote: Since there seems to be so much concern and speculation about the size, complexity, and implementation of what the patch might look like, I went ahead and implemented a fully working version for Windows and GTK to provide something completely concrete to review. I'm afraid there was little concern or speculation about size and complexity. The only concerns I read where calling into question whether or not it was a good idea at all. Thus suggestions flowing your way how others would solve or have solved the issue. Best /Jörg ... -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
On Apr 18 2018, Matt Welland wrote: On Wed, Apr 18, 2018 at 1:23 AM, Jörg F. Wittenberger < joerg.wittenber...@softeyes.net> wrote: Hi, just my two cents. On Apr 16 2018, Eric Wing wrote: This is a proposal to introduce a way to post and run events on the main UI thread. Currently (as far as I know), IUP is hands-off on threads. ... It's easy to see the problem you're facing. I'm no IUP expert, however I'm pretty positive that this can be solved without introducing another API. In a similar situation I have been able to abstain from using the complete IUP abstraction around the main loop and resort to using IupFlush() instead. Doing so allows to queue requests from other threads for execution in the GUI thread, which processes said queue right before calling IupFlush(). Once I had these roughly 40 lines of code in place begin factoring out IupFlush()s and run them just once before IupFlush() to reduce some flickering. Maybe such an approach can work for you too. Hi Jörg, this approach sounds really interesting. Can you provide a little more detail to clarify how this works? Do you put calls to set attribute in the queue and then periodically execute the calls in the queue followed by an IupFlush? I tried this (using the Chicken Scheme IUP binding) and it seems to work well but I'm concerned there are corner cases to be accounted for. My (probably naive) test implementation of your approach is pasted below. Hi Matt, Exactly that's what I did. (Slightly more elaborate than your example code, e.g. using a configurable sleep time and not using thread-sleep! but waiting with timeout on a condition-variable, which has the added advantage that urgent signals can easily terminate the wait by signaling the condition variable, while non-critical changes may be postponed until the regular update takes place.) But the principle is the same. Yes, you are right, there can be corner cases. You really, really want to be sure that your Iup callbacks don't capture continuations. But it is a while ago that this was fixed right in the iup egg. From your code I'm afraid another such corner case would be whether or not you empty the queue one-by-one (as I would suggest) or all at once. Your case of doing the latter but flushing the queue only _after_ processing it looks a bit error prone to me. BEst /Jörg Best /Jörg -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users ;; trial of replacing iup:main-loop with a queue (use (prefix iup iup:) srfi-18) (define *queue* '()) (define *queue-mutex* (make-mutex)) (define (process-queue) (for-each (lambda (entry)(entry))(reverse *queue*)) (print "processed queue") (set! *queue* '())) (define (iattr . params) (mutex-lock! *queue-mutex*) (if (not (null? *queue*)) (process-queue)) (let ((result (apply iup:attribute params))) (mutex-unlock! *queue-mutex*) result)) (define (iattr-set! . params) (mutex-lock! *queue-mutex*) (set! *queue* (cons (lambda ()(apply iup:attribute-set! params)) *queue*)) (mutex-unlock! *queue-mutex*)) (define button1 (iup:button "Push me" action: (lambda (o) (print "Got here at " (current-seconds)) (iattr-set! o "BGCOLOR" "255 255 255" (define tl (iup:show (iup:dialog (iup:vbox button1 (iup:button "Exit" action: (lambda (o)(exit))) (define (main) (let* ((th1 (make-thread (lambda () (let loop () (mutex-lock! *queue-mutex*) (process-queue) (mutex-unlock! *queue-mutex*) (iup:main-loop-flush) (thread-sleep! 1) ;; use a really long delay just for illustration (loop))) "flush loop")) (th2 (make-thread (lambda () (let loop () (print "set to green") (iattr-set! button1 "BGCOLOR" "70 249 73") (thread-sleep! 0.2) (print "set to red") (iattr-set! button1 "BGCOLOR" "253 33 49") (thread-sleep! 0.2) (loop) (th3 (make-thread (lambda () (let loop () (print (iattr button1 "BGCOLOR")) (thread-sleep! (random 5)) (loop)) (thread-start! th1) (thread-start! th2) (thread-start! th3) (thread-join! th1))) (main) -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
Since there seems to be so much concern and speculation about the size, complexity, and implementation of what the patch might look like, I went ahead and implemented a fully working version for Windows and GTK to provide something completely concrete to review. You can find the repo here: https://github.com/ewmailing/IupCocoa/tree/IupPostMessage Make sure you clone/switch to the IupPostMessage branch. The IupPostMessage() as implemented is not intended to be final form. There are 4 parameters (2 unused) because I didn’t feel like adding a new callback type to iupcbs.h until we made a final decision on the API. Also, I decided to rename my proposed “UITHREAD” to “POSTMESSAGE_CB”. I’m also attaching the patch for those who find it convenient, as it is small enough to include in this post without exceeding the mailing list maximum post size threshold. My source tree was originally based off of SVN revision 4768. The repo also contains a test program called postmessage.c in html/examples/tests. (The diff/patch didn’t capture it since it is a new file.) It is a single-threaded example showing that it is also usable in single threaded situations, i.e. those who just want to schedule an event to fire on the next event-loop pass. Those familiar with certain async patterns may recognize this. I also added a version 2 of the IupALmixerThreads example which now uses this patch as a test and further demonstration. https://bitbucket.org/ewing/iupalmixerthread2 Thanks, Eric diff --git a/html/examples/tests/config.mak b/html/examples/tests/config.mak index 0910be9..7ab409f 100644 --- a/html/examples/tests/config.mak +++ b/html/examples/tests/config.mak @@ -46,6 +46,7 @@ SRC += dialog.c SRC += calendar.c SRC += predialogs.c SRC += timer.c +SRC += postmessage.c SRC += label.c SRC += canvas.c SRC += frame.c diff --git a/include/iup.h b/include/iup.h index 1c67a3f..9eac444 100644 --- a/include/iup.h +++ b/include/iup.h @@ -42,6 +42,7 @@ int IupLoopStepWait (void); int IupMainLoopLevel (void); void IupFlush (void); void IupExitLoop (void); +void IupPostMessage (Ihandle* ih, char*, void* message_data, int); int IupRecordInput(const char* filename, int mode); int IupPlayInput(const char* filename); diff --git a/src/gtk/iupgtk_loop.c b/src/gtk/iupgtk_loop.c index f156607..61fd14d 100644 --- a/src/gtk/iupgtk_loop.c +++ b/src/gtk/iupgtk_loop.c @@ -6,6 +6,7 @@ #include #include +#include #include @@ -113,3 +114,33 @@ void IupFlush(void) if (old_gtk_idle_cb) iupdrvSetIdleFunction((Icallback)old_gtk_idle_cb); } + + +typedef struct { + Ihandle* ih; + void* messageData; +} gtkPostMessageUserData; + +static gint gtkPostMessageCallback(void *user_data) +{ + gtkPostMessageUserData* message_user_data = (gtkPostMessageUserData*)user_data; + Ihandle* ih = message_user_data->ih; + /* TODO: Figure out callback type. For now, I'm reusing an existing type so I don't have to add one until we decide. */ + IFnsVi post_message_callback = (IFnsVi)IupGetCallback(ih, "POSTMESSAGE_CB"); + if (post_message_callback) + { +void* message_data = message_user_data->messageData; +post_message_callback(ih, NULL, message_data, 0); + } + free(user_data); + return FALSE; // call only once +} + +/* TODO: Make decision on final API. For now, this API is just to get a usable demo. */ +void IupPostMessage(Ihandle* ih, char* unusedchar, void* message_data, int unusedint) +{ + gtkPostMessageUserData* user_data = (gtkPostMessageUserData*)malloc(sizeof(gtkPostMessageUserData)); + user_data->ih = ih; + user_data->messageData = message_data; + g_idle_add(gtkPostMessageCallback, user_data); +} diff --git a/src/iup.def b/src/iup.def index bbbd45a..69b3278 100644 --- a/src/iup.def +++ b/src/iup.def @@ -260,6 +260,7 @@ IupDial IupGauge IupColorbar IupColorBrowser +IupPostMessage iupdrvSetVisible iupdrvSetFontAttrib diff --git a/src/iup_classbase.c b/src/iup_classbase.c index 7620c72..95868fc 100644 --- a/src/iup_classbase.c +++ b/src/iup_classbase.c @@ -571,6 +571,7 @@ void iupBaseRegisterCommonCallbacks(Iclass* ic) iupClassRegisterCallback(ic, "ENTERWINDOW_CB", ""); iupClassRegisterCallback(ic, "LEAVEWINDOW_CB", ""); iupClassRegisterCallback(ic, "HELP_CB", ""); + iupClassRegisterCallback(ic, "POSTMESSAGE_CB", ""); iupClassRegisterCallback(ic, "K_ANY", "i"); } diff --git a/src/win/iupwin_drv.h b/src/win/iupwin_drv.h index ca66b82..22d3eda 100644 --- a/src/win/iupwin_drv.h +++ b/src/win/iupwin_drv.h @@ -17,7 +17,8 @@ extern "C" { extern HINSTANCE iupwin_hinstance; /* iupwin_open.c */ extern int iupwin_comctl32ver6; /* iupwin_open.c */ extern HINSTANCE iupwin_dll_hinstance; /* iupwindows_main.c */ - +extern DWORD iupwin_mainthreadid; /* iupwin_open.c, iupwin_loop.c */ +extern HHOOK iupwin_threadmsghook; /* iupwin_open.c, iupwin_loop.c */ /* open */ void iupwinShowLastError(void); @@ -104,6 +
Re: [Iup-users] Formal proposal for a "postMessage" API to send messages to run on the UI thread
Eric, sorry, you missunderstood my proposed solution. I wanted to suggest to NOT put additional events into whatever queue Iup uses behind the scenes. Instead better maintain you own queue and process this before you complete Iup's queue once using IupFlush. On Apr 18 2018, Eric Wing wrote: It's easy to see the problem you're facing. I'm no IUP expert, however I'm pretty positive that this can be solved without introducing another API. In a similar situation I have been able to abstain from using the complete IUP abstraction around the main loop and resort to using IupFlush() instead. Doing so allows to queue requests from other threads for execution in the GUI thread, which processes said queue right before calling IupFlush(). Once I had these roughly 40 lines of code in place begin factoring out IupFlush()s and run them just once before IupFlush() to reduce some flickering. Maybe such an approach can work for you too. Thanks for the idea. But I don't think IupFlush() addresses the problem. IupFlush() solves a problem of needing to process a request immediately already in the event queue. But the missing piece of the puzzle is *how to put an event (from another thread) into the event queue*. -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Iup-users mailing list Iup-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iup-users