aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/flext
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2002-12-22 01:28:34 +0000
committerThomas Grill <xovo@users.sourceforge.net>2002-12-22 01:28:34 +0000
commit99a29c1926eee84f100ad9ea59a8c33f7878c342 (patch)
tree8b9235a630b5839350529d9e255d4f87c2389b5b /externals/grill/flext
parent927c48a90eb2a5ebf9e221041cd963c7377c8349 (diff)
"no message"
svn path=/trunk/; revision=306
Diffstat (limited to 'externals/grill/flext')
-rw-r--r--externals/grill/flext/flext.cwbin202097 -> 204177 bytes
-rw-r--r--externals/grill/flext/readme.txt19
-rw-r--r--externals/grill/flext/source/flbase.h4
-rw-r--r--externals/grill/flext/source/flclass.h99
-rw-r--r--externals/grill/flext/source/fldefs.h50
-rw-r--r--externals/grill/flext/source/fldsp.h2
-rw-r--r--externals/grill/flext/source/flext.cpp14
-rw-r--r--externals/grill/flext/source/flext.h17
-rw-r--r--externals/grill/flext/source/flout.cpp49
-rwxr-xr-xexternals/grill/flext/source/flprefix.h16
-rw-r--r--externals/grill/flext/source/flsupport.h235
-rw-r--r--externals/grill/flext/source/flthr.cpp230
-rwxr-xr-xexternals/grill/flext/tutorial/maxmsp/ex-thread1bin0 -> 1004 bytes
-rwxr-xr-xexternals/grill/flext/tutorial/maxmsp/ex-thread2bin0 -> 874 bytes
-rw-r--r--externals/grill/flext/tutorial/pd/ex-thread1.pd86
-rw-r--r--externals/grill/flext/tutorial/readme.txt2
-rw-r--r--externals/grill/flext/tutorial/thread1/main.cpp8
-rw-r--r--externals/grill/flext/tutorial/thread1/thread1.cwbin68426 -> 68426 bytes
-rw-r--r--externals/grill/flext/tutorial/thread2/main.cpp18
-rwxr-xr-xexternals/grill/flext/tutorial/thread2/thread2.cwbin68426 -> 68426 bytes
20 files changed, 534 insertions, 315 deletions
diff --git a/externals/grill/flext/flext.cw b/externals/grill/flext/flext.cw
index 120b5560..21096612 100644
--- a/externals/grill/flext/flext.cw
+++ b/externals/grill/flext/flext.cw
Binary files differ
diff --git a/externals/grill/flext/readme.txt b/externals/grill/flext/readme.txt
index 7fbcc8dc..eefd0260 100644
--- a/externals/grill/flext/readme.txt
+++ b/externals/grill/flext/readme.txt
@@ -33,7 +33,7 @@ Package files:
- flmspbuffer.h: MaxMSP's inofficial buffer.h included here for conveniance
> for PD you need the pd source code (which is most likely part of the distribution)
-> for Max/MSP you will also need the Max/MSP SDK (and for threading the GUSI library)
+> for Max/MSP you will also need the Max/MSP SDK (and for threading the Multiprocessing library)
> if you choose to compile with SndObj support you will need the respective library
> download from: http://www.may.ie/academic/music/musictec/SndObj/main.html
@@ -44,7 +44,7 @@ The package should at least compile (and is tested) with the following compilers
pd - Windows:
-------------
-For any of these compilers define "PD" and "NT".
+For any of these compilers define "FLEXT_SYS=2".
o Microsoft Visual C++ 6: edit "config-pd-msvc.txt" & run "build-pd-msvc.bat"
@@ -54,25 +54,27 @@ o Cygwin: edit "config-pd-cygwin.txt" & run "sh build-pd-cygwin.sh"
pd - linux:
-----------
-Be sure to define "PD".
+Be sure to define "FLEXT_SYS=2".
o GCC: edit "config-pd-linux.txt" & run "sh build-pd-linux.sh"
pd - MacOSX:
-----------
-Be sure to define "PD".
+Be sure to define "FLEXT_SYS=2".
o GCC: edit "config-pd-darwin.txt" & run "sh build-pd-darwin.sh"
Max/MSP - MacOS 9:
------------------
-Be sure to define "MAXMSP".
+Be sure to define "FLEXT_SYS=1" - alternatively use the prefix file "flcwmax.h"
o Metrowerks CodeWarrior V6: edit & use the "flext.cw" project file
Max/MSP - MacOSX:
------------------
-... sorry, not yet... would someone please donate me a CodeWarrior V8 ?
+Be sure to define "FLEXT_SYS=1" - alternatively use the prefix file "flcwmax-x.h" or "flcwmax-x-thr.h" for threading support.
+
+o Metrowerks CodeWarrior V6: edit & use the "flext.cw" project file
----------------------------------------------------------------------------
@@ -98,6 +100,7 @@ see flext.h, fldefs.h and flclass.h for the documented base definitions and clas
Version history:
0.4.1:
+- full port for Max@OSX
- fixed crash issue in flext_dsp when there are NO signal inlets or outlets defined
(this is possibly only a problem for the signal2 tutorial example)
- added flext::GetType(t_atom &), flext::ZeroMem
@@ -115,6 +118,10 @@ Version history:
- put more flext functions into flext static class
- replaced ChangePriority by RefPriority
- fixed setting of priorities... problems were caused by a compiler bug (MSVC 6)
+- made a portable threading interface with support for threading libraries other than pthreads (FLEXT_THREADS defined as FLEXT_THR_*)
+- implemented threading support with the MacOS MP thread library
+- stripped the ThrMutex and ThrCond classes of non-portable (and irrelevant) functionality
+- simplified "ToQueue*" and threaded "ToOut*" message queue mechanism for Max/MSP
0.4.0:
- the use of the const keyword is enforced (e.g. the preferred type for symbols is now "const t_symbol *")
diff --git a/externals/grill/flext/source/flbase.h b/externals/grill/flext/source/flbase.h
index 0c8e8e7e..79128e53 100644
--- a/externals/grill/flext/source/flbase.h
+++ b/externals/grill/flext/source/flbase.h
@@ -20,7 +20,7 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#include "flstdc.h"
#include "flsupport.h"
-class flext_obj;
+class FLEXT_EXT flext_obj;
// ----------------------------------------------------------------------------
/*! \brief The obligatory PD or Max/MSP object header
@@ -85,7 +85,7 @@ struct FLEXT_EXT flext_hdr
*/
// ----------------------------------------------------------------------------
-class flext_obj:
+class FLEXT_EXT flext_obj:
public flext
{
public:
diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h
index dd51d85a..ab90667a 100644
--- a/externals/grill/flext/source/flclass.h
+++ b/externals/grill/flext/source/flclass.h
@@ -40,7 +40,7 @@ WARRANTIES, see the file, "license.txt," in this distribution.
*/
-class flext_base:
+class FLEXT_EXT flext_base:
public flext_obj
{
FLEXT_HEADER_S(flext_base,flext_obj,Setup)
@@ -392,6 +392,12 @@ public:
@{
*/
+ //! Start a thread for this object
+ bool StartThread(void (*meth)(thr_params *p),thr_params *p,const char *) { p->cl = this; return flext::LaunchThread(meth,p); }
+
+ //! Terminate all threads of this object
+ bool StopThreads();
+
//! Check if current thread should terminate
bool ShouldExit() const;
@@ -403,75 +409,6 @@ public:
protected:
-// --- thread stuff -----------------------------------------------
-
-#ifdef FLEXT_THREADS
-
- /*! \brief Thread parameters
- \internal
- */
- class thr_params:
- public flext
- {
- public:
- thr_params(flext_base *c,int n = 1);
- ~thr_params();
-
- void set_any(const t_symbol *s,int argc,const t_atom *argv);
- void set_list(int argc,const t_atom *argv);
-
- flext_base *cl;
- union _data {
- bool _bool;
- float _float;
- int _int;
- t_symptr _t_symptr;
- struct { AtomAnything *args; } _any;
- struct { AtomList *args; } _list;
- struct { void *data; } _ext;
- } *var;
- };
-
- /*! \brief This represents an entry to the list of active method threads
- \internal
- */
- class thr_entry
- {
- public:
- thr_entry(flext_base *t,void *(*m)(thr_params *),thr_params *p,pthread_t id = pthread_self());
-
- //! \brief Check if this class represents the current thread
- bool Is(pthread_t id = pthread_self()) const { return pthread_equal(thrid,id) != 0; }
-
- flext_base *th;
- void *(*meth)(thr_params *);
- thr_params *params;
- pthread_t thrid;
- bool active,shouldexit;
- thr_entry *nxt;
- };
-
- /*! \brief Add current thread to list of active threads
- \return true on success
- \internal
- */
- bool PushThread();
-
- /*! \brief Remove current thread from list of active threads
- \internal
- */
- void PopThread();
-
-public:
- /*! \brief Start a method thread
- \internal
- */
- bool StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname);
-
-#endif
-
-protected:
-
flext_base();
virtual ~flext_base();
@@ -630,30 +567,18 @@ private:
static bool cb_GetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->GetAttrib(s,argc,argv); }
static bool cb_SetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->SetAttrib(s,argc,argv); }
-#ifdef FLEXT_THREADS
- ThrMutex qmutex;
-
- static thr_entry *thrhead,*thrtail;
- static ThrMutex tlmutex;
-
- static pthread_t thrhelpid;
- static bool StartHelper();
- static bool StopHelper();
- static void ThrHelper(void *);
- void TermThreads();
-#endif
+ // queue stuff
class qmsg;
qmsg *qhead,*qtail;
t_qelem *qclk;
-#if FLEXT_SYS == FLEXT_SYS_MAX
- t_clock *yclk;
- static void YTick(flext_base *th);
-#endif
-
static void QTick(flext_base *th);
void Queue(qmsg *m);
+#ifdef FLEXT_THREADS
+ ThrMutex qmutex;
+#endif
+
#if FLEXT_SYS == FLEXT_SYS_PD
// proxy object (for additional inlets) stuff
diff --git a/externals/grill/flext/source/fldefs.h b/externals/grill/flext/source/fldefs.h
index f7488fe0..353752f7 100644
--- a/externals/grill/flext/source/fldefs.h
+++ b/externals/grill/flext/source/fldefs.h
@@ -412,10 +412,10 @@ FLEXT_CALLBACK_1(M_FUN,t_symptr)
//! Set up a threaded method callback with no arguments
#define FLEXT_THREAD(M_FUN) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c) { \
- thr_params *p = new thr_params(c); \
+ thr_params *p = new thr_params; \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
delete p; \
@@ -423,16 +423,15 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->M_FUN(); \
th->PopThread(); \
} \
- return NULL; \
}
//! Set up a threaded method callback for an anything argument
#define FLEXT_THREAD_A(M_FUN) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,t_symbol *s,int argc,t_atom *argv) { \
- thr_params *p = new thr_params(c); p->set_any(s,argc,argv); \
+ thr_params *p = new thr_params; p->set_any(s,argc,argv); \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
AtomAnything *args = p->var[0]._any.args; \
@@ -442,16 +441,15 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->PopThread(); \
} \
delete args; \
- return NULL; \
}
//! Set up a threaded method callback for a variable argument list
#define FLEXT_THREAD_V(M_FUN) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int argc,t_atom *argv) { \
- thr_params *p = new thr_params(c); p->set_list(argc,argv); \
+ thr_params *p = new thr_params; p->set_list(argc,argv); \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
AtomList *args = p->var[0]._list.args; \
@@ -461,7 +459,6 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->PopThread(); \
} \
delete args; \
- return NULL; \
}
/*! \brief Set up a threaded method callback for an arbitrary data struct
@@ -469,10 +466,10 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
*/
#define FLEXT_THREAD_X(M_FUN) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,void *data) { \
- thr_params *p = new thr_params(c); p->var[0]._ext.data = data; \
+ thr_params *p = new thr_params; p->var[0]._ext.data = data; \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
void *data = p->var[0]._ext.data; \
@@ -482,16 +479,15 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->PopThread(); \
} \
delete data; \
- return NULL; \
}
//! Set up a threaded method callback for a boolean argument
#define FLEXT_THREAD_B(M_FUN) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int &arg1) { \
- thr_params *p = new thr_params(c); p->var[0]._bool = arg1 != 0; \
+ thr_params *p = new thr_params; p->var[0]._bool = arg1 != 0; \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
bool b = p->var[0]._bool; \
@@ -500,17 +496,16 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->M_FUN(b); \
th->PopThread(); \
} \
- return NULL; \
}
//! Set up a threaded method callback for 1 argument
#define FLEXT_THREAD_1(M_FUN,TP1) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1) { \
- thr_params *p = new thr_params(c,1); \
+ thr_params *p = new thr_params(1); \
p->var[0]._ ## TP1 = arg1; \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
const TP1 v1 = p->var[0]._ ## TP1; \
@@ -519,18 +514,17 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->M_FUN(v1); \
th->PopThread(); \
} \
- return NULL; \
}
//! Set up a threaded method callback for 2 arguments
#define FLEXT_THREAD_2(M_FUN,TP1,TP2) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2) { \
- thr_params *p = new thr_params(c,2); \
+ thr_params *p = new thr_params(2); \
p->var[0]._ ## TP1 = arg1; \
p->var[1]._ ## TP2 = arg2; \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
const TP1 v1 = p->var[0]._ ## TP1; \
@@ -540,19 +534,18 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->M_FUN(v1,v2); \
th->PopThread(); \
} \
- return NULL; \
}
//! Set up a threaded method callback for 3 arguments
#define FLEXT_THREAD_3(M_FUN,TP1,TP2,TP3) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3) { \
- thr_params *p = new thr_params(c,3); \
+ thr_params *p = new thr_params(3); \
p->var[0]._ ## TP1 = arg1; \
p->var[1]._ ## TP2 = arg2; \
p->var[2]._ ## TP3 = arg3; \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
const TP1 v1 = p->var[0]._ ## TP1; \
@@ -563,20 +556,19 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->M_FUN(v1,v2,v3); \
th->PopThread(); \
} \
- return NULL; \
}
//! Set up a threaded method callback for 4 arguments
#define FLEXT_THREAD_4(M_FUN,TP1,TP2,TP3,TP4) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4) { \
- thr_params *p = new thr_params(c,4); \
+ thr_params *p = new thr_params(4); \
p->var[0]._ ## TP1 = arg1; \
p->var[1]._ ## TP2 = arg2; \
p->var[2]._ ## TP3 = arg3; \
p->var[3]._ ## TP4 = arg4; \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
const TP1 v1 = p->var[0]._ ## TP1; \
@@ -588,13 +580,12 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->M_FUN(v1,v2,v3,v4); \
th->PopThread(); \
} \
- return NULL; \
}
//! Set up a threaded method callback for 5 arguments
#define FLEXT_THREAD_5(M_FUN,TP1,TP2,TP3,TP4,TP5) \
static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4,TP5 &arg5) { \
- thr_params *p = new thr_params(c,5); \
+ thr_params *p = new thr_params(5); \
p->var[0]._ ## TP1 = arg1; \
p->var[1]._ ## TP2 = arg2; \
p->var[2]._ ## TP3 = arg3; \
@@ -602,7 +593,7 @@ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP
p->var[4]._ ## TP5 = arg5; \
return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
} \
-static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+static void FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
thisType *th = FLEXT_CAST<thisType *>(p->cl); \
bool ok = th->PushThread(); \
const TP1 v1 = p->var[0]._ ## TP1; \
@@ -615,7 +606,6 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
th->M_FUN(v1,v2,v3,v4,v5); \
th->PopThread(); \
} \
- return NULL; \
}
diff --git a/externals/grill/flext/source/fldsp.h b/externals/grill/flext/source/fldsp.h
index b1fbe23d..4926d873 100644
--- a/externals/grill/flext/source/fldsp.h
+++ b/externals/grill/flext/source/fldsp.h
@@ -24,7 +24,7 @@ WARRANTIES, see the file, "license.txt," in this distribution.
/*! \brief Flext dsp enabled base object
*/
-class flext_dsp:
+class FLEXT_EXT flext_dsp:
public flext_base
{
FLEXT_HEADER_S(flext_dsp,flext_base,Setup)
diff --git a/externals/grill/flext/source/flext.cpp b/externals/grill/flext/source/flext.cpp
index e052e56a..f74d11c6 100644
--- a/externals/grill/flext/source/flext.cpp
+++ b/externals/grill/flext/source/flext.cpp
@@ -130,15 +130,8 @@ flext_base::flext_base():
{
LOG1("%s - flext logging is on",thisName());
-#ifdef FLEXT_THREADS
-// shouldexit = false;
-// thrhead = thrtail = NULL;
-#endif
qhead = qtail = NULL;
qclk = (t_qelem *)(qelem_new(this,(t_method)QTick));
-#if FLEXT_SYS == FLEXT_SYS_MAX
- yclk = (t_clock *)(clock_new(this,(t_method)YTick));
-#endif
AddMethod(0,"getattributes",(methfun)cb_ListAttrib);
}
@@ -146,15 +139,12 @@ flext_base::flext_base():
flext_base::~flext_base()
{
#ifdef FLEXT_THREADS
- TermThreads();
+ StopThreads();
#endif
// send remaining pending messages
while(qhead) QTick(this);
qelem_free((t_qelem *)qclk);
-#if FLEXT_SYS == FLEXT_SYS_MAX
- clock_free((object *)yclk);
-#endif
if(inlist) delete inlist;
if(outlist) delete outlist;
@@ -464,7 +454,7 @@ void flext_base::Setup(t_class *c)
ADD_IN_FT(9);
#ifdef FLEXT_THREADS
- thrid = pthread_self();
+ thrid = GetThreadId();
StartHelper();
#endif
diff --git a/externals/grill/flext/source/flext.h b/externals/grill/flext/source/flext.h
index 1e72daa5..9b5da4e6 100644
--- a/externals/grill/flext/source/flext.h
+++ b/externals/grill/flext/source/flext.h
@@ -34,11 +34,20 @@ WARRANTIES, see the file, "license.txt," in this distribution.
// determine System/OS/CPU
#include "flprefix.h"
+// include headers necessary for multi-threading
#ifdef FLEXT_THREADS
-extern "C" {
- #include <pthread.h>
- #include <sched.h>
-}
+ #if FLEXT_THREADS == FLEXT_THR_POSIX
+ extern "C" {
+ #include <pthread.h>
+ #include <sched.h>
+ }
+ #elif FLEXT_THREADS == FLEXT_THR_MP
+ #include <multiprocessing.h>
+ #elif FLEXT_THREADS == FLEXT_THR_WIN32
+ #include <windows.h>
+ #else
+ #error "Thread model not supported"
+ #endif
#endif
// include all the flext interface definitions
diff --git a/externals/grill/flext/source/flout.cpp b/externals/grill/flext/source/flout.cpp
index 16a6ea29..9dbda7f1 100644
--- a/externals/grill/flext/source/flout.cpp
+++ b/externals/grill/flext/source/flout.cpp
@@ -67,8 +67,6 @@ public:
struct { int argc; t_atom *argv; } _list;
struct { const t_symbol *s; int argc; t_atom *argv; } _any;
};
-
-// void Add(qmsg *o);
};
flext_base::qmsg::~qmsg()
@@ -84,44 +82,24 @@ void flext_base::qmsg::Clear()
tp = tp_none;
}
-/*
-void flext_base::qmsg::Add(qmsg *o)
-{
- if(nxt) nxt->Add(o);
- else nxt = o;
-}
-*/
-
-#if FLEXT_SYS == FLEXT_SYS_MAX
-void flext_base::YTick(flext_base *th)
-{
- clock_delay(th->yclk,0);
- qelem_set(th->qclk);
-#ifdef FLEXT_THREADS
- sched_yield();
-#endif
-}
-#endif
-
void flext_base::QTick(flext_base *th)
{
-#ifdef FLEXT_THREADS
-
-#ifdef FLEXT_DEBUG
+// post("qtick");
+#if defined(FLEXT_THREADS) && defined(FLEXT_DEBUG)
if(!th->IsSystemThread()) {
error("flext - Queue tick called by wrong thread!");
return;
}
#endif
+#ifdef FLEXT_THREADS
th->qmutex.Lock();
#endif
- while(th->qhead) {
+ for(;;) {
qmsg *m = th->qhead;
+ if(!m) break;
-#if FLEXT_SYS == FLEXT_SYS_MAX
- short state = lockout_set(1);
-#endif
+ CRITON();
switch(m->tp) {
case qmsg::tp_bang: th->ToOutBang(m->out); break;
@@ -135,9 +113,7 @@ void flext_base::QTick(flext_base *th)
#endif
}
-#if FLEXT_SYS == FLEXT_SYS_MAX
- lockout_set(state);
-#endif
+ CRITOFF();
th->qhead = m->nxt;
if(!th->qhead) th->qtail = NULL;
@@ -151,23 +127,26 @@ void flext_base::QTick(flext_base *th)
void flext_base::Queue(qmsg *m)
{
+// post("Queue");
+
#ifdef FLEXT_THREADS
qmutex.Lock();
#endif
if(qtail) qtail->nxt = m;
else qhead = m;
qtail = m;
+#ifdef FLEXT_THREADS
+ qmutex.Unlock();
+#endif
+
#if FLEXT_SYS == FLEXT_SYS_PD
clock_delay(qclk,0);
#elif FLEXT_SYS == FLEXT_SYS_MAX
- clock_delay(yclk,0);
+ qelem_set(qclk);
#else
#error
#endif
-#ifdef FLEXT_THREADS
- qmutex.Unlock();
-#endif
}
void flext_base::ToQueueBang(outlet *o) const
diff --git a/externals/grill/flext/source/flprefix.h b/externals/grill/flext/source/flprefix.h
index d2c7f173..6aa1e0ac 100755
--- a/externals/grill/flext/source/flprefix.h
+++ b/externals/grill/flext/source/flprefix.h
@@ -50,6 +50,11 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#define FLEXT_CPU_MIPS 3
#define FLEXT_CPU_ALPHA 4
+// --- definitions for FLEXT_THREADS -----------------
+#define FLEXT_THR_POSIX 1 // pthreads
+#define FLEXT_THR_WIN32 2 // Win32 native
+#define FLEXT_THR_MP 3 // MacOS MPThreads
+
// ---------------------------------------------------
// support old definitions
@@ -233,4 +238,15 @@ WARRANTIES, see the file, "license.txt," in this distribution.
// #pragma message("Compiling for PD")
#endif
+// set threading model
+#ifdef FLEXT_THREADS
+ #undef FLEXT_THREADS
+ #if FLEXT_OS == FLEXT_OS_MACOS && FLEXT_SYS == FLEXT_SYS_MAX
+ // Max crashes with posix threads (but don't know why...)
+ #define FLEXT_THREADS FLEXT_THR_MP
+ #else
+ #define FLEXT_THREADS FLEXT_THR_POSIX
+ #endif
+#endif
+
#endif
diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h
index 9429599d..ad7158f9 100644
--- a/externals/grill/flext/source/flsupport.h
+++ b/externals/grill/flext/source/flsupport.h
@@ -17,6 +17,8 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#include "flstdc.h"
+class FLEXT_EXT flext_base;
+
class FLEXT_EXT flext {
/*! \defgroup FLEXT_SUPPORT Flext support class
@@ -392,29 +394,129 @@ public:
*/
//! thread type
+#if FLEXT_THREADS == FLEXT_THR_MP
+ typedef MPTaskID thrid_t;
+#elif FLEXT_THREADS == FLEXT_THR_POSIX
typedef pthread_t thrid_t;
+#else
+#error
+#endif
+
+ /*! \brief Get current thread id
+ */
+ static thrid_t GetThreadId() {
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ return pthread_self();
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ return MPCurrentTaskID();
+#else
+#error
+#endif
+ }
+
+ /*! \brief Get system thread id
+ */
+ static thrid_t GetSysThreadId() { return thrid; }
+
+ //! Check if current thread is the realtime system's thread
+ static bool IsThread(thrid_t t,thrid_t ref = GetThreadId()) {
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ return pthread_equal(ref,t) != 0;
+#else
+ return ref == t;
+#endif
+ }
+
+ //! Check if current thread is the realtime system's thread
+ static bool IsSystemThread() { return IsThread(GetSysThreadId()); }
+
+
+ /*! \brief Thread parameters
+ \internal
+ */
+ class thr_params
+ {
+ public:
+ thr_params(int n = 1);
+ ~thr_params();
+
+ void set_any(const t_symbol *s,int argc,const t_atom *argv);
+ void set_list(int argc,const t_atom *argv);
+
+ flext_base *cl;
+ union _data {
+ bool _bool;
+ float _float;
+ int _int;
+ t_symptr _t_symptr;
+ struct { AtomAnything *args; } _any;
+ struct { AtomList *args; } _list;
+ struct { void *data; } _ext;
+ } *var;
+ };
+
+ /*! \brief This represents an entry to the list of active method threads
+ \internal
+ */
+ class thr_entry
+ {
+ 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_base *This() const { return th; }
+ thrid_t Id() const { return thrid; }
+
+ 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 bool StartHelper();
+ static bool StopHelper();
+ static void ThrHelper(void *);
+
//! system's thread id
static thrid_t thrid; // the system thread
public:
- //! Check if current thread is the realtime system's thread
- static bool IsSystemThread() { pthread_t cur = pthread_self(); return pthread_equal(cur,thrid) != 0; }
-
/*! \brief Yield to other threads
\remark A call to this is only needed for systems with cooperative multitasking like MacOS<=9
*/
- static void ThrYield() { sched_yield(); }
-
- /*! \brief Get current thread id
- */
- static thrid_t GetThreadId() { return pthread_self(); }
+ static void ThrYield() {
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ sched_yield();
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ MPYield();
+#else
+#error
+#endif
+ }
- /*! \brief Get current thread id
+ /*! \brief Query whether task is preemptive
*/
- static thrid_t GetSysThreadId() { return thrid; }
+ static bool IsThreadPreemptive(thrid_t t = GetThreadId()) {
+#if FLEXT_THREADS == FLEXT_THR_POSIX || FLEXT_THREADS == FLEXT_THR_WIN32
+ return true;
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ return MPTaskIsPreemptive(t);
+#else
+#error
+#endif
+ }
+
/*! \brief Increase/Decrease priority of a thread
*/
@@ -431,35 +533,63 @@ public:
/*! \brief Thread mutex
\sa pthreads documentation
*/
- class ThrMutex
+ class FLEXT_EXT ThrMutex
+#if FLEXT_THREADS == FLEXT_THR_POSIX
{
public:
//! Construct thread mutex
- ThrMutex(): cnt(0) { pthread_mutex_init(&mutex,NULL); }
+ ThrMutex() /*: cnt(0)*/ { pthread_mutex_init(&mutex,NULL); }
//! Destroy thread mutex
~ThrMutex() { pthread_mutex_destroy(&mutex); }
//! Lock thread mutex
- int Lock() { cnt = 1; return pthread_mutex_lock(&mutex); }
+ bool Lock() { /*cnt = 1;*/ return pthread_mutex_lock(&mutex) == 0; }
+ //! Lock thread mutex
+ bool WaitForLock(float tm) { /*cnt = 1;*/ return pthread_mutex_lock(&mutex) == 0; }
//! Try to lock, but don't wait
- int TryLock() { return pthread_mutex_trylock(&mutex); }
+ bool TryLock() { return pthread_mutex_trylock(&mutex) == 0; }
//! Unlock thread mutex
- int Unlock() { cnt = 0; return pthread_mutex_unlock(&mutex); }
-
+ bool Unlock() { /*cnt = 0;*/ return pthread_mutex_unlock(&mutex) == 0; }
+/*
//! Lock thread mutex (increase lock count by one)
void Push() { if(!cnt++) Lock(); }
//! Unlock thread mutex if lock count reaches zero
void Pop() { if(!--cnt) Unlock(); }
+*/
protected:
pthread_mutex_t mutex;
- int cnt;
+// int cnt;
};
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ {
+ public:
+ //! Construct thread mutex
+ ThrMutex() /*: cnt(0)*/ { MPCreateCriticalRegion(&crit); }
+ //! Destroy thread mutex
+ ~ThrMutex() { MPDeleteCriticalRegion(crit); }
+
+ //! Lock thread mutex
+ bool Lock() { /*cnt = 1;*/ return MPEnterCriticalRegion(crit,kDurationForever) == noErr; }
+ //! Wait to lock thread mutex
+ bool WaitForLock(float tm) { /*cnt = 1;*/ return MPEnterCriticalRegion(crit,tm*kDurationMicrosecond*1.e6) == noErr; }
+ //! Try to lock, but don't wait
+ bool TryLock() { return MPEnterCriticalRegion(crit,kDurationImmediate) == noErr; }
+ //! Unlock thread mutex
+ bool Unlock() { /*cnt = 0;*/ return MPExitCriticalRegion(crit) == noErr; }
+
+ protected:
+ MPCriticalRegionID crit;
+ };
+#else
+#error "Not implemented"
+#endif
/*! \brief Thread conditional
\sa pthreads documentation
*/
- class ThrCond:
- public ThrMutex
+ class FLEXT_EXT ThrCond
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ :public ThrMutex
{
public:
//! Construct thread conditional
@@ -468,24 +598,81 @@ public:
~ThrCond() { pthread_cond_destroy(&cond); }
//! Wait for condition
- int Wait() { return pthread_cond_wait(&cond,&mutex); }
+ bool Wait() {
+ Lock();
+ bool ret = pthread_cond_wait(&cond,&mutex) == 0;
+ Unlock();
+ return ret;
+ }
/*! \brief Wait for condition (for a certain time)
\param time Wait time in seconds
*/
- int TimedWait(float time)
+ bool TimedWait(float time)
{
timespec tm; tm.tv_sec = (long)time; tm.tv_nsec = (long)((time-(long)time)*1.e9);
- return pthread_cond_timedwait(&cond,&mutex,&tm);
+ Lock();
+ bool ret = pthread_cond_timedwait(&cond,&mutex,&tm) == 0;
+ Unlock();
+ return ret;
}
//! Signal condition
- int Signal() { return pthread_cond_signal(&cond); }
+ bool Signal()
+ {
+ Lock();
+ bool ret = pthread_cond_signal(&cond) == 0;
+ Unlock();
+ return ret;
+ }
//! Broadcast condition
- int Broadcast() { return pthread_cond_broadcast(&cond); }
+// int Broadcast() { return pthread_cond_broadcast(&cond); }
protected:
pthread_cond_t cond;
};
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ {
+ public:
+ //! Construct thread conditional
+ ThrCond() { MPCreateEvent(&ev); }
+ //! Destroy thread conditional
+ ~ThrCond() { MPDeleteEvent(ev); }
+
+ //! Wait for condition
+ bool Wait() { return MPWaitForEvent(ev,NULL,kDurationForever) == noErr; }
+
+ /*! \brief Wait for condition (for a certain time)
+ \param time Wait time in seconds
+ */
+ bool TimedWait(float tm) { return MPWaitForEvent(ev,NULL,tm*kDurationMicrosecond*1.e6) == noErr; }
+
+ //! Signal condition
+ bool Signal() { return MPSetEvent(ev,1) == noErr; } // one bit needs to be set at least
+ //! Broadcast condition
+// int Broadcast() { return pthread_cond_broadcast(&cond); }
+ protected:
+ MPEventID ev;
+ };
+#else
+#error "Not implemented"
+#endif
+
+ /*! \brief Add current thread to list of active threads
+ \return true on success
+ \internal
+ */
+ static bool PushThread();
+
+ /*! \brief Remove current thread from list of active threads
+ \internal
+ */
+ static void PopThread();
+
+ /*! \brief Launch a thread
+ \remark thr_params *p may be NULL if not needed
+ */
+ static bool LaunchThread(void (*meth)(thr_params *p),thr_params *p);
+
//! @} FLEXT_S_THREAD
#endif // FLEXT_THREADS
diff --git a/externals/grill/flext/source/flthr.cpp b/externals/grill/flext/source/flthr.cpp
index 96e52b0d..e8834b76 100644
--- a/externals/grill/flext/source/flthr.cpp
+++ b/externals/grill/flext/source/flthr.cpp
@@ -17,57 +17,60 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#ifdef FLEXT_THREADS
-#if FLEXT_OS == FLEXT_OS_WIN
-#include <windows.h>
-#endif
-
#include <errno.h>
//! Thread id of system thread
flext::thrid_t flext::thrid;
//! Thread id of helper thread
-flext::thrid_t flext_base::thrhelpid;
+flext::thrid_t flext::thrhelpid;
-flext_base::thr_entry *flext_base::thrhead = NULL,*flext_base::thrtail = NULL;
-flext::ThrMutex flext_base::tlmutex;
+/*
+flext::thr_entry *flext::thrhead = NULL,*flext::thrtail = NULL;
+flext::ThrMutex flext::tlmutex;
+*/
+static flext::thr_entry *thrhead = NULL,*thrtail = NULL;
+static flext::ThrMutex tlmutex;
//! Helper thread should terminate
-bool thrhelpexit = false;
+static bool thrhelpexit = false;
//! Helper thread conditional
-flext::ThrCond *thrhelpcond = NULL;
-
-
-flext_base::thr_entry::thr_entry(flext_base *t,void *(*m)(thr_params *),thr_params *p,pthread_t id):
- th(t),meth(m),params(p),thrid(id),
- active(false),shouldexit(false),
- nxt(NULL)
-{}
+static flext::ThrCond *thrhelpcond = NULL;
//! Start helper thread
-bool flext_base::StartHelper()
+bool flext::StartHelper()
{
+ bool ok = false;
+#if FLEXT_THREADS == FLEXT_THR_POSIX
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
thrhelpexit = false;
int ret = pthread_create (&thrhelpid,&attr,(void *(*)(void *))ThrHelper,NULL);
- if(ret) {
- error((char *)("flext - Could not launch helper thread!"));
- return false;
+ ok = !ret;
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ if(!MPLibraryIsLoaded())
+ error("Thread library is not loaded");
+ else {
+ OSStatus ret = MPCreateTask((TaskProc)ThrHelper,NULL,0,0,0,0,0,&thrhelpid);
+ ok = ret == noErr;
}
- else
- return true;
+#else
+#error
+#endif
+ if(!ok)
+ error("flext - Could not launch helper thread!");
+ return ok;
}
#if 0
/*! \brief Stop helper thread
\note not called!
*/
-bool flext_base::StopHelper()
+bool flext::StopHelper()
{
thrhelpexit = true;
if(thrhelpcond) thrhelpcond->Signal();
@@ -75,12 +78,16 @@ bool flext_base::StopHelper()
#endif
//! Static helper thread function
-void flext_base::ThrHelper(void *)
+void flext::ThrHelper(void *)
{
+#if FLEXT_THREADS == FLEXT_THR_POSIX
// set prototype thread attributes
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
+#endif
+
+// post("Helper");
// set thread priority one point below normal
// so thread construction won't disturb real-time audio
@@ -90,18 +97,32 @@ void flext_base::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) {
- int ret = pthread_create (&ti->thrid,&attr,(void *(*)(void *))ti->meth,ti->params);
- if(ret) {
- error((char *)("flext - Could not launch thread!"));
+ bool ok;
+
+// post("Helper start thread");
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ ok = pthread_create (&ti->thrid,&attr,(void *(*)(void *))ti->meth,ti->params) == 0;
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ ok = MPCreateTask((TaskProc)ti->meth,ti->params,0,0,0,0,0,&ti->thrid) == noErr;
+#else
+#error
+#endif
+ if(!ok) {
+ error("flext - Could not launch thread!");
// delete from queue
if(prv)
@@ -114,6 +135,8 @@ void flext_base::ThrHelper(void *)
delete ti;
}
else {
+// post("Helper thread ok");
+
// set active flag
ti->active = true;
}
@@ -128,47 +151,56 @@ void flext_base::ThrHelper(void *)
}
-bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname)
+bool flext::LaunchThread(void (*meth)(thr_params *p),thr_params *p)
{
#ifdef FLEXT_DEBUG
- if(!p || !thrhelpcond) {
+ if(!thrhelpcond) {
ERRINTERNAL();
return false;
}
#endif
+// post("make threads");
+
tlmutex.Lock();
// make an entry into thread list
- thr_entry *nt = new thr_entry(this,meth,p);
+ thr_entry *nt = new thr_entry(meth,p);
if(thrtail) thrtail->nxt = nt;
else thrhead = nt;
thrtail = nt;
+ tlmutex.Unlock();
+
+// post("signal helper");
+
// signal thread helper
thrhelpcond->Signal();
- tlmutex.Unlock();
return true;
}
bool flext_base::ShouldExit() const
{
+ bool ret = true;
+
+ tlmutex.Lock();
for(thr_entry *ti = thrhead; ti; ti = ti->nxt)
- if(ti->Is()) return ti->shouldexit;
+ if(ti->Is()) { ret = ti->shouldexit; break; }
+ tlmutex.Unlock();
// thread was not found -> EXIT!!!
- return true;
+ return ret;
}
-bool flext_base::PushThread()
+bool flext::PushThread()
{
// set priority of newly created thread one point below the system thread's
RelPriority(-1);
return true;
}
-void flext_base::PopThread()
+void flext::PopThread()
{
tlmutex.Lock();
@@ -190,7 +222,7 @@ void flext_base::PopThread()
}
else {
#ifdef FLEXT_DEBUG
- post("%s - INTERNAL ERROR: Thread not found!",thisName());
+ post("flext - INTERNAL ERROR: Thread not found!");
#endif
}
@@ -198,46 +230,70 @@ void flext_base::PopThread()
}
//! Terminate all object threads
-void flext_base::TermThreads()
+bool flext_base::StopThreads()
{
thr_entry *t;
// signal termination
- for(t = thrhead; t; t = t->nxt)
- if(t->th == this) t->shouldexit = true;
+ tlmutex.Lock();
+ for(t = thrhead; t; t = t->nxt) {
+ if(t->This() == this) t->shouldexit = true;
+ }
+ tlmutex.Unlock();
- // TODO: maybe there should be a thread conditional for every thread so that it can be signaled
+ // TODO: maybe there should be a thread conditional for every thread so that it can be signalled efficiently
- // wait for thread termination
+ // wait for thread termination (1 second max.)
+ int cnt;
for(int wi = 0; wi < 100; ++wi) {
- int cnt = 0;
+ cnt = 0;
+ tlmutex.Lock();
for(t = thrhead; t; t = t->nxt)
- if(t->th == this) ++cnt;
+ if(t->This() == this) ++cnt;
+ tlmutex.Unlock();
if(!cnt) break;
Sleep(0.01f);
}
- // --- all object threads have terminated by now -------
+ if(cnt) {
+#ifdef FLEXT_DEBUG
+ post("flext - doing hard thread termination");
+#endif
+
+ // --- all object threads have terminated by now -------
- qmutex.Lock(); // Lock message queue
- tlmutex.Lock();
+ qmutex.Lock(); // Lock message queue
+ tlmutex.Lock();
- // timeout -> hard termination
- for(t = thrhead; t; )
- if(t->th == this) {
- if(pthread_cancel(t->thrid)) post("%s - Thread could not be terminated!",thisName());
- thr_entry *tn = t->nxt;
- t->nxt = NULL; delete t;
- t = tn;
- }
- else t = t->nxt;
+ // 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!!
+ #else
+ #error
+ #endif
+ thr_entry *tn = t->nxt;
+ t->nxt = NULL; delete t;
+ t = tn;
+ }
+ else t = t->nxt;
- tlmutex.Unlock();
- qmutex.Unlock();
+ tlmutex.Unlock();
+ qmutex.Unlock();
+ }
+
+// post("All threads have terminated");
+
+ return true;
}
bool flext::RelPriority(int dp,thrid_t ref,thrid_t id)
{
+#if FLEXT_THREADS == FLEXT_THR_POSIX
sched_param parm;
int policy;
if(pthread_getschedparam(ref,&policy,&parm) < 0) {
@@ -274,11 +330,39 @@ 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) {
+ // thread found in list
+ int w = GetPriority(id);
+ if(dp < 0) w /= 1<<(-dp);
+ else w *= 1<<dp;
+ if(w < 1) {
+ #ifdef FLEXT_DEBUG
+ post("flext - minimum thread priority reached");
+ #endif
+ w = 1;
+ }
+ else if(w > 10000) {
+ #ifdef FLEXT_DEBUG
+ post("flext - maximum thread priority reached");
+ #endif
+ w = 10000;
+ }
+ t->weight = w;
+ return MPSetTaskWeight(id,w) == noErr;
+ }
+ else return false;
+#else
+#error
+#endif
}
int flext::GetPriority(thrid_t id)
{
+#if FLEXT_THREADS == FLEXT_THR_POSIX
sched_param parm;
int policy;
if(pthread_getschedparam(id,&policy,&parm) < 0) {
@@ -288,11 +372,19 @@ int flext::GetPriority(thrid_t id)
return -1;
}
return parm.sched_priority;
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ thr_entry *t;
+ for(t = thrhead; t && t->Id() != id; t = t->nxt) {}
+ return t?t->weight:-1;
+#else
+#error
+#endif
}
bool flext::SetPriority(int p,thrid_t id)
{
+#if FLEXT_THREADS == FLEXT_THR_POSIX
sched_param parm;
int policy;
if(pthread_getschedparam(id,&policy,&parm) < 0) {
@@ -311,12 +403,34 @@ 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;
+#else
+#error
+#endif
}
-flext_base::thr_params::thr_params(flext_base *c,int n): cl(c),var(new _data[n]) {}
+
+flext_base::thr_params::thr_params(int n): cl(NULL),var(new _data[n]) {}
flext_base::thr_params::~thr_params() { if(var) delete[] var; }
void flext_base::thr_params::set_any(const t_symbol *s,int argc,const t_atom *argv) { var[0]._any.args = new AtomAnything(s,argc,argv); }
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)
+{}
+
+
#endif // FLEXT_THREADS
diff --git a/externals/grill/flext/tutorial/maxmsp/ex-thread1 b/externals/grill/flext/tutorial/maxmsp/ex-thread1
new file mode 100755
index 00000000..cd204b4a
--- /dev/null
+++ b/externals/grill/flext/tutorial/maxmsp/ex-thread1
Binary files differ
diff --git a/externals/grill/flext/tutorial/maxmsp/ex-thread2 b/externals/grill/flext/tutorial/maxmsp/ex-thread2
new file mode 100755
index 00000000..d68690c4
--- /dev/null
+++ b/externals/grill/flext/tutorial/maxmsp/ex-thread2
Binary files differ
diff --git a/externals/grill/flext/tutorial/pd/ex-thread1.pd b/externals/grill/flext/tutorial/pd/ex-thread1.pd
index 67d673db..341bcc37 100644
--- a/externals/grill/flext/tutorial/pd/ex-thread1.pd
+++ b/externals/grill/flext/tutorial/pd/ex-thread1.pd
@@ -1,43 +1,43 @@
-#N canvas 105 266 700 343 12;
-#X obj 39 91 bng 25 250 50 0 empty empty start 0 -6 32 8 -261681 -1
--1;
-#X obj 39 244 thread1;
-#X obj 130 246 thread1;
-#X obj 220 247 thread1;
-#X obj 312 247 thread1;
-#X obj 405 247 thread1;
-#X obj 131 185 delay 200;
-#X obj 220 184 delay 200;
-#X obj 313 186 delay 200;
-#X obj 404 185 delay 200;
-#X text 78 85 click to start;
-#X text 126 103 (if you click twice \, the same thread is started a
-second time);
-#X obj 16 8 cnv 15 550 40 empty empty thread1 10 22 32 24 -260818 -1
-0;
-#X text 175 8 flext tutorial \, (C)2002 Thomas Grill;
-#X text 175 28 http://www.parasitaere-kapazitaeten.net;
-#X obj 39 277 nbx 5 16 -1e+37 1e+37 0 0 empty empty empty 0 -6 32 12
--228992 -1 -1 0 256;
-#X obj 131 277 nbx 5 16 -1e+37 1e+37 0 0 empty empty empty 0 -6 32
-12 -228992 -1 -1 0 256;
-#X obj 221 277 nbx 5 16 -1e+37 1e+37 0 0 empty empty empty 0 -6 32
-12 -228992 -1 -1 0 256;
-#X obj 311 277 nbx 5 16 -1e+37 1e+37 0 0 empty empty empty 0 -6 32
-12 -228992 -1 -1 0 256;
-#X obj 406 276 nbx 5 16 -1e+37 1e+37 0 0 empty empty empty 0 -6 32
-12 -228992 -1 -1 0 256;
-#X connect 0 0 1 0;
-#X connect 0 0 6 0;
-#X connect 1 0 15 0;
-#X connect 2 0 16 0;
-#X connect 3 0 17 0;
-#X connect 4 0 18 0;
-#X connect 5 0 19 0;
-#X connect 6 0 2 0;
-#X connect 6 0 7 0;
-#X connect 7 0 3 0;
-#X connect 7 0 8 0;
-#X connect 8 0 4 0;
-#X connect 8 0 9 0;
-#X connect 9 0 5 0;
+#N canvas 105 266 702 345 12;
+#X obj 39 91 bng 25 250 50 0 empty empty start 0 -6 0 8 -261681 -1
+-1;
+#X obj 130 246 thread1;
+#X obj 220 247 thread1;
+#X obj 312 247 thread1;
+#X obj 405 247 thread1;
+#X obj 131 185 delay 200;
+#X obj 220 184 delay 200;
+#X obj 313 186 delay 200;
+#X obj 404 185 delay 200;
+#X text 78 85 click to start;
+#X text 126 103 (if you click twice \, the same thread is started a
+second time);
+#X obj 16 8 cnv 15 550 40 empty empty thread1 10 22 0 24 -260818 -1
+0;
+#X text 175 8 flext tutorial \, (C)2002 Thomas Grill;
+#X text 175 28 http://www.parasitaere-kapazitaeten.net;
+#X obj 131 277 nbx 5 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0
+12 -228992 -1 -1 0 256;
+#X obj 221 277 nbx 5 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0
+12 -228992 -1 -1 0 256;
+#X obj 311 277 nbx 5 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0
+12 -228992 -1 -1 0 256;
+#X obj 406 276 nbx 5 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0
+12 -228992 -1 -1 0 256;
+#X obj 39 244 thread1;
+#X obj 39 277 nbx 5 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0
+12 -228992 -1 -1 0 256;
+#X connect 0 0 5 0;
+#X connect 0 0 18 0;
+#X connect 1 0 14 0;
+#X connect 2 0 15 0;
+#X connect 3 0 16 0;
+#X connect 4 0 17 0;
+#X connect 5 0 1 0;
+#X connect 5 0 6 0;
+#X connect 6 0 2 0;
+#X connect 6 0 7 0;
+#X connect 7 0 3 0;
+#X connect 7 0 8 0;
+#X connect 8 0 4 0;
+#X connect 18 0 19 0;
diff --git a/externals/grill/flext/tutorial/readme.txt b/externals/grill/flext/tutorial/readme.txt
index fa86a5ce..3e7004a1 100644
--- a/externals/grill/flext/tutorial/readme.txt
+++ b/externals/grill/flext/tutorial/readme.txt
@@ -39,7 +39,7 @@ o Metrowerks CodeWarrior V6: edit & use the several ".cw" project files
Max/MSP - MacOSX:
------------------
-... sorry, not yet... would someone please donate me a CodeWarrior V8 ?
+o Metrowerks CodeWarrior V6: edit & use the several ".cw" project files
----------------------------------------------------------------------------
diff --git a/externals/grill/flext/tutorial/thread1/main.cpp b/externals/grill/flext/tutorial/thread1/main.cpp
index 72fb1019..f5e2a651 100644
--- a/externals/grill/flext/tutorial/thread1/main.cpp
+++ b/externals/grill/flext/tutorial/thread1/main.cpp
@@ -37,7 +37,7 @@ protected:
void m_start(); // method function
private:
- // define threaded callback for method m_start (with boolean argument)
+ // define threaded callback for method m_start
// the same syntax as with FLEXT_CALLBACK is used here
FLEXT_THREAD(m_start);
};
@@ -64,17 +64,19 @@ void thread1::m_start()
for(int i = 0; i < 20 && !ShouldExit(); ++i) {
ToOutInt(0,i); // output loop count
+// post("%i",i);
// wait for half a second
for(int j = 0; j < 5 && !ShouldExit(); ++j) Sleep(0.1f);
// note: we shall not block a thread for a longer time.
// The system might want to destroy the object in the meantime and
- // expects thread termination.
- // Flext waits for 1 second by default, then it aborts the thread brutally
+ // expects thread termination. In such a case flext waits
+ // for 1 second by default, then it aborts the thread brutally
}
// output a final zero
ToOutInt(0,0);
+// post("end");
}
diff --git a/externals/grill/flext/tutorial/thread1/thread1.cw b/externals/grill/flext/tutorial/thread1/thread1.cw
index f971d4a3..680bdfba 100644
--- a/externals/grill/flext/tutorial/thread1/thread1.cw
+++ b/externals/grill/flext/tutorial/thread1/thread1.cw
Binary files differ
diff --git a/externals/grill/flext/tutorial/thread2/main.cpp b/externals/grill/flext/tutorial/thread2/main.cpp
index bd6354a2..2cdc37c3 100644
--- a/externals/grill/flext/tutorial/thread2/main.cpp
+++ b/externals/grill/flext/tutorial/thread2/main.cpp
@@ -88,18 +88,18 @@ void thread2::m_start(int st)
ToOutInt(0,count); // output loop count
}
- cond.Lock(); // lock conditional
running = false; // change state flag
- cond.Signal(); // signal changed flag to watiting "stop" method
- cond.Unlock(); // unlock conditional
+// cond.Lock(); // lock conditional
+ cond.Signal(); // signal changed flag to waiting "stop" method
+// cond.Unlock(); // unlock conditional
}
void thread2::m_stop()
{
- cond.Lock(); // lock conditional
+// cond.Lock(); // lock conditional
stopit = true; // set termination flag
- while(*(&running) || *(&blipping)) // workaround for CodeWarrior!
+ while(*(&running) || *(&blipping)) // workaround for CodeWarrior (doesn't honor volatile modifier!)
{
cond.Wait(); // wait for signal by running threads
}
@@ -107,7 +107,7 @@ void thread2::m_stop()
// --- Here, the threads should have stopped ---
stopit = false; // reset flag
- cond.Unlock(); // unlock conditional
+// cond.Unlock(); // unlock conditional
}
@@ -126,9 +126,9 @@ void thread2::m_textout()
Sleep(1.f);
}
- cond.Lock(); // lock conditional
blipping = false; // change state flag
- cond.Signal(); // signal changed flag to watiting "stop" method
- cond.Unlock(); // unlock conditional
+// cond.Lock(); // lock conditional
+ cond.Signal(); // signal changed flag to waiting "stop" method
+// cond.Unlock(); // unlock conditional
}
diff --git a/externals/grill/flext/tutorial/thread2/thread2.cw b/externals/grill/flext/tutorial/thread2/thread2.cw
index af968e69..524ad776 100755
--- a/externals/grill/flext/tutorial/thread2/thread2.cw
+++ b/externals/grill/flext/tutorial/thread2/thread2.cw
Binary files differ