aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--externals/grill/flext/buildsys/lnx/gnumake-gcc-flext.inc2
-rw-r--r--externals/grill/flext/buildsys/lnx/gnumake-icc-ext.inc2
-rw-r--r--externals/grill/flext/buildsys/lnx/gnumake-icc-flext.inc10
-rw-r--r--externals/grill/flext/buildsys/lnx/gnumake-icc.inc1
-rw-r--r--externals/grill/flext/changes.txt2
-rw-r--r--externals/grill/flext/notes.txt1
-rw-r--r--externals/grill/flext/source/flattr_ed.cpp147
-rw-r--r--externals/grill/flext/source/flcontainers.h8
-rwxr-xr-xexternals/grill/flext/source/flprefix.h30
-rwxr-xr-xexternals/grill/flext/source/flsimd.cpp4
-rw-r--r--externals/grill/flext/source/flsupport.h31
-rw-r--r--externals/grill/flext/source/flthr.cpp484
-rwxr-xr-xexternals/grill/flext/source/fltimer.cpp1
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):