From 5f9fb860331abe6e439f900edd31e3dd4eda54a3 Mon Sep 17 00:00:00 2001 From: Lars Kanis <kanis@comcard.de> Date: Mon, 6 Jul 2015 17:54:40 +0200 Subject: [PATCH] Release GVL for FXApp#run and FXDialogBox#execute. Switch off polling-based (addChore) processing of threads Add event-based interruption of GVL-released functions. --- ext/fox16_c/FXRbApp.cpp | 39 +++++++++++++++++++++++++---- ext/fox16_c/include/FXRbApp.h | 8 ++++++ ext/fox16_c/include/FXRbDialogBox.h | 2 +- ext/fox16_c/include/gvl_wrappers.h | 32 +++++++++++++++++++++-- lib/fox16/thread.rb | 1 + swig-interfaces/FXApp.i | 6 ----- swig-interfaces/macros.i | 2 ++ 7 files changed, 76 insertions(+), 14 deletions(-) diff --git a/ext/fox16_c/FXRbApp.cpp b/ext/fox16_c/FXRbApp.cpp index 11d8bb5..b70c5db 100644 --- a/ext/fox16_c/FXRbApp.cpp +++ b/ext/fox16_c/FXRbApp.cpp @@ -36,19 +36,25 @@ extern "C" { #include <sys/time.h> /* For struct timeval */ #endif +#include <fcntl.h> + // Message map FXDEFMAP(FXRbApp) FXRbAppMap[]={ +#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) + FXMAPFUNC(SEL_IO_READ,FXRbApp::ID_CHORE_THREADS,FXRbApp::onChoreThreads), +#else FXMAPFUNC(SEL_CHORE,FXRbApp::ID_CHORE_THREADS,FXRbApp::onChoreThreads), +#endif }; // Class implementation FXRbIMPLEMENT(FXRbApp,FXApp,FXRbAppMap,ARRAYNUMBER(FXRbAppMap)) +int FXRbApp::interrupt_fds[2] = {-1, -1}; + // Constructor -FXRbApp::FXRbApp(const FXchar* appname,const FXchar* vendor) : FXApp(appname,vendor),m_bThreadsEnabled(TRUE),sleepTime(100){ - if(m_bThreadsEnabled){ - addChore(this,ID_CHORE_THREADS); - } +FXRbApp::FXRbApp(const FXchar* appname,const FXchar* vendor) : FXApp(appname,vendor),m_bThreadsEnabled(FALSE),sleepTime(100){ + setThreadsEnabled(TRUE); } @@ -67,7 +73,12 @@ void FXRbApp::setThreadsEnabled(FXbool enabled){ if(enabled){ if(!m_bThreadsEnabled){ m_bThreadsEnabled=TRUE; +#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) + pipe2(interrupt_fds, O_NONBLOCK); + addInput(interrupt_fds[0],INPUT_READ,this,ID_CHORE_THREADS); +#else addChore(this,ID_CHORE_THREADS); +#endif } } else{ @@ -88,9 +99,21 @@ FXuint FXRbApp::getSleepTime() const { return sleepTime; } +long FXRbApp::onChoreThreads(FXObject *obj,FXSelector sel,void *p){ + return FXRbApp_onChoreThreads(this, obj, sel, p); + } + +long FXRbApp_onChoreThreads_gvlcb(FXRbApp *self,FXObject *obj,FXSelector sel,void *p){ + return self->onChoreThreads_gvlcb(obj, sel, p); + } // Process threads -long FXRbApp::onChoreThreads(FXObject*,FXSelector,void*){ +long FXRbApp::onChoreThreads_gvlcb(FXObject*,FXSelector,void*){ +#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) + char byte; + // clear the pipe + read(interrupt_fds[0], &byte, 1); +#else // Pause for 'sleepTime' millseconds struct timeval wait; wait.tv_sec=0; @@ -108,11 +131,17 @@ long FXRbApp::onChoreThreads(FXObject*,FXSelector,void*){ // Re-register this chore for next time addChore(this,ID_CHORE_THREADS); +#endif // Back to work... return 1; } +#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) +void fxrb_wakeup_fox(void *){ + int l = write(FXRbApp::interrupt_fds[1], "X", 1); + } +#endif // Destructor FXRbApp::~FXRbApp(){ diff --git a/ext/fox16_c/include/FXRbApp.h b/ext/fox16_c/include/FXRbApp.h index 17375a2..68cea6f 100644 --- a/ext/fox16_c/include/FXRbApp.h +++ b/ext/fox16_c/include/FXRbApp.h @@ -38,6 +38,9 @@ inline void cls ## _detach(cls *self){ \ inline void cls ## _create(cls *self){ \ self->cls::create(); \ } \ +inline FXint cls ## _run_gvl(cls *self){ \ + return self->cls::run(); \ + } \ static void cls ## _init(cls* self,VALUE ary,bool connect){ \ int i; \ char **argv; \ @@ -114,6 +117,8 @@ class FXRbApp : public FXApp { protected: FXbool m_bThreadsEnabled; FXuint sleepTime; +public: + static int interrupt_fds[2]; protected: FXRbApp(){} public: @@ -126,6 +131,7 @@ public: }; public: long onChoreThreads(FXObject*,FXSelector,void*); + long onChoreThreads_gvlcb(FXObject*,FXSelector,void*); public: // Constructor FXRbApp(const FXchar* name,const FXchar* vendor); @@ -152,4 +158,6 @@ public: virtual ~FXRbApp(); }; +long FXRbApp_onChoreThreads_gvlcb(FXRbApp*,FXObject*,FXSelector,void*); + #endif diff --git a/ext/fox16_c/include/FXRbDialogBox.h b/ext/fox16_c/include/FXRbDialogBox.h index 883b926..4a748a4 100644 --- a/ext/fox16_c/include/FXRbDialogBox.h +++ b/ext/fox16_c/include/FXRbDialogBox.h @@ -28,7 +28,7 @@ #define FXRBDIALOGBOX_H #define DECLARE_FXDIALOGBOX_STUBS(klass) \ -inline FXuint klass ## _execute(klass* self,FXuint placement){ \ +inline FXuint klass ## _execute_gvl(klass* self,FXuint placement){ \ return self->klass::execute(placement); \ } diff --git a/ext/fox16_c/include/gvl_wrappers.h b/ext/fox16_c/include/gvl_wrappers.h index df47817..9013224 100644 --- a/ext/fox16_c/include/gvl_wrappers.h +++ b/ext/fox16_c/include/gvl_wrappers.h @@ -26,6 +26,8 @@ extern "C" { #endif } +void fxrb_wakeup_fox(void *); + #define DEFINE_PARAM_LIST1(type, ref, name) \ , name @@ -71,7 +73,7 @@ extern __thread int g_fxrb_thread_has_gvl; struct gvl_wrapper_##klass##_##name##_params params = { \ {firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST1)}, when_non_void((rettype)0) \ }; \ - rb_thread_call_without_gvl(gvl_##klass##_##name##_skeleton, ¶ms, RUBY_UBF_IO, 0); \ + rb_thread_call_without_gvl(gvl_##klass##_##name##_skeleton, ¶ms, fxrb_wakeup_fox, 0); \ when_non_void( return params.retval; ) \ } #else @@ -147,6 +149,11 @@ extern __thread int g_fxrb_thread_has_gvl; #define FOR_EACH_PARAM_OF_FXImage_savePixels(param) \ param(FXStream, &, store) +#define FOR_EACH_PARAM_OF_FXDialogBox_execute(param) \ + param(FXuint, , placement) + +#define FOR_EACH_PARAM_OF_FXApp_run(param) + /* function( class, name, baseclass, void_or_nonvoid, returntype, firstparamtype, firstparamname ) */ #define FOR_EACH_BLOCKING_FUNCTION(function) \ function(FXImage, loadPixels, FXImage, GVL_TYPE_NONVOID, bool, FXImage *, self) \ @@ -200,7 +207,22 @@ extern __thread int g_fxrb_thread_has_gvl; function(FXXBMIcon, loadPixels, FXImage, GVL_TYPE_NONVOID, bool, FXXBMIcon *, self) \ function(FXXBMIcon, savePixels, FXImage, GVL_TYPE_NONVOID, bool, const FXXBMIcon *, self) \ function(FXXPMIcon, loadPixels, FXImage, GVL_TYPE_NONVOID, bool, FXXPMIcon *, self) \ - function(FXXPMIcon, savePixels, FXImage, GVL_TYPE_NONVOID, bool, const FXXPMIcon *, self) + function(FXXPMIcon, savePixels, FXImage, GVL_TYPE_NONVOID, bool, const FXXPMIcon *, self) \ + function(FXChoiceBox, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXChoiceBox *, self) \ + function(FXColorDialog, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXColorDialog *, self) \ + function(FXDialogBox, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXDialogBox *, self) \ + function(FXDirDialog, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXDirDialog *, self) \ + function(FXFileDialog, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXFileDialog *, self) \ + function(FXFontDialog, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXFontDialog *, self) \ + function(FXInputDialog, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXInputDialog *, self) \ + function(FXMessageBox, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXMessageBox *, self) \ + function(FXPrintDialog, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXPrintDialog *, self) \ + function(FXProgressDialog, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXProgressDialog *, self) \ + function(FXReplaceDialog, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXReplaceDialog *, self) \ + function(FXSearchDialog, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXSearchDialog *, self) \ + function(FXWizard, execute, FXDialogBox, GVL_TYPE_NONVOID, FXuint, FXWizard *, self) \ + function(FXApp, run, FXApp, GVL_TYPE_NONVOID, FXint, FXApp *, self) \ + FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL ) @@ -470,6 +492,11 @@ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL ) param(TYPE1, , arg1) \ param(TYPE2, , arg2) +#define FOR_EACH_PARAM_OF_FXRbApp_onChoreThreads_4(param) \ + param(ID, , func) \ + param(TYPE1, , arg1) \ + param(TYPE2, , arg2) + /* function( name, void_or_nonvoid, returntype, firstparamtype, firstparamname, paramcount ) */ #define FOR_EACH_CALLBACK_FUNCTION(function) \ @@ -524,6 +551,7 @@ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL ) function(FXRbCallDCDrawMethod, GVL_TYPE_VOID, void, RECV, recv, 6) \ function(FXRbCallTreeItemMethod, GVL_TYPE_NONVOID, FXTreeItem*, RECV, recv, 4) \ function(FXRbCallFoldingItemMethod, GVL_TYPE_NONVOID, FXFoldingItem*, RECV, recv, 4) \ + function(FXRbApp_onChoreThreads, GVL_TYPE_NONVOID, long, RECV, recv, 4) \ FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB_DECL ) diff --git a/lib/fox16/thread.rb b/lib/fox16/thread.rb index 0cf58ee..902b8e8 100644 --- a/lib/fox16/thread.rb +++ b/lib/fox16/thread.rb @@ -24,6 +24,7 @@ module Fox gs = TCPServer.open('localhost', 0) prd = TCPSocket.open('localhost', gs.addr[1]) pwr = gs.accept + gs.close else prd, pwr = IO.pipe end diff --git a/swig-interfaces/FXApp.i b/swig-interfaces/FXApp.i index f25f8b4..f3aa4b0 100644 --- a/swig-interfaces/FXApp.i +++ b/swig-interfaces/FXApp.i @@ -397,12 +397,6 @@ public: /// Perform one event dispatch; return true if event was dispatched bool runOneEvent(bool blocking=true); - /** - * Run the main application event loop until stop() is called, - * and return the exit code passed as argument to stop(). - */ - FXint run(); - /** * Run an event loop till some flag becomes non-zero, and * then return. diff --git a/swig-interfaces/macros.i b/swig-interfaces/macros.i index 8ed1e82..3349425 100644 --- a/swig-interfaces/macros.i +++ b/swig-interfaces/macros.i @@ -31,6 +31,8 @@ /// Detach application's windows virtual void detach(); + FXint run(); + /** * Initialize application. * Parses and removes common command line arguments, reads the registry. -- GitLab