From 42a820099a1c03b6f0a84e4f16cb983c69309aa5 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Sat, 12 Mar 2005 04:56:36 +0000 Subject: macros for 64-bit architectures fixes for icc@linux fixes for attribute editor (to deal with large dialogs) fix lines on box text change fix for gcc strangeness no more static assignment of symbols (problems with Metrowerks) fixed bugs in SIMD code for non-power-of-2 lengths fixed shared library versioning lock-free thread management don't depend on ldconfig begin in the system path (should be in /sbin/..) fixed flext::Timer::At method new lock-free lifo and fifo svn path=/trunk/; revision=2619 --- .../grill/flext/buildsys/lnx/gnumake-gcc-flext.inc | 2 +- .../grill/flext/buildsys/lnx/gnumake-icc-ext.inc | 2 + .../grill/flext/buildsys/lnx/gnumake-icc-flext.inc | 10 + externals/grill/flext/buildsys/lnx/gnumake-icc.inc | 1 - externals/grill/flext/changes.txt | 2 +- externals/grill/flext/notes.txt | 1 + externals/grill/flext/source/flattr_ed.cpp | 147 ++++--- externals/grill/flext/source/flcontainers.h | 8 +- externals/grill/flext/source/flprefix.h | 30 +- externals/grill/flext/source/flsimd.cpp | 4 +- externals/grill/flext/source/flsupport.h | 31 +- externals/grill/flext/source/flthr.cpp | 484 +++++++++++---------- externals/grill/flext/source/fltimer.cpp | 1 - 13 files changed, 365 insertions(+), 358 deletions(-) (limited to 'externals') 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 {} \" 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 {} \" 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 {} \" 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 {} \" 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 {} \" 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 {} \" 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 {} \" 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(list?"%s {\n":"%s\n"),GetString(sym)); + sys_vgui(const_cast(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(list?"} {\n":" \n")); + sys_vgui(const_cast(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(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 @@ -31,7 +36,6 @@ WARRANTIES, see the file, "license.txt," in this distribution. #error WIN32 threads need Windows SDK version >= 0x500 #endif - #include //! 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 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 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 > thrpending; +static ThrFinder< TypedLifo > 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 &qufnd,float wait = 0) +{ + TypedLifo 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 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 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 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 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): -- cgit v1.2.1