diff options
-rw-r--r-- | externals/grill/flext/buildsys/lnx/gnumake-gcc-flext.inc | 2 | ||||
-rw-r--r-- | externals/grill/flext/buildsys/lnx/gnumake-icc-ext.inc | 2 | ||||
-rw-r--r-- | externals/grill/flext/buildsys/lnx/gnumake-icc-flext.inc | 10 | ||||
-rw-r--r-- | externals/grill/flext/buildsys/lnx/gnumake-icc.inc | 1 | ||||
-rw-r--r-- | externals/grill/flext/changes.txt | 2 | ||||
-rw-r--r-- | externals/grill/flext/notes.txt | 1 | ||||
-rw-r--r-- | externals/grill/flext/source/flattr_ed.cpp | 147 | ||||
-rw-r--r-- | externals/grill/flext/source/flcontainers.h | 8 | ||||
-rwxr-xr-x | externals/grill/flext/source/flprefix.h | 30 | ||||
-rwxr-xr-x | externals/grill/flext/source/flsimd.cpp | 4 | ||||
-rw-r--r-- | externals/grill/flext/source/flsupport.h | 31 | ||||
-rw-r--r-- | externals/grill/flext/source/flthr.cpp | 484 | ||||
-rwxr-xr-x | externals/grill/flext/source/fltimer.cpp | 1 |
13 files changed, 365 insertions, 358 deletions
diff --git a/externals/grill/flext/buildsys/lnx/gnumake-gcc-flext.inc b/externals/grill/flext/buildsys/lnx/gnumake-gcc-flext.inc index 93db3313..3a84d399 100644 --- a/externals/grill/flext/buildsys/lnx/gnumake-gcc-flext.inc +++ b/externals/grill/flext/buildsys/lnx/gnumake-gcc-flext.inc @@ -61,6 +61,6 @@ $(FLEXTLIBINST): _install_: $(FLEXTINC) $(FLEXTLIBINST) install $(TARGET) $(FLEXTLIBINST) ifdef SHARED - ldconfig -l $(TARGET) + /sbin/ldconfig -l $(TARGET) endif install $(patsubst %,$(SRCDIR)/%,$(HDRS)) $(FLEXTINC) diff --git a/externals/grill/flext/buildsys/lnx/gnumake-icc-ext.inc b/externals/grill/flext/buildsys/lnx/gnumake-icc-ext.inc index 4ce1c1da..58bb7c3d 100644 --- a/externals/grill/flext/buildsys/lnx/gnumake-icc-ext.inc +++ b/externals/grill/flext/buildsys/lnx/gnumake-icc-ext.inc @@ -1,5 +1,7 @@ # build class specific settings +TARGET=$(TARGETPATH)/$(OUTNAME).$(EXT) + INCPATH += -I$(FLEXTINC) LIBPATH += -L$(FLEXTLIB) -L$(FLEXTSHLIB) LIBS += -l$(FLEXTNAME) diff --git a/externals/grill/flext/buildsys/lnx/gnumake-icc-flext.inc b/externals/grill/flext/buildsys/lnx/gnumake-icc-flext.inc index ed06f9cf..8c106e7c 100644 --- a/externals/grill/flext/buildsys/lnx/gnumake-icc-flext.inc +++ b/externals/grill/flext/buildsys/lnx/gnumake-icc-flext.inc @@ -1,5 +1,12 @@ # build class specific settings +ifdef SHARED +SONAME=$(OUTNAME).$(EXT) +TARGET=$(TARGETPATH)/$(OUTNAME).$(PKGVERSION).$(EXT) +else +TARGET=$(TARGETPATH)/$(OUTNAME).$(EXT) +endif + ############################################## # default target @@ -53,4 +60,7 @@ $(FLEXTLIBINST): _install_: $(FLEXTINC) $(FLEXTLIBINST) install $(TARGET) $(FLEXTLIBINST) +ifdef SHARED + /sbin/ldconfig -l $(TARGET) +endif install $(patsubst %,$(SRCDIR)/%,$(HDRS)) $(FLEXTINC) diff --git a/externals/grill/flext/buildsys/lnx/gnumake-icc.inc b/externals/grill/flext/buildsys/lnx/gnumake-icc.inc index 2797e882..96d3d642 100644 --- a/externals/grill/flext/buildsys/lnx/gnumake-icc.inc +++ b/externals/grill/flext/buildsys/lnx/gnumake-icc.inc @@ -2,7 +2,6 @@ OBJPATH=$(OUTPATH)/$(OUTSUB) TARGETPATH=$(OBJPATH) -TARGET=$(TARGETPATH)/$(OUTNAME).$(EXT) ############################################## diff --git a/externals/grill/flext/changes.txt b/externals/grill/flext/changes.txt index e1248969..81ed3b30 100644 --- a/externals/grill/flext/changes.txt +++ b/externals/grill/flext/changes.txt @@ -33,7 +33,7 @@ Version history: - added some more SIMD functionality - fixes to flext::Timer::At method - eliminated misleading flext_dsp::ChannelsIn and ChannelsOut -- added lock-free Lifo and Fifo structures and used it with message queueing +- added lock-free Lifo and Fifo structures and used it with message queueing and thread management 0.4.7: - added flext::GetBool (just because flext::GetInt has been there for a while) diff --git a/externals/grill/flext/notes.txt b/externals/grill/flext/notes.txt index 97fefdeb..aed2641b 100644 --- a/externals/grill/flext/notes.txt +++ b/externals/grill/flext/notes.txt @@ -40,6 +40,7 @@ TODO LIST: - optimizations for object initialization and messaging
- speed up message handling (usage of other containers?)
- SIMD for gcc
+- lock-free code for 64-bit architectures
- update documentation
- add log messages for debugging version
diff --git a/externals/grill/flext/source/flattr_ed.cpp b/externals/grill/flext/source/flattr_ed.cpp index 6e13e71c..16a418a3 100644 --- a/externals/grill/flext/source/flattr_ed.cpp +++ b/externals/grill/flext/source/flattr_ed.cpp @@ -251,46 +251,45 @@ static void tclscript() "wm title $id $title\n" "wm protocol $id WM_DELETE_WINDOW [concat flext_cancel $id]\n" + "frame $id.frame\n" "set row 0\n" // set grow parameters - "grid columnconfigure $id 0 -weight 1\n" // label - "grid columnconfigure $id {1 4} -weight 3\n" // value entry - "grid columnconfigure $id {2 3} -weight 0\n" // copy buttons - "grid columnconfigure $id 5 -weight 1\n" // apply button - "grid columnconfigure $id {6 7 8} -weight 0\n" // radio buttons + "grid columnconfigure $id.frame 0 -weight 1\n" // label + "grid columnconfigure $id.frame {1 4} -weight 3\n" // value entry + "grid columnconfigure $id.frame {2 3} -weight 0\n" // copy buttons + "grid columnconfigure $id.frame 5 -weight 1\n" // apply button + "grid columnconfigure $id.frame {6 7 8} -weight 0\n" // radio buttons -// "grid rowconfigure $id {0 1 2} -weight 0\n" + "grid rowconfigure $id.frame {0 1} -weight 0\n" // set column labels - "label $id.label -text {attribute} -height 2 -font {Helvetica 9 bold}\n" - "label $id.init -text {initial value} -height 2 -font {Helvetica 9 bold}\n" - "label $id.copy -text {copy} -height 2 -font {Helvetica 9 bold}\n" - "label $id.val -text {current value} -height 2 -font {Helvetica 9 bold}\n" - "label $id.apply -text {} -height 2 -font {Helvetica 9 bold}\n" // why must this be empty? + "label $id.frame.label -text {attribute} -font {Helvetica 9 bold}\n" + "label $id.frame.init -text {initial value} -font {Helvetica 9 bold}\n" + "label $id.frame.copy -text {copy} -font {Helvetica 9 bold}\n" + "label $id.frame.val -text {current value} -font {Helvetica 9 bold}\n" + "label $id.frame.apply -text {} -font {Helvetica 9 bold}\n" // why must this be empty? "foreach {i txt} {0 {don't\rsave} 1 {do\rinit} 2 {always\rsave} } {\n" - "label $id.b$i -text $txt -height 2 -font {Helvetica 9 bold}\n" + "label $id.frame.b$i -text $txt -font {Helvetica 7 bold}\n" "}\n" -// "label $id.options -text {options} -height 2\n" - - "grid config $id.label -column 0 -row $row \n" - "grid config $id.init -column 1 -row $row \n" - "grid config $id.copy -column 2 -columnspan 2 -row $row \n" - "grid config $id.val -column 4 -row $row \n" - "grid config $id.apply -column 5 -row $row \n" - "foreach i {0 1 2} { grid config $id.b$i -column [expr $i + 6] -row $row }\n" -// "grid config $id.options -column 3 -row 0 \n" + + "grid config $id.frame.label -column 0 -row $row \n" + "grid config $id.frame.init -column 1 -row $row \n" + "grid config $id.frame.copy -column 2 -columnspan 2 -row $row \n" + "grid config $id.frame.val -column 4 -row $row \n" + "grid config $id.frame.apply -column 5 -row $row \n" + "foreach i {0 1 2} { grid config $id.frame.b$i -column [expr $i + 6] -row $row }\n" "incr row\n" // Separator - "frame $id.sep -relief ridge -bd 1 -height 2\n" - "grid config $id.sep -column 0 -columnspan 9 -row $row -pady 2 -sticky {snew}\n" + "frame $id.frame.sep -relief ridge -bd 1 -height 2\n" + "grid config $id.frame.sep -column 0 -columnspan 9 -row $row -pady 2 -sticky {snew}\n" "incr row\n" ); sys_vgui( "set ix 1\n" "foreach {an av ai atp asv afl} $attrlist {\n" - "grid rowconfigure $id $row -weight 0\n" + "grid rowconfigure $id.frame $row -weight 1\n" // get attribute name "set var_attr_name [concat [concat var_name_$ix]_$vid ]\n" @@ -320,8 +319,8 @@ static void tclscript() // add dialog elements to window // attribute label - "label $id.label-$ix -text \"$an :\" -font {Helvetica 8 bold}\n" - "grid config $id.label-$ix -column 0 -row $row -padx 5 -sticky {e}\n" + "label $id.frame.label-$ix -text \"$an :\" -font {Helvetica 8 bold}\n" + "grid config $id.frame.label-$ix -column 0 -row $row -padx 5 -sticky {e}\n" ); sys_vgui( "if { $afl != 0 } {\n" @@ -333,45 +332,42 @@ static void tclscript() // choose entry field type "switch $atp {\n" "0 - 1 {\n" // int or float - "entry $id.init-$ix -textvariable $var_attr_init\n" - "entry $id.val-$ix -textvariable $var_attr_val\n" + "entry $id.frame.init-$ix -textvariable $var_attr_init\n" + "entry $id.frame.val-$ix -textvariable $var_attr_val\n" "}\n" "2 {\n" // boolean - "checkbutton $id.init-$ix -variable $var_attr_init\n" - "checkbutton $id.val-$ix -variable $var_attr_val\n" + "checkbutton $id.frame.init-$ix -variable $var_attr_init\n" + "checkbutton $id.frame.val-$ix -variable $var_attr_val\n" "}\n" "3 {\n" // symbol - "entry $id.init-$ix -textvariable $var_attr_init\n" - "entry $id.val-$ix -textvariable $var_attr_val\n" + "entry $id.frame.init-$ix -textvariable $var_attr_init\n" + "entry $id.frame.val-$ix -textvariable $var_attr_val\n" "}\n" "4 - 5 {\n" // list or unknown - "entry $id.init-$ix -textvariable $var_attr_init\n" - "bind $id.init-$ix {<Control-Button-1>} \" flext_textzoom $id.init-$ix $var_attr_init { $title } $an 1\"\n" - "entry $id.val-$ix -textvariable $var_attr_val\n" - "bind $id.val-$ix {<Control-Button-1>} \" flext_textzoom $id.val-$ix $var_attr_val { $title } $an 1\"\n" + "entry $id.frame.init-$ix -textvariable $var_attr_init\n" + "bind $id.frame.init-$ix {<Control-Button-1>} \" flext_textzoom $id.frame.init-$ix $var_attr_init { $title } $an 1\"\n" + "entry $id.frame.val-$ix -textvariable $var_attr_val\n" + "bind $id.frame.val-$ix {<Control-Button-1>} \" flext_textzoom $id.frame.val-$ix $var_attr_val { $title } $an 1\"\n" "}\n" "}\n" - "grid config $id.init-$ix -column 1 -row $row -padx 5 -sticky {ew}\n" - "grid config $id.val-$ix -column 4 -row $row -padx 5 -sticky {ew}\n" + "grid config $id.frame.init-$ix -column 1 -row $row -padx 5 -sticky {ew}\n" + "grid config $id.frame.val-$ix -column 4 -row $row -padx 5 -sticky {ew}\n" // copy buttons - "button $id.b2i-$ix -text {<-} -height 1 -command \" flext_copyval $var_attr_init $var_attr_val \"\n" - "grid config $id.b2i-$ix -column 2 -row $row -sticky {ew}\n" - "button $id.b2c-$ix -text {->} -height 1 -command \" flext_copyval $var_attr_val $var_attr_init \"\n" - "grid config $id.b2c-$ix -column 3 -row $row -sticky {ew}\n" + "button $id.frame.b2i-$ix -text {<-} -height 1 -command \" flext_copyval $var_attr_init $var_attr_val \"\n" + "grid config $id.frame.b2i-$ix -column 2 -row $row -sticky {ew}\n" + "button $id.frame.b2c-$ix -text {->} -height 1 -command \" flext_copyval $var_attr_val $var_attr_init \"\n" + "grid config $id.frame.b2c-$ix -column 3 -row $row -sticky {ew}\n" // apply button - "button $id.apply-$ix -text {Apply} -height 1 -command \" flext_apply $id $ix \"\n" - "grid config $id.apply-$ix -column 5 -row $row -sticky {ew}\n" - - // "tk_optionMenu $id.opt-$ix $var_attr_save {don't save} {initialize} {always save}\n" - // "grid config $id.opt-$ix -column 5 -row $ix \n" + "button $id.frame.apply-$ix -text {Apply} -height 1 -command \" flext_apply $id $ix \"\n" + "grid config $id.frame.apply-$ix -column 5 -row $row -sticky {ew}\n" // radiobuttons "foreach {i c} {0 black 1 blue 2 red} {\n" - "radiobutton $id.b$i-$ix -value $i -foreground $c -variable $var_attr_save \n" - "grid config $id.b$i-$ix -column [expr $i + 6] -row $row \n" + "radiobutton $id.frame.b$i-$ix -value $i -foreground $c -variable $var_attr_save \n" + "grid config $id.frame.b$i-$ix -column [expr $i + 6] -row $row \n" "}\n" ); sys_vgui( @@ -383,55 +379,58 @@ static void tclscript() // choose display field type "switch $atp {\n" "0 - 1 {\n" // int or float - "entry $id.val-$ix -textvariable $var_attr_val -state disabled\n" + "entry $id.frame.val-$ix -textvariable $var_attr_val -state disabled\n" "}\n" "2 {\n" // boolean - "checkbutton $id.val-$ix -variable $var_attr_val -state disabled\n" + "checkbutton $id.frame.val-$ix -variable $var_attr_val -state disabled\n" "}\n" "3 {\n" // symbol - "entry $id.val-$ix -textvariable $var_attr_val -state disabled\n" + "entry $id.frame.val-$ix -textvariable $var_attr_val -state disabled\n" "}\n" "4 - 5 {\n" // list or unknown - "entry $id.val-$ix -textvariable $var_attr_val -state disabled\n" - "bind $id.val-$ix {<Control-Button-1>} \" flext_textzoom $id.val-$ix $var_attr_val { $title } $an 0\"\n" + "entry $id.frame.val-$ix -textvariable $var_attr_val -state disabled\n" + "bind $id.frame.val-$ix {<Control-Button-1>} \" flext_textzoom $id.frame.val-$ix $var_attr_val { $title } $an 0\"\n" "}\n" "}\n" -// "entry $id.val-$ix -textvariable $var_attr_val -state disabled\n" - "grid config $id.val-$ix -column 4 -row $row -padx 5 -sticky {ew}\n" +// "entry $id.fval.val-$ix -textvariable $var_attr_val -state disabled\n" + "grid config $id.frame.val-$ix -column 4 -row $row -padx 5 -sticky {ew}\n" - "label $id.readonly-$ix -text \"read-only\"\n" - "grid config $id.readonly-$ix -column 6 -columnspan 3 -row $row -padx 5 -sticky {ew}\n" + "label $id.frame.readonly-$ix -text \"read-only\"\n" + "grid config $id.frame.readonly-$ix -column 6 -columnspan 3 -row $row -padx 5 -sticky {ew}\n" "}\n" // increase counter "incr ix\n" "incr row\n" "}\n" + + // empty space + "grid rowconfigure $id.frame $row -weight 1\n" + "frame $id.frame.dummy\n" + "grid config $id.frame.dummy -column 0 -columnspan 9 -row $row\n" + "incr row\n" ); sys_vgui( // Separator "frame $id.sep2 -relief ridge -bd 1 -height 2\n" -// "grid rowconfigure $id $row -weight 0\n" - "grid config $id.sep2 -column 0 -columnspan 9 -row $row -pady 5 -sticky {snew}\n" - "incr row\n" // Buttons "frame $id.buttonframe\n" - "pack $id.buttonframe -side bottom -fill x\n" "button $id.buttonframe.cancel -text {Leave} -width 20 -command \" flext_cancel $id \"\n" "button $id.buttonframe.apply -text {Apply all} -width 20 -command \" flext_applyall $id $alen \"\n" "button $id.buttonframe.ok -text {Apply & Leave} -width 20 -command \" flext_ok $id $alen \"\n" "button $id.buttonframe.help -text {Help} -width 10 -command \" flext_help $id \"\n" - "pack $id.buttonframe.cancel -side left -expand 1\n" - "pack $id.buttonframe.apply -side left -expand 1\n" - "pack $id.buttonframe.ok -side left -expand 1\n" - "pack $id.buttonframe.help -side left -expand 1\n" + "grid columnconfigure $id.buttonframe {0 1 2 3} -weight 1\n" + "grid config $id.buttonframe.cancel $id.buttonframe.apply $id.buttonframe.ok $id.buttonframe.help -padx 2 -sticky {snew}\n" + +// "scrollbar $id.scroll -command \"$id.frame yview\"\n" -// "grid rowconfigure $id $row -weight 0\n" - "grid config $id.buttonframe -column 0 -columnspan 9 -row $row -pady 5 -sticky {ew}\n" + "pack $id.buttonframe $id.sep2 -pady 2 -expand 0 -side bottom -fill x\n" +// "pack $id.scroll -side right -fill y\n" + "pack $id.frame -expand 1 -side top -fill both\n" // Key bindings "bind $id {<KeyPress-Escape>} \" flext_cancel $id \"\n" @@ -539,7 +538,7 @@ void flext_base::cb_GfxProperties(t_gobj *c, t_glist *) FLEXT_ASSERT(false); } - sys_vgui(const_cast<char *>(list?"%s {\n":"%s\n"),GetString(sym)); + sys_vgui(const_cast<char *>(list?"%s {":"%s "),GetString(sym)); AtomList lv; if(gattr) { // gettable attribute is present @@ -553,12 +552,12 @@ void flext_base::cb_GfxProperties(t_gobj *c, t_glist *) b += escapeit(b,sizeof(buf)+buf-b,tmp); if(i < lv.Count()-1) { *(b++) = ' '; *b = 0; } } - sys_vgui("%s\n",buf); + sys_vgui("%s",buf); } else - sys_vgui("{}\n"); + sys_vgui("{}"); - sys_vgui(const_cast<char *>(list?"} {\n":" \n")); + sys_vgui(const_cast<char *>(list?"} {":" ")); if(pattr) { // if there is initialization data take this, otherwise take the current data @@ -571,10 +570,10 @@ void flext_base::cb_GfxProperties(t_gobj *c, t_glist *) b += escapeit(b,sizeof(buf)+buf-b,tmp); if(i < lp.Count()-1) { *(b++) = ' '; *b = 0; } } - sys_vgui("%s\n",buf); + sys_vgui("%s",buf); } else - sys_vgui("{}\n"); + sys_vgui("{}"); sys_vgui(const_cast<char *>(list?"} %i %i %i \n":" %i %i %i \n"),tp,sv,pattr?(pattr->BothExist()?2:1):0); diff --git a/externals/grill/flext/source/flcontainers.h b/externals/grill/flext/source/flcontainers.h index a97df172..e1121b63 100644 --- a/externals/grill/flext/source/flcontainers.h +++ b/externals/grill/flext/source/flcontainers.h @@ -44,7 +44,7 @@ public: inline Cell *Avail() { return (Cell *)top; }
-#if defined(_MSC_VER) && (defined(_WIN32))
+#if defined(_MSC_VER) && FLEXT_CPU == FLEXT_CPU_IA32
#ifdef __SMP__
#define LOCK lock
#else
@@ -109,7 +109,7 @@ public: }
inline size_t Size() const { return ic-oc; }
-#elif defined(__GNUC__) && (defined(_X86_) || defined(__i386__))
+#elif defined(__GNUC__) && FLEXT_CPU == FLEXT_CPU_IA32
#ifndef SMPLOCK
# ifdef __SMP__
# define SMPLOCK "lock ; "
@@ -180,11 +180,11 @@ public: :"memory", "edx");
return n;
}
-#elif defined(__GNUC__) && defined(__x86_64__)
+#elif defined(__GNUC__) && FLEXT_CPU == FLEXT_CPU_X64_64
#error x86-64 architecture not supported yet
-#elif defined(__GNUC__) && defined(__POWERPC__)
+#elif defined(__GNUC__) && FLEXT_CPU == FLEXT_CPU_PPC
inline void Push(register Cell *cl)
{
register volatile long t1;
diff --git a/externals/grill/flext/source/flprefix.h b/externals/grill/flext/source/flprefix.h index ab09390e..faaa67b9 100755 --- a/externals/grill/flext/source/flprefix.h +++ b/externals/grill/flext/source/flprefix.h @@ -66,10 +66,16 @@ WARRANTIES, see the file, "license.txt," in this distribution. // --- definitions for FLEXT_CPU --------------------- #define FLEXT_CPU_UNKNOWN 0 -#define FLEXT_CPU_INTEL 1 -#define FLEXT_CPU_PPC 2 -#define FLEXT_CPU_MIPS 3 -#define FLEXT_CPU_ALPHA 4 +#define FLEXT_CPU_IA32 1 +#define FLEXT_CPU_PPC 2 +#define FLEXT_CPU_MIPS 3 +#define FLEXT_CPU_ALPHA 4 + +#define FLEXT_CPU_IA64 5 // Itanium +#define FLEXT_CPU_X86_64 6 // AMD-K8, EMT64 + +// compatibility +#define FLEXT_CPU_INTEL FLEXT_CPU_IA32 // --- definitions for FLEXT_THREADS ----------------- #define FLEXT_THR_POSIX 1 // pthreads @@ -110,8 +116,12 @@ WARRANTIES, see the file, "license.txt," in this distribution. // and Intel C++ (as guessed) #ifndef FLEXT_CPU - #if defined(_M_IX86) - #define FLEXT_CPU FLEXT_CPU_INTEL + #if defined(_M_AMD64) + #define FLEXT_CPU FLEXT_CPU_X86_64 + #elif defined(_M_IA64) + #define FLEXT_CPU FLEXT_CPU_IA64 + #elif defined(_M_IX86) + #define FLEXT_CPU FLEXT_CPU_IA32 #elif defined(_M_PPC) #define FLEXT_CPU FLEXT_CPU_PPC #elif defined(_M_MRX000) @@ -124,7 +134,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #endif #ifndef FLEXT_OS - #if defined(_WIN32) + #if defined(_WIN32) || defined(_WIN64) #define FLEXT_OS FLEXT_OS_WIN #define FLEXT_OSAPI FLEXT_OSAPI_WIN_NATIVE #else @@ -211,8 +221,10 @@ WARRANTIES, see the file, "license.txt," in this distribution. // and Intel (as suggested by Tim Blechmann) #ifndef FLEXT_CPU - #if defined(_X86_) || defined(__i386__) || defined(__i586__) || defined(__i686__) - #define FLEXT_CPU FLEXT_CPU_INTEL + #if defined(_X86_64_) // not sure about this one + #define FLEXT_CPU FLEXT_CPU_X86_64 + #elif defined(_X86_) || defined(__i386__) || defined(__i586__) || defined(__i686__) + #define FLEXT_CPU FLEXT_CPU_IA32 #elif defined(__POWERPC__) #define FLEXT_CPU FLEXT_CPU_PPC #elif defined(__MIPS__) diff --git a/externals/grill/flext/source/flsimd.cpp b/externals/grill/flext/source/flsimd.cpp index efeae6e3..1ed9480d 100755 --- a/externals/grill/flext/source/flsimd.cpp +++ b/externals/grill/flext/source/flsimd.cpp @@ -66,7 +66,7 @@ unsigned long flext::GetSIMDCapabilities() { return simdcaps; } #ifdef FLEXT_USE_SIMD -#if FLEXT_CPU == FLEXT_CPU_INTEL +#if FLEXT_CPU == FLEXT_CPU_IA32 || FLEXT_CPU == FLEXT_CPU_X84_64 #define _CPU_FEATURE_MMX 0x0001 #define _CPU_FEATURE_SSE 0x0002 @@ -294,7 +294,7 @@ static int _cpuid (_p_info *pinfo) static unsigned long setsimdcaps() { unsigned long simdflags = flext::simd_none; -#if FLEXT_CPU == FLEXT_CPU_INTEL +#if FLEXT_CPU == FLEXT_CPU_IA32 || FLEXT_CPU == FLEXT_CPU_AMD64 _p_info cpuinfo; int feature = _cpuid(&cpuinfo); if(cpuinfo.os_support&_CPU_FEATURE_MMX) simdflags += flext::simd_mmx; diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h index 123f956a..c3141a16 100644 --- a/externals/grill/flext/source/flsupport.h +++ b/externals/grill/flext/source/flsupport.h @@ -782,40 +782,12 @@ public: } *var; }; - /*! \brief This represents an entry to the list of active method threads - \internal - */ - class FLEXT_SHARE thr_entry: - public flext_root - { - public: - thr_entry(void (*m)(thr_params *),thr_params *p,thrid_t id = GetThreadId()); - - //! \brief Check if this class represents the current thread - bool Is(thrid_t id = GetThreadId()) const { return IsThread(thrid,id); } - - FLEXT_CLASSDEF(flext_base) *This() const { return th; } - thrid_t Id() const { return thrid; } - - FLEXT_CLASSDEF(flext_base) *th; - void (*meth)(thr_params *); - thr_params *params; - thrid_t thrid; - bool active,shouldexit; -#if FLEXT_THREADS == FLEXT_THR_MP - int weight; -#endif - thr_entry *nxt; - }; - protected: static thrid_t thrhelpid; static thrid_t thrmsgid; static bool StartHelper(); - static bool StopHelper(); static void ThrHelper(void *); - static void LaunchHelper(thr_entry *e); //! the system's thread id static thrid_t thrid; // the system thread @@ -1081,6 +1053,9 @@ public: */ static void Sleep(double s); + //! Sleep for a very short amount of time, just to let other threads wake up + static void MiniSleep(); + /*! \brief Class encapsulating a timer with callback functionality. This class can either be used with FLEXT_ADDTIMER or used as a base class with an overloaded virtual Work function. */ diff --git a/externals/grill/flext/source/flthr.cpp b/externals/grill/flext/source/flthr.cpp index 0750dd83..47c64354 100644 --- a/externals/grill/flext/source/flthr.cpp +++ b/externals/grill/flext/source/flthr.cpp @@ -13,10 +13,15 @@ WARRANTIES, see the file, "license.txt," in this distribution. */ #include "flext.h" -#include "flinternal.h" #ifdef FLEXT_THREADS +// maximum wait time for threads to finish (in ms) +#define MAXIMUMWAIT 100 + + +#include "flinternal.h" +#include "flcontainers.h" #include <time.h> @@ -31,7 +36,6 @@ WARRANTIES, see the file, "license.txt," in this distribution. #error WIN32 threads need Windows SDK version >= 0x500 #endif - #include <errno.h> //! Thread id of system thread @@ -40,11 +44,61 @@ flext::thrid_t flext::thrid = 0; //! Thread id of helper thread flext::thrid_t flext::thrhelpid = 0; -static flext::thr_entry *thrhead = NULL,*thrtail = NULL; -static flext::ThrMutex tlmutex; -//! Helper thread should terminate -static bool thrhelpexit = false; +//! \brief This represents an entry to the list of active method threads +class thr_entry + : public flext + , public Fifo::Cell +{ +public: + void thr_entry::Set(void (*m)(thr_params *),thr_params *p,thrid_t id = GetThreadId()) + { + th = p?p->cl:NULL; + meth = m,params = p,thrid = id; + shouldexit = false; +#if FLEXT_THREADS == FLEXT_THR_MP + weight = 100; // MP default weight +#endif + } + + //! \brief Check if this class represents the current thread + bool Is(thrid_t id = GetThreadId()) const { return IsThread(thrid,id); } + + FLEXT_CLASSDEF(flext_base) *This() const { return th; } + thrid_t Id() const { return thrid; } + + FLEXT_CLASSDEF(flext_base) *th; + void (*meth)(thr_params *); + thr_params *params; + thrid_t thrid; + bool shouldexit; +#if FLEXT_THREADS == FLEXT_THR_MP + int weight; +#endif +}; + +template<class T> +class ThrFinder: + public T +{ +public: + void Push(thr_entry *e) { T::Push(e); } + thr_entry *Pop() { return T::Pop(); } + + thr_entry *Find(flext::thrid_t id,bool pop = false) + { + TypedLifo<thr_entry> qutmp; + thr_entry *fnd; + while((fnd = Pop()) && !fnd->Is(id)) qutmp.Push(fnd); + // put back entries + for(thr_entry *ti; ti = qutmp.Pop(); ) Push(ti); + if(fnd && !pop) Push(fnd); + return fnd; + } +}; + +static ThrFinder< PooledLifo<thr_entry,1,10> > thrpending; +static ThrFinder< TypedLifo<thr_entry> > thractive,thrstopped; //! Helper thread conditional static flext::ThrCond *thrhelpcond = NULL; @@ -53,12 +107,13 @@ static flext::ThrCond *thrhelpcond = NULL; flext::thrid_t flext::GetSysThreadId() { return thrid; } -void flext::LaunchHelper(thr_entry *e) +static void LaunchHelper(thr_entry *e) { - e->thrid = GetThreadId(); + e->thrid = flext::GetThreadId(); e->meth(e->params); } + //! Start helper thread bool flext::StartHelper() { @@ -76,7 +131,6 @@ bool flext::StartHelper() pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); - thrhelpexit = false; ok = pthread_create (&thrhelpid,&attr,(void *(*)(void *))ThrHelper,NULL) == 0; #elif FLEXT_THREADS == FLEXT_THR_MP if(!MPLibraryIsLoaded()) @@ -105,17 +159,6 @@ bool flext::StartHelper() return ok; } -#if 0 -/*! \brief Stop helper thread - \note Never called! -*/ -bool flext::StopHelper() -{ - thrhelpexit = true; - if(thrhelpcond) thrhelpcond->Signal(); -} -#endif - //! Static helper thread function void flext::ThrHelper(void *) { @@ -128,8 +171,6 @@ void flext::ThrHelper(void *) pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); #endif -// post("Helper thread started"); - // set thread priority one point below normal // so thread construction won't disturb real-time audio RelPriority(-1); @@ -138,156 +179,151 @@ void flext::ThrHelper(void *) // helper loop for(;;) { -// post("Helper loop"); - thrhelpcond->Wait(); - if(thrhelpexit) break; - -// post("Helper signalled"); - tlmutex.Lock(); -// post("Helper after lock"); - - // start all inactive threads in queue - thr_entry *prv = NULL,*ti; - for(ti = thrhead; ti; prv = ti,ti = ti->nxt) { - if(!ti->active) { - bool ok; - -// post("Helper start thread"); -#if FLEXT_THREADS == FLEXT_THR_POSIX - thrid_t dummy; - ok = pthread_create (&dummy,&attr,(void *(*)(void *))LaunchHelper,ti) == 0; -#elif FLEXT_THREADS == FLEXT_THR_MP - thrid_t dummy; - ok = MPCreateTask((TaskProc)LaunchHelper,ti,0,0,0,0,0,&dummy) == noErr; -#elif FLEXT_THREADS == FLEXT_THR_WIN32 - ok = _beginthread((void (*)(void *))LaunchHelper,0,ti) >= 0; -#else -#error -#endif - if(!ok) { - error("flext - Could not launch thread!"); - - // delete from queue - if(prv) - prv->nxt = ti->nxt; - else - thrhead = ti->nxt; - if(thrtail == ti) thrtail = prv; - - ti->nxt = NULL; - delete ti; - } - else { -// post("Helper thread ok"); - - // set active flag - ti->active = true; - } - } - } - - tlmutex.Unlock(); + // start all inactive threads + thr_entry *ti; + while(ti = thrpending.Pop()) { + bool ok; + + #if FLEXT_THREADS == FLEXT_THR_POSIX + thrid_t dummy; + ok = pthread_create (&dummy,&attr,(void *(*)(void *))LaunchHelper,ti) == 0; + #elif FLEXT_THREADS == FLEXT_THR_MP + thrid_t dummy; + ok = MPCreateTask((TaskProc)LaunchHelper,ti,0,0,0,0,0,&dummy) == noErr; + #elif FLEXT_THREADS == FLEXT_THR_WIN32 + ok = _beginthread((void (*)(void *))LaunchHelper,0,ti) >= 0; + #else + #error + #endif + if(!ok) { + error("flext - Could not launch thread!"); + thrpending.Free(ti); ti = NULL; + } + else + // insert into queue of active threads + thractive.Push(ti); + } } + FLEXT_ASSERT(false); +/* + // Never reached! + delete thrhelpcond; thrhelpcond = NULL; #if FLEXT_THREADS == FLEXT_THR_POSIX pthread_attr_destroy(&attr); #endif +*/ } bool flext::LaunchThread(void (*meth)(thr_params *p),thr_params *p) { -#ifdef FLEXT_DEBUG - if(!thrhelpcond) { - ERRINTERNAL(); - return false; - } -#endif - -// post("make threads"); - - tlmutex.Lock(); + FLEXT_ASSERT(thrhelpcond); // make an entry into thread list - thr_entry *nt = new thr_entry(meth,p); - if(thrtail) thrtail->nxt = nt; - else thrhead = nt; - thrtail = nt; - - tlmutex.Unlock(); - -// post("signal helper"); - + thr_entry *e = thrpending.New(); + e->Set(meth,p); + thrpending.Push(e); // signal thread helper thrhelpcond->Signal(); return true; } +static bool waitforstopped(TypedFifo<thr_entry> &qufnd,float wait = 0) +{ + TypedLifo<thr_entry> qutmp; + + double until; + if(wait) until = flext::GetOSTime()+wait; + + for(;;) { + thr_entry *fnd = qufnd.Get(); + if(!fnd) break; // no more entries -> done! + + thr_entry *ti; + // search for entry + while((ti = thrstopped.Pop()) != NULL && ti != fnd) qutmp.Push(ti); + // put back entries + while((ti = qutmp.Pop()) != NULL) thrstopped.Push(ti); + + if(ti) { + // still in thrstopped queue + qufnd.Put(fnd); + // yield to other threads + flext::ThrYield(); + + if(wait && flext::GetOSTime() > until) + // not successful -> remaining thread are still in qufnd queue + return false; + } + } + return true; +} + bool flext::StopThread(void (*meth)(thr_params *p),thr_params *p,bool wait) { -#ifdef FLEXT_DEBUG - if(!thrhelpcond) { - ERRINTERNAL(); - return false; - } -#endif + FLEXT_ASSERT(thrhelpcond); - int found = 0; - - tlmutex.Lock(); - for(thr_entry *ti = thrhead; ti; ti = ti->nxt) - // set shouldexit if meth and params match - if(ti->meth == meth && ti->params == p) { ti->shouldexit = true; found++; } - tlmutex.Unlock(); - - if(found) { - // signal thread helper - thrhelpcond->Signal(); -#if 0 - // ###################### - // i don't think we need to wait for a single thread to stop - // ###################### - int cnt = 0; - for(int wi = 0; wi < 100; ++wi) { - // lock and count this object's threads - cnt = 0; - tlmutex.Lock(); - for(thr_entry *t = thrhead; t; t = t->nxt) - if(t->meth == meth && t->params == p) ++cnt; - tlmutex.Unlock(); - - // if no threads are remaining, we are done - if(!cnt) break; - - // Wait - Sleep(0.01f); - } + TypedLifo<thr_entry> qutmp; + thr_entry *ti; - return cnt == 0; -#endif - return true; - } - else - return false; + // first search pending queue + // -------------------------- + + { + bool found = false; + while((ti = thrpending.Pop()) != NULL) + if(ti->meth == meth && ti->params == p) { + // found -> thread hasn't started -> just delete + thrpending.Free(ti); + found = true; + } + else + qutmp.Push(ti); + + // put back into pending queue (order doesn't matter) + while((ti = qutmp.Pop()) != NULL) thrpending.Push(ti); + + if(found) return true; + } + + // now search active queue + // ----------------------- + + TypedFifo<thr_entry> qufnd; + + while((ti = thractive.Pop()) != NULL) + if(ti->meth == meth && ti->params == p) { + thrstopped.Push(ti); + thrhelpcond->Signal(); + qufnd.Put(ti); + } + else + qutmp.Push(ti); + + // put back into pending queue (order doesn't matter) + while((ti = qutmp.Pop()) != NULL) thractive.Push(ti); + + // wakeup helper thread + thrhelpcond->Signal(); + + // now wait for entries in qufnd to have vanished from thrstopped + if(wait) + return waitforstopped(qufnd); + else + return qufnd.Size() == 0; } bool flext_base::ShouldExit() const { - bool ret = true; - - tlmutex.Lock(); - for(thr_entry *ti = thrhead; ti; ti = ti->nxt) - if(ti->Is()) { ret = ti->shouldexit; break; } - tlmutex.Unlock(); - - // thread was not found -> EXIT!!! - return ret; + thr_entry *fnd = thrstopped.Find(GetThreadId()); + return fnd != NULL; } bool flext::PushThread() @@ -299,99 +335,87 @@ bool flext::PushThread() void flext::PopThread() { - tlmutex.Lock(); - -// post("Pop thread"); - - thr_entry *prv = NULL,*ti; - for(ti = thrhead; ti; prv = ti,ti = ti->nxt) - if(ti->Is()) break; + thrid_t id = GetThreadId(); + thr_entry *fnd = thrstopped.Find(id,true); + if(!fnd) fnd = thractive.Find(id,true); - if(ti) { - if(prv) - prv->nxt = ti->nxt; - else - thrhead = ti->nxt; - if(thrtail == ti) thrtail = prv; - - ti->nxt = NULL; - delete ti; - } - else { + if(fnd) + thrpending.Free(fnd); #ifdef FLEXT_DEBUG + else post("flext - INTERNAL ERROR: Thread not found!"); #endif - } - - tlmutex.Unlock(); } //! Terminate all object threads bool flext_base::StopThreads() { - thr_entry *t; + FLEXT_ASSERT(thrhelpcond); - // signal termination for all object's threads - tlmutex.Lock(); - for(t = thrhead; t; t = t->nxt) { - if(t->This() == this) t->shouldexit = true; - } - tlmutex.Unlock(); + TypedLifo<thr_entry> qutmp; + thr_entry *ti; - // TODO: maybe there should be a thread conditional for every thread so that it can be signalled efficiently + // first search pending queue + // -------------------------- - // wait for thread termination (1 second max.) - int cnt; - for(int wi = 0; wi < 100; ++wi) { - // lock and count this object's threads - tlmutex.Lock(); - for(cnt = 0,t = thrhead; t; t = t->nxt) - if(t->This() == this) ++cnt; - tlmutex.Unlock(); + bool found = false; + while((ti = thrpending.Pop()) != NULL) + if(ti->This() == this) + // found -> thread hasn't started -> just delete + thrpending.Free(ti); + else + qutmp.Push(ti); - // if no threads are remaining, we are done - if(!cnt) break; + // put back into pending queue (order doesn't matter) + while((ti = qutmp.Pop()) != NULL) thrpending.Push(ti); - // Wait - Sleep(0.01f); - } + // now search active queue + // ----------------------- + + TypedFifo<thr_entry> qufnd; + + while((ti = thractive.Pop()) != NULL) + if(ti->This() == this) { + thrstopped.Push(ti); + thrhelpcond->Signal(); + qufnd.Put(ti); + } + else + qutmp.Push(ti); - if(cnt) { + // put back into pending queue (order doesn't matter) + while((ti = qutmp.Pop()) != NULL) thractive.Push(ti); + + // wakeup helper thread + thrhelpcond->Signal(); + + // now wait for entries in qufnd to have vanished from thrstopped + if(!waitforstopped(qufnd,MAXIMUMWAIT*0.001f)) { #ifdef FLEXT_DEBUG post("flext - doing hard thread termination"); #endif - - // --- all object threads have terminated by now ------- - tlmutex.Lock(); // timeout -> hard termination - for(t = thrhead; t; ) - if(t->This() == this) { - #if FLEXT_THREADS == FLEXT_THR_POSIX - if(pthread_cancel(t->thrid)) post("%s - Thread could not be terminated!",thisName()); - #elif FLEXT_THREADS == FLEXT_THR_MP - MPTerminateTask(t->thrid,0); - // here, we should use a task queue to check whether the task has really terminated!! - #elif FLEXT_THREADS == FLEXT_THR_WIN32 - // can't use the c library function _endthread.. memory leaks will occur - HANDLE hnd = OpenThread(THREAD_ALL_ACCESS,TRUE,t->thrid); - TerminateThread(hnd,0); - #else - #error - #endif - thr_entry *tn = t->nxt; - t->nxt = NULL; delete t; - t = tn; - } - else t = t->nxt; - thrhead = NULL; - - tlmutex.Unlock(); + while((ti = qufnd.Get()) != NULL) { +#if FLEXT_THREADS == FLEXT_THR_POSIX + if(pthread_cancel(ti->thrid)) + post("%s - Thread could not be terminated!",thisName()); +#elif FLEXT_THREADS == FLEXT_THR_MP + MPTerminateTask(ti->thrid,0); + // here, we should use a task queue to check whether the task has really terminated!! +#elif FLEXT_THREADS == FLEXT_THR_WIN32 + // can't use the c library function _endthread.. memory leaks will occur + HANDLE hnd = OpenThread(THREAD_ALL_ACCESS,TRUE,ti->thrid); + TerminateThread(hnd,0); +#else +#error Not implemented +#endif + thrpending.Free(ti); + } + return false; } - -// post("All threads have terminated"); - - return true; + else + return true; } bool flext::RelPriority(int dp,thrid_t ref,thrid_t id) @@ -469,9 +493,9 @@ bool flext::RelPriority(int dp,thrid_t ref,thrid_t id) return true; #elif FLEXT_THREADS == FLEXT_THR_MP - thr_entry *t; - for(t = thrhead; t && t->Id() != id; t = t->nxt) {} - if(t) { + thr_entry *ti = thrpending.Find(id); + if(!ti) ti = thractive.Find(id); + if(ti) { // thread found in list int w = GetPriority(id); if(dp < 0) w /= 1<<(-dp); @@ -488,7 +512,7 @@ bool flext::RelPriority(int dp,thrid_t ref,thrid_t id) #endif w = 10000; } - t->weight = w; + ti->weight = w; return MPSetTaskWeight(id,w) == noErr; } else return false; @@ -524,9 +548,9 @@ int flext::GetPriority(thrid_t id) return pr; #elif FLEXT_THREADS == FLEXT_THR_MP - thr_entry *t; - for(t = thrhead; t && t->Id() != id; t = t->nxt) {} - return t?t->weight:-1; + thr_entry *ti = thrpending.Find(id); + if(!ti) ti = thractive.Find(id); + return ti?ti->weight:-1; #else #error #endif @@ -566,12 +590,9 @@ bool flext::SetPriority(int p,thrid_t id) return true; #elif FLEXT_THREADS == FLEXT_THR_MP - thr_entry *t; - for(t = thrhead; t && t->Id() != id; t = t->nxt) {} - if(t) - return MPSetTaskWeight(id,t->weight = p) == noErr; - else - return false; + thr_entry *ti = thrpending.Find(id); + if(!ti) ti = thractive.Find(id); + return ti && MPSetTaskWeight(id,ti->weight = p) == noErr; #else #error #endif @@ -585,17 +606,6 @@ void flext_base::thr_params::set_any(const t_symbol *s,int argc,const t_atom *ar void flext_base::thr_params::set_list(int argc,const t_atom *argv) { var[0]._list.args = new AtomList(argc,argv); } -flext_base::thr_entry::thr_entry(void (*m)(thr_params *),thr_params *p,thrid_t id): - th(p?p->cl:NULL),meth(m),params(p),thrid(id), - active(false),shouldexit(false), -#if FLEXT_THREADS == FLEXT_THR_MP - weight(100), // MP default weight -#endif - nxt(NULL) -{} - - - #if FLEXT_THREADS == FLEXT_THR_POSIX bool flext::ThrCond::Wait() { Lock(); diff --git a/externals/grill/flext/source/fltimer.cpp b/externals/grill/flext/source/fltimer.cpp index 294da438..c33716e5 100755 --- a/externals/grill/flext/source/fltimer.cpp +++ b/externals/grill/flext/source/fltimer.cpp @@ -109,7 +109,6 @@ void flext::Sleep(double s) #endif } - /* \param qu determines whether timed messages should be queued (low priority - only when supported by the system). */ flext::Timer::Timer(bool qu): |