aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2005-12-12 00:18:21 +0000
committerThomas Grill <xovo@users.sourceforge.net>2005-12-12 00:18:21 +0000
commitd1297bad7d860014ff6a4aa3ce66002125c7d0ac (patch)
tree5e79ae7505fc8d41f950b4a93ca2c2577bf2f691
parentfdca1f5103adda0421002ef21370b434ed4c8202 (diff)
new flext::CopyAtoms function
fixed dangerous spot (also memory leak) with message queuing flext::Forward has more incarnations now fixed and cleaned up library related stuff, especially co-existance of Max message and DSP library objects some minor changes after valgrind run more pthreads V2 fixes added message bundles (flext::MsgBundle) save some space saving inlet pointers fix uninitialized pointer update docs svn path=/trunk/; revision=4189
-rw-r--r--externals/grill/flext/changes.txt3
-rw-r--r--externals/grill/flext/flext.vcproj2
-rw-r--r--externals/grill/flext/source/flatom.cpp22
-rw-r--r--externals/grill/flext/source/flbase.h2
-rw-r--r--externals/grill/flext/source/flclass.h108
-rw-r--r--externals/grill/flext/source/flext.cpp10
-rw-r--r--externals/grill/flext/source/flout.cpp52
-rwxr-xr-xexternals/grill/flext/source/flqueue.cpp349
-rw-r--r--externals/grill/flext/source/flsupport.cpp4
-rw-r--r--externals/grill/flext/source/flsupport.h70
10 files changed, 469 insertions, 153 deletions
diff --git a/externals/grill/flext/changes.txt b/externals/grill/flext/changes.txt
index 6c862aaa..65826efc 100644
--- a/externals/grill/flext/changes.txt
+++ b/externals/grill/flext/changes.txt
@@ -23,6 +23,9 @@ Version history:
- fixed coexistence of message and signal objects in Max/MSP object libraries
- fixes for pthreads version 2
- deprecated FLEXT_GLOBALNEW in favor of FLEXT_USECMEM (either global new/delete operators or C library memory allocation)
+- fixing uninitialized pointer (first inlet pointer)
+- added message bundle functionality (to send more messages over the thread boundary to arrive at the same logical time)
+- fixed dangerous spot (also memory leak) with message queuing
0.5.0:
- fixes for 64 bit builds (size_t is integer type of pointer size)
diff --git a/externals/grill/flext/flext.vcproj b/externals/grill/flext/flext.vcproj
index a763ee7d..3eaa1c6b 100644
--- a/externals/grill/flext/flext.vcproj
+++ b/externals/grill/flext/flext.vcproj
@@ -121,7 +121,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="c:\data\prog\packs\pthreads\include;c:\programme\audio\pd\src;c:\data\prog\audio\sndobj\include;c:\data\prog\audio\stk\include"
+ AdditionalIncludeDirectories="c:\data\prog\packs\pthreads\include;&quot;c:\data\pd\pd-cvs\src&quot;;c:\data\prog\audio\sndobj\include;c:\data\prog\audio\stk\include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLEXT_SYS_PD;FLEXT_THREADS;FLEXT_USE_SIMD;FLEXT_EXPORTS;xFLEXT_ATTRHIDE;xFLEXT_NOATTREDIT;_WIN32_WINNT=0x501"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
diff --git a/externals/grill/flext/source/flatom.cpp b/externals/grill/flext/source/flatom.cpp
index ae133425..9f433222 100644
--- a/externals/grill/flext/source/flatom.cpp
+++ b/externals/grill/flext/source/flatom.cpp
@@ -48,7 +48,7 @@ t_atom *flext::CopyList(int argc,const t_atom *argv)
return dst;
}
-static void copyatoms(int cnt,t_atom *dst,const t_atom *src)
+void flext::CopyAtoms(int cnt,t_atom *dst,const t_atom *src)
{
if(dst < src)
// forward
@@ -63,16 +63,22 @@ void flext::AtomList::Alloc(int sz,int keepix,int keeplen,int keepto)
if(lst) {
if(cnt == sz) return; // no change
- t_atom *l = new t_atom[sz];
- if(keepix >= 0)
- // keep contents
- copyatoms(keeplen >= 0?keeplen:(cnt > sz?sz:cnt),l+keepto,lst+keepix);
+ t_atom *l;
+ if(sz) {
+ l = new t_atom[sz];
+ if(keepix >= 0)
+ // keep contents
+ CopyAtoms(keeplen >= 0?keeplen:(cnt > sz?sz:cnt),l+keepto,lst+keepix);
+ }
+ else
+ l = NULL;
+
delete[] lst;
lst = l,cnt = sz;
}
else {
FLEXT_ASSERT(cnt == 0);
- lst = new t_atom[cnt = sz];
+ if(sz) lst = new t_atom[cnt = sz];
}
}
@@ -94,7 +100,7 @@ flext::AtomList &flext::AtomList::Set(int argc,const t_atom *argv,int offs,bool
if(resize) Alloc(ncnt);
// argv can be NULL independently from argc
- if(argv) copyatoms(argc,lst+offs,argv);
+ if(argv) CopyAtoms(argc,lst+offs,argv);
return *this;
}
@@ -120,7 +126,7 @@ void flext::AtomListStaticBase::Alloc(int sz,int keepix,int keeplen,int keepto)
if(lst != predata && lst) {
if(keepix >= 0)
// keep contents
- copyatoms(keeplen >= 0?keeplen:(cnt > sz?sz:cnt),predata+keepto,lst+keepix);
+ CopyAtoms(keeplen >= 0?keeplen:(cnt > sz?sz:cnt),predata+keepto,lst+keepix);
AtomList::Free();
}
lst = predata,cnt = sz;
diff --git a/externals/grill/flext/source/flbase.h b/externals/grill/flext/source/flbase.h
index 5560e74a..b0155b1c 100644
--- a/externals/grill/flext/source/flbase.h
+++ b/externals/grill/flext/source/flbase.h
@@ -160,8 +160,8 @@ class FLEXT_SHARE FLEXT_CLASSDEF(flext_obj):
static bool IsLib(t_classid id);
bool HasAttributes() const;
- bool IsDSP() const;
bool IsLib() const;
+ bool IsDSP() const;
#if FLEXT_SYS == FLEXT_SYS_MAX
// under Max/MSP it could be necessary to activate DSP also for message objects
diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h
index 1e18cd93..e7a16957 100644
--- a/externals/grill/flext/source/flclass.h
+++ b/externals/grill/flext/source/flclass.h
@@ -192,8 +192,6 @@ public:
//! Get number of signal outlets
int CntOutSig() const { return outsigs; }
- //! Check if we are in DSP time
- static bool InDsp() { return indsp; }
//! Retrieve currently processed message tag (NULL if no message processing)
static const t_symbol *thisTag() { return curtag; }
@@ -249,38 +247,44 @@ public:
@{
*/
- //! Output bang (index n starts with 0)
+ //! Output low priority bang (index n starts with 0)
void ToQueueBang(int n) const;
- //! Output float (index n starts with 0)
+ //! Output low priority float (index n starts with 0)
void ToQueueFloat(int n,float f) const;
- //! Output integer (index n starts with 0)
+ //! Output low priority integer (index n starts with 0)
void ToQueueInt(int n,int f) const;
- //! Output boolean (index n starts with 0)
+ //! Output low priority boolean (index n starts with 0)
void ToQueueBool(int n,bool f) const { ToQueueInt(n,f?1:0); }
- //! Output symbol (index n starts with 0)
+ //! Output low priority symbol (index n starts with 0)
void ToQueueSymbol(int n,const t_symbol *s) const;
- //! Output string aka symbol (to appointed outlet)
+ //! Output low priority string aka symbol (to appointed outlet)
void ToQueueString(int n,const char *s) const { ToQueueSymbol(n,MakeSymbol(s)); }
- //! Output atom (index n starts with 0)
+ //! Output low priority atom (index n starts with 0)
void ToQueueAtom(int n,const t_atom &at) const;
- //! Output list (index n starts with 0)
+ //! Output low priority list (index n starts with 0)
void ToQueueList(int n,int argc,const t_atom *argv) const;
- //! Output list (index n starts with 0)
+ //! Output low priority list (index n starts with 0)
void ToQueueList(int n,const AtomList &list) const { ToQueueList(n,list.Count(),list.Atoms()); }
- //! Output anything (index n starts with 0)
+ //! Output low priority anything (index n starts with 0)
void ToQueueAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const;
- //! Output anything (index n starts with 0)
+ //! Output low priority anything (index n starts with 0)
void ToQueueAnything(int n,const AtomAnything &any) const { ToQueueAnything(n,any.Header(),any.Count(),any.Atoms()); }
+ //! @} FLEXT_C_IO_QUEUE
+
- //! Send bang to self (inlet n)
+ /*! \defgroup FLEXT_C_IO_SELF Output of data to inlets/outlets of this object
+ @{
+ */
+
+ //! Send bang to self (inlet n)
void ToSelfBang(int n) const { ToQueueBang(-1-n); }
//! Send float to self (inlet n)
@@ -310,7 +314,76 @@ public:
//! Send anything to self (inlet n)
void ToSelfAnything(int n,const AtomAnything &any) const { ToSelfAnything(n,any.Header(),any.Count(),any.Atoms()); }
-//! @} FLEXT_C_IO_QUEUE
+ //! @} FLEXT_C_IO_SELF
+
+
+ /*! \defgroup FLEXT_C_IO_MESSAGEBUNDLE Output of data via message bundles
+
+ These are used to assure the sending of several messages from a second thread to the same logical time
+
+ @{
+ */
+
+ //! Output bang (index n starts with 0)
+ void MsgAddBang(MsgBundle *mb,int n) const;
+
+ //! Output float (index n starts with 0)
+ void MsgAddFloat(MsgBundle *mb,int n,float f) const;
+
+ //! Output integer (index n starts with 0)
+ void MsgAddInt(MsgBundle *mb,int n,int f) const;
+
+ //! Output boolean (index n starts with 0)
+ void MsgAddBool(MsgBundle *mb,int n,bool f) const { MsgAddInt(mb,n,f?1:0); }
+
+ //! Output symbol (index n starts with 0)
+ void MsgAddSymbol(MsgBundle *mb,int n,const t_symbol *s) const;
+ //! Output string aka symbol (to appointed outlet)
+ void MsgAddString(MsgBundle *mb,int n,const char *s) const { MsgAddSymbol(mb,n,MakeSymbol(s)); }
+
+ //! Output atom (index n starts with 0)
+ void MsgAddAtom(MsgBundle *mb,int n,const t_atom &at) const;
+
+ //! Output list (index n starts with 0)
+ void MsgAddList(MsgBundle *mb,int n,int argc,const t_atom *argv) const;
+ //! Output list (index n starts with 0)
+ void MsgAddList(MsgBundle *mb,int n,const AtomList &list) const { MsgAddList(mb,n,list.Count(),list.Atoms()); }
+
+ //! Output anything (index n starts with 0)
+ void MsgAddAnything(MsgBundle *mb,int n,const t_symbol *s,int argc,const t_atom *argv) const;
+ //! Output anything (index n starts with 0)
+ void MsgAddAnything(MsgBundle *mb,int n,const AtomAnything &any) const { MsgAddAnything(mb,n,any.Header(),any.Count(),any.Atoms()); }
+
+ void MsgSelfBang(MsgBundle *mb,int n) const { MsgAddBang(mb,-1-n); }
+
+ //! Send float to self (inlet n)
+ void MsgSelfFloat(MsgBundle *mb,int n,float f) const { MsgAddFloat(mb,-1-n,f); }
+
+ //! Send integer to self (inlet n)
+ void MsgSelfInt(MsgBundle *mb,int n,int f) const { MsgAddInt(mb,-1-n,f); }
+
+ //! Send boolean to self (inlet n)
+ void MsgSelfBool(MsgBundle *mb,int n,bool f) const { MsgSelfInt(mb,n,f?1:0); }
+
+ //! Send symbol to self (inlet n)
+ void MsgSelfSymbol(MsgBundle *mb,int n,const t_symbol *s) const { MsgAddSymbol(mb,-1-n,s); }
+ //! Send string aka symbol to self (inlet 0)
+ void MsgSelfString(MsgBundle *mb,int n,const char *s) const { MsgSelfSymbol(mb,n,MakeSymbol(s)); }
+
+ //! Output atom (index n starts with 0)
+ void MsgSelfAtom(MsgBundle *mb,int n,const t_atom &at) const { MsgAddAtom(mb,-1-n,at); }
+
+ //! Send list to self (inlet n)
+ void MsgSelfList(MsgBundle *mb,int n,int argc,const t_atom *argv) const { MsgAddList(mb,-1-n,argc,argv); }
+ //! Send list to self (inlet n)
+ void MsgSelfList(MsgBundle *mb,int n,const AtomList &list) const { MsgSelfList(mb,n,list.Count(),list.Atoms()); }
+
+ //! Send anything to self (inlet n)
+ void MsgSelfAnything(MsgBundle *mb,int n,const t_symbol *s,int argc,const t_atom *argv) const { MsgAddAnything(mb,-1-n,s,argc,argv); }
+ //! Send anything to self (inlet n)
+ void MsgSelfAnything(MsgBundle *mb,int n,const AtomAnything &any) const { MsgSelfAnything(mb,n,any.Header(),any.Count(),any.Atoms()); }
+
+ //! @} FLEXT_C_IO_MESSAGEBUNDLE
//! @} FLEXT_C_INOUT
@@ -764,6 +837,8 @@ protected:
void ToSysBool(int n,bool f) const { ToSysInt(n,f?1:0); }
void ToSysAtom(int n,const t_atom &at) const;
+ static void ToSysMsg(MsgBundle *mb);
+
// add class method handlers
static void AddMessageMethods(t_class *c);
static void AddSignalMethods(t_class *c);
@@ -798,9 +873,6 @@ public:
void AddAttrib(const t_symbol *attr,metharg tp,methfun gfun,methfun sfun);
static void AddAttrib(t_classid c,const t_symbol *attr,metharg tp,methfun gfun,methfun sfun);
- //! flag if we are within DSP
- static bool indsp;
-
private:
static inline flext_base *thisObject(flext_hdr *c) { return FLEXT_CAST<flext_base *>(c->data); }
diff --git a/externals/grill/flext/source/flext.cpp b/externals/grill/flext/source/flext.cpp
index f332ce65..df0f0b61 100644
--- a/externals/grill/flext/source/flext.cpp
+++ b/externals/grill/flext/source/flext.cpp
@@ -20,7 +20,6 @@ WARRANTIES, see the file, "license.txt," in this distribution.
// === flext_base ============================================
bool flext_base::compatibility = true;
-bool flext_base::indsp = false;
const t_symbol *flext_base::curtag = NULL;
flext_base::FLEXT_CLASSDEF(flext_base)()
@@ -113,13 +112,14 @@ void flext_base::Exit()
if(outlets) delete[] outlets;
if(inlets) {
- for(int ix = 0; ix < incnt; ++ix)
- if(inlets[ix]) {
+ FLEXT_ASSERT(incnt > 1);
+ for(int ix = 1; ix < incnt; ++ix)
+ if(inlets[ix-1]) {
// release proxy object
#if FLEXT_SYS == FLEXT_SYS_PD
- pd_free(&inlets[ix]->obj.ob_pd);
+ pd_free(&inlets[ix-1]->obj.ob_pd);
#elif FLEXT_SYS == FLEXT_SYS_MAX
- freeobject((object *)inlets[ix]);
+ freeobject((object *)inlets[ix-1]);
#endif
}
delete[] inlets;
diff --git a/externals/grill/flext/source/flout.cpp b/externals/grill/flext/source/flout.cpp
index c95bf8fa..67ab40c0 100644
--- a/externals/grill/flext/source/flout.cpp
+++ b/externals/grill/flext/source/flout.cpp
@@ -45,12 +45,12 @@ void flext_base::ToSysAtom(int n,const t_atom &at) const
#if defined(FLEXT_THREADS)
#if FLEXT_QMODE == 2
- #define CHKTHR() ((IsSystemThread() || IsThread(flext::thrmsgid)) && !InDsp())
+ #define CHKTHR() ((IsSystemThread() || IsThread(flext::thrmsgid)) && !InDSP())
#else
- #define CHKTHR() (IsSystemThread() && !InDsp())
+ #define CHKTHR() (IsSystemThread() && !InDSP())
#endif
#else
- #define CHKTHR() (!InDsp())
+ #define CHKTHR() (!InDSP())
#endif
void flext_base::ToOutBang(int n) const { if(CHKTHR()) ToSysBang(n); else ToQueueBang(n); }
@@ -61,6 +61,13 @@ void flext_base::ToOutAtom(int n,const t_atom &at) const { if(CHKTHR()) ToSysAto
void flext_base::ToOutList(int n,int argc,const t_atom *argv) const { if(CHKTHR()) ToSysList(n,argc,argv); else ToQueueList(n,argc,argv); }
void flext_base::ToOutAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const { if(CHKTHR()) ToSysAnything(n,s,argc,argv); else ToQueueAnything(n,s,argc,argv); }
+void flext::ToOutMsg(MsgBundle *mb) { if(CHKTHR()) ToSysMsg(mb); else ToQueueMsg(mb); }
+
+bool flext::Forward(const t_symbol *recv,const t_symbol *s,int argc,const t_atom *argv)
+{
+ return CHKTHR()?SysForward(recv,s,argc,argv):QueueForward(recv,s,argc,argv);
+}
+
bool flext_base::InitInlets()
{
@@ -86,7 +93,7 @@ bool flext_base::InitInlets()
#endif
#if FLEXT_SYS == FLEXT_SYS_PD || FLEXT_SYS == FLEXT_SYS_MAX
- inlets = new px_object *[incnt];
+ inlets = incnt > 1?new px_object *[incnt]:NULL;
#endif
// type info is now in list array
@@ -104,7 +111,6 @@ bool flext_base::InitInlets()
// this is on a per-class basis... we cannot really use it here
// if(xi.desc && *xi.desc) class_settip(thisClass(),gensym(xi.desc));
#endif
- inlets[0] = NULL;
}
for(int ix = 1; ix < incnt; ++ix,++cnt) {
@@ -113,7 +119,7 @@ bool flext_base::InitInlets()
switch(xi.tp) {
case xlet_float:
case xlet_int: {
- inlets[ix] = NULL;
+ inlets[ix-1] = NULL;
char sym[] = "ft??";
if(ix >= 10) {
if(compatibility) {
@@ -133,19 +139,19 @@ bool flext_base::InitInlets()
break;
}
case xlet_sym:
- (inlets[ix] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages
- in = inlet_new(&x_obj->obj,&inlets[ix]->obj.ob_pd, (t_symbol *)sym_symbol, (t_symbol *)sym_symbol);
+ (inlets[ix-1] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages
+ in = inlet_new(&x_obj->obj,&inlets[ix-1]->obj.ob_pd, (t_symbol *)sym_symbol, (t_symbol *)sym_symbol);
break;
case xlet_list:
- (inlets[ix] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages
- in = inlet_new(&x_obj->obj,&inlets[ix]->obj.ob_pd, (t_symbol *)sym_list, (t_symbol *)sym_list);
+ (inlets[ix-1] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages
+ in = inlet_new(&x_obj->obj,&inlets[ix-1]->obj.ob_pd, (t_symbol *)sym_list, (t_symbol *)sym_list);
break;
case xlet_any:
- (inlets[ix] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages
- in = inlet_new(&x_obj->obj,&inlets[ix]->obj.ob_pd, 0, 0);
+ (inlets[ix-1] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages
+ in = inlet_new(&x_obj->obj,&inlets[ix-1]->obj.ob_pd, 0, 0);
break;
case xlet_sig:
- inlets[ix] = NULL;
+ inlets[ix-1] = NULL;
if(compatibility && inlist[ix-1].tp != xlet_sig) {
post("%s: All signal inlets must be left-aligned in compatibility mode",thisName());
ok = false;
@@ -158,7 +164,7 @@ bool flext_base::InitInlets()
}
break;
default:
- inlets[ix] = NULL;
+ inlets[ix-1] = NULL;
error("%s: Wrong type for inlet #%i: %i",thisName(),ix,(int)inlist[ix].tp);
ok = false;
}
@@ -180,7 +186,6 @@ bool flext_base::InitInlets()
for(cnt = 0,ix = incnt-1; ix >= insigs; --ix,++cnt) {
xlet &xi = inlist[ix];
if(ix == 0) {
- inlets[ix] = NULL;
if(xi.tp != xlet_any) {
error("%s: Leftmost inlet must be of type signal or anything",thisName());
ok = false;
@@ -189,13 +194,13 @@ bool flext_base::InitInlets()
else {
switch(xi.tp) {
case xlet_sig:
- inlets[ix] = NULL;
+ inlets[ix-1] = NULL;
error("%s: All signal inlets must be left-aligned",thisName());
ok = false;
break;
case xlet_float: {
if(ix < 10) {
- inlets[ix] = NULL;
+ inlets[ix-1] = NULL;
floatin(x_obj,ix);
break;
}
@@ -204,7 +209,7 @@ bool flext_base::InitInlets()
}
case xlet_int: {
if(ix < 10) {
- inlets[ix] = NULL;
+ inlets[ix-1] = NULL;
intin(x_obj,ix);
break;
}
@@ -215,17 +220,17 @@ bool flext_base::InitInlets()
case xlet_any: // non-leftmost
case xlet_sym:
case xlet_list:
- inlets[ix] = (px_object *)proxy_new(x_obj,ix,&((flext_hdr *)x_obj)->curinlet);
+ inlets[ix-1] = (px_object *)proxy_new(x_obj,ix,&((flext_hdr *)x_obj)->curinlet);
break;
default:
- inlets[ix] = NULL;
+ inlets[ix-1] = NULL;
error("%s: Wrong type for inlet #%i: %i",thisName(),ix,(int)xi.tp);
ok = false;
}
}
}
- while(ix >= 0) inlets[ix--] = NULL;
+ while(ix > 0) inlets[ix--] = NULL;
}
#else
#error
@@ -266,7 +271,10 @@ bool flext_base::InitOutlets()
#endif
#if FLEXT_SYS == FLEXT_SYS_PD || FLEXT_SYS == FLEXT_SYS_MAX
- outlets = new outlet *[outcnt+procattr];
+ if(outcnt+procattr)
+ outlets = new outlet *[outcnt+procattr];
+ else
+ outlets = NULL;
// type info is now in list array
#if FLEXT_SYS == FLEXT_SYS_PD
diff --git a/externals/grill/flext/source/flqueue.cpp b/externals/grill/flext/source/flqueue.cpp
index a83aa01e..b0080ba1 100755
--- a/externals/grill/flext/source/flqueue.cpp
+++ b/externals/grill/flext/source/flqueue.cpp
@@ -38,93 +38,81 @@ static bool qustarted = false;
static void Trigger();
-class qmsg:
+
+class flext::MsgBundle;
+
+typedef PooledFifo<flext::MsgBundle> QueueFifo;
+
+class Queue:
public flext,
- public Fifo::Cell
+ public QueueFifo
{
public:
- inline qmsg &Set(flext_base *t,int o,const t_symbol *s,int ac,const t_atom *av)
- {
- th = t;
- out = o;
- msg(s,ac,av);
- return *this;
- }
+ inline bool Empty() const { return Size() == 0; }
- inline qmsg &Set(const t_symbol *r,const t_symbol *s,int ac,const t_atom *av)
+ inline void Push(MsgBundle *m)
{
- th = NULL;
- recv = r;
- msg(s,ac,av);
- return *this;
- }
-
- // \note PD sys lock must already be held by caller
- inline void Send() const
- {
- if(th) {
- if(out < 0)
- // message to self
- th->CbMethodHandler(-1-out,msg.Header(),msg.Count(),msg.Atoms());
- else
- // message to outlet
- th->ToSysAnything(out,msg.Header(),msg.Count(),msg.Atoms());
+ if(m) {
+ Put(m);
+ Trigger();
}
- else
- flext::Forward(recv,msg,true);
}
-
-private:
- flext_base *th;
- union {
- int out;
- const t_symbol *recv;
- };
- AtomAnything msg;
};
+static Queue queue;
-typedef PooledFifo<qmsg> QueueFifo;
+#define STATSIZE 8
-class Queue:
+class flext::MsgBundle:
public flext,
- public QueueFifo
+ public Fifo::Cell
{
public:
- inline bool Empty() const { return Size() == 0; }
+ static MsgBundle *New()
+ {
+ MsgBundle *m = queue.New();
+ m->msg.Init();
+ return m;
+ }
+
+ static void Free(MsgBundle *m)
+ {
+ for(Msg *mi = m->msg.nxt; mi; ) {
+ Msg *mn = mi->nxt;
+ mi->Free();
+ delete mi;
+ mi = mn;
+ }
+ m->msg.Free();
+ queue.Free(m);
+ }
- inline void Push(flext_base *t,int o,const t_symbol *s,int ac,const t_atom *av)
+ inline MsgBundle &Add(flext_base *t,int o,const t_symbol *s,int ac,const t_atom *av)
{
- qmsg *m = QueueFifo::New();
- FLEXT_ASSERT(m);
- m->Set(t,o,s,ac,av);
- Put(m);
- Trigger();
+ Get()->Set(t,o,s,ac,av);
+ return *this;
}
- inline void Push(const t_symbol *r,const t_symbol *s,int ac,const t_atom *av)
+ inline MsgBundle &Add(const t_symbol *r,const t_symbol *s,int ac,const t_atom *av)
{
- qmsg *m = QueueFifo::New();
- FLEXT_ASSERT(m);
- m->Set(r,s,ac,av);
- Put(m);
- Trigger();
+ Get()->Set(r,s,ac,av);
+ return *this;
}
- inline void Push(flext_base *th,int o) // bang
+ inline MsgBundle &Add(flext_base *th,int o) // bang
{
- Push(th,o,sym_bang,0,NULL);
+ return Add(th,o,sym_bang,0,NULL);
}
- inline void Push(flext_base *th,int o,float dt)
+ inline MsgBundle &Add(flext_base *th,int o,float dt)
{
t_atom at;
SetFloat(at,dt);
- Push(th,o,sym_float,1,&at);
+ return Add(th,o,sym_float,1,&at);
}
- inline void Push(flext_base *th,int o,int dt)
+ inline MsgBundle &Add(flext_base *th,int o,int dt)
{
t_atom at;
SetInt(at,dt);
@@ -136,17 +124,17 @@ public:
#else
#error Not implemented!
#endif
- Push(th,o,sym,1,&at);
+ return Add(th,o,sym,1,&at);
}
- inline void Push(flext_base *th,int o,const t_symbol *dt)
+ inline MsgBundle &Add(flext_base *th,int o,const t_symbol *dt)
{
t_atom at;
SetSymbol(at,dt);
- Push(th,o,sym_symbol,1,&at);
+ return Add(th,o,sym_symbol,1,&at);
}
- void Push(flext_base *th,int o,const t_atom &a)
+ inline MsgBundle &Add(flext_base *th,int o,const t_atom &a)
{
const t_symbol *sym;
if(IsSymbol(a))
@@ -163,18 +151,119 @@ public:
#endif
else {
error("atom type not supported");
- return;
+ return *this;
}
- Push(th,o,sym,1,&a);
+ return Add(th,o,sym,1,&a);
}
- inline void Push(flext_base *th,int o,int argc,const t_atom *argv)
+ inline MsgBundle &Add(flext_base *th,int o,int argc,const t_atom *argv)
{
- Push(th,o,sym_list,argc,argv);
+ return Add(th,o,sym_list,argc,argv);
}
-};
-static Queue queue;
+ // \note PD sys lock must already be held by caller
+ inline void Send() const
+ {
+ FLEXT_ASSERT(msg.Ok());
+
+ const Msg *m = &msg;
+ do {
+ m->Send();
+ m = m->nxt;
+ } while(m);
+ }
+
+private:
+
+ class Msg {
+ public:
+ inline bool Ok() const { return th || recv; }
+
+ void Init()
+ {
+ th = NULL;
+ recv = NULL;
+ nxt = NULL;
+ argc = 0;
+ }
+
+ void Free()
+ {
+ if(argc > STATSIZE) {
+ FLEXT_ASSERT(argv);
+ delete[] argv;
+ }
+ }
+
+ void Set(flext_base *t,int o,const t_symbol *s,int ac,const t_atom *av)
+ {
+ FLEXT_ASSERT(t);
+ th = t;
+ out = o;
+ SetMsg(s,ac,av);
+}
+
+ void Set(const t_symbol *r,const t_symbol *s,int ac,const t_atom *av)
+ {
+ FLEXT_ASSERT(r);
+ th = NULL;
+ recv = r;
+ SetMsg(s,ac,av);
+ }
+
+ void Send() const
+ {
+ if(th) {
+ if(out < 0)
+ // message to self
+ th->CbMethodHandler(-1-out,sym,argc,argc > STATSIZE?argv:argl);
+ else
+ // message to outlet
+ th->ToSysAnything(out,sym,argc,argc > STATSIZE?argv:argl);
+ }
+ else
+ flext::SysForward(recv,sym,argc,argc > STATSIZE?argv:argl);
+ }
+
+ Msg *nxt;
+
+ protected:
+ flext_base *th;
+ union {
+ int out;
+ const t_symbol *recv;
+ };
+ const t_symbol *sym;
+ int argc;
+ union {
+ t_atom *argv;
+ t_atom argl[STATSIZE];
+ };
+
+ void SetMsg(const t_symbol *s,int cnt,const t_atom *lst)
+ {
+ sym = s;
+ argc = cnt;
+ if(cnt > STATSIZE) {
+ argv = new t_atom[cnt];
+ flext::CopyAtoms(cnt,argv,lst);
+ }
+ else
+ flext::CopyAtoms(cnt,argl,lst);
+ }
+
+ } msg;
+
+ Msg *Get()
+ {
+ Msg *m = &msg;
+ if(m->Ok()) {
+ for(; m->nxt; m = m->nxt) {}
+ m = m->nxt = new Msg;
+ }
+ return m;
+ }
+};
#if FLEXT_QMODE == 2
@@ -201,10 +290,10 @@ static void QWork(bool syslock)
if(syslock) flext::Lock();
#endif
- qmsg *q;
+ flext::MsgBundle *q;
while((q = queue.Get()) != NULL) {
q->Send();
- queue.Free(q);
+ flext::MsgBundle::Free(q);
}
#if FLEXT_QMODE == 2
@@ -329,58 +418,144 @@ void flext_base::StartQueue()
#endif
}
+
+flext::MsgBundle *flext::MsgNew()
+{
+ return MsgBundle::New();
+}
+
+void flext::MsgFree(MsgBundle *m)
+{
+ MsgBundle::Free(m);
+}
+
+void flext::ToSysMsg(MsgBundle *m)
+{
+ m->Send();
+ queue.Free(m);
+}
+
+void flext::ToQueueMsg(MsgBundle *m)
+{
+ queue.Push(m);
+}
+
+
+
void flext_base::ToQueueBang(int o) const
{
- queue.Push(const_cast<flext_base *>(this),o);
+ MsgBundle *m = MsgBundle::New();
+ m->Add(const_cast<flext_base *>(this),o);
+ queue.Push(m);
}
void flext_base::ToQueueFloat(int o,float f) const
{
- queue.Push(const_cast<flext_base *>(this),o,f);
+ MsgBundle *m = MsgBundle::New();
+ m->Add(const_cast<flext_base *>(this),o,f);
+ queue.Push(m);
}
void flext_base::ToQueueInt(int o,int f) const
{
- queue.Push(const_cast<flext_base *>(this),o,f);
+ MsgBundle *m = MsgBundle::New();
+ m->Add(const_cast<flext_base *>(this),o,f);
+ queue.Push(m);
}
void flext_base::ToQueueSymbol(int o,const t_symbol *s) const
{
- queue.Push(const_cast<flext_base *>(this),o,s);
+ MsgBundle *m = MsgBundle::New();
+ m->Add(const_cast<flext_base *>(this),o,s);
+ queue.Push(m);
}
void flext_base::ToQueueAtom(int o,const t_atom &at) const
{
- queue.Push(const_cast<flext_base *>(this),o,at);
+ MsgBundle *m = MsgBundle::New();
+ m->Add(const_cast<flext_base *>(this),o,at);
+ queue.Push(m);
}
void flext_base::ToQueueList(int o,int argc,const t_atom *argv) const
{
- queue.Push(const_cast<flext_base *>(this),o,argc,argv);
+ MsgBundle *m = MsgBundle::New();
+ m->Add(const_cast<flext_base *>(this),o,argc,argv);
+ queue.Push(m);
}
void flext_base::ToQueueAnything(int o,const t_symbol *s,int argc,const t_atom *argv) const
{
- queue.Push(const_cast<flext_base *>(this),o,s,argc,argv);
+ MsgBundle *m = MsgBundle::New();
+ m->Add(const_cast<flext_base *>(this),o,s,argc,argv);
+ queue.Push(m);
+}
+
+
+void flext_base::MsgAddBang(MsgBundle *m,int n) const
+{
+ m->Add(const_cast<flext_base *>(this),n);
+}
+
+void flext_base::MsgAddFloat(MsgBundle *m,int n,float f) const
+{
+ m->Add(const_cast<flext_base *>(this),n,f);
+}
+
+void flext_base::MsgAddInt(MsgBundle *m,int n,int f) const
+{
+ m->Add(const_cast<flext_base *>(this),n,f);
+}
+
+void flext_base::MsgAddSymbol(MsgBundle *m,int n,const t_symbol *s) const
+{
+ m->Add(const_cast<flext_base *>(this),n,s);
}
+void flext_base::MsgAddAtom(MsgBundle *m,int n,const t_atom &at) const
+{
+ m->Add(const_cast<flext_base *>(this),n,at);
+}
-bool flext::Forward(const t_symbol *recv,const t_symbol *s,int argc,const t_atom *argv,bool direct)
+void flext_base::MsgAddList(MsgBundle *m,int n,int argc,const t_atom *argv) const
{
- if(direct || IsSystemThread()) {
- void *cl = recv->s_thing;
- if(!cl) return false;
-
+ m->Add(const_cast<flext_base *>(this),n,argc,argv);
+}
+
+void flext_base::MsgAddAnything(MsgBundle *m,int n,const t_symbol *s,int argc,const t_atom *argv) const
+{
+ m->Add(const_cast<flext_base *>(this),n,s,argc,argv);
+}
+
+
+
+
+bool flext::SysForward(const t_symbol *recv,const t_symbol *s,int argc,const t_atom *argv)
+{
+ void *cl = recv->s_thing;
+ if(!cl) return false;
+
#if FLEXT_SYS == FLEXT_SYS_PD
- pd_typedmess((t_class **)cl,(t_symbol *)s,argc,(t_atom *)argv);
+ pd_typedmess((t_class **)cl,(t_symbol *)s,argc,(t_atom *)argv);
#elif FLEXT_SYS == FLEXT_SYS_MAX
- typedmess(recv->s_thing,(t_symbol *)s,argc,(t_atom *)argv);
+ typedmess(recv->s_thing,(t_symbol *)s,argc,(t_atom *)argv);
#else
#error Not implemented
#endif
- }
- else
- // send over queue
- queue.Push(recv,s,argc,argv);
+ return true;
+}
+
+bool flext::QueueForward(const t_symbol *recv,const t_symbol *s,int argc,const t_atom *argv)
+{
+ MsgBundle *m = MsgBundle::New();
+ m->Add(recv,s,argc,argv);
+ // send over queue
+ queue.Push(m);
+ return true;
+}
+
+bool flext::MsgForward(MsgBundle *m,const t_symbol *recv,const t_symbol *s,int argc,const t_atom *argv)
+{
+ m->Add(recv,s,argc,argv);
return true;
}
diff --git a/externals/grill/flext/source/flsupport.cpp b/externals/grill/flext/source/flsupport.cpp
index 3443eb46..929de35e 100644
--- a/externals/grill/flext/source/flsupport.cpp
+++ b/externals/grill/flext/source/flsupport.cpp
@@ -42,6 +42,8 @@ const t_symbol *flext::sym_size = NULL;
const t_symbol *flext::sym_attributes = NULL;
const t_symbol *flext::sym_methods = NULL;
+bool flext::indsp = false;
+
int flext::Version() { return FLEXT_VERSION; }
const char *flext::VersionStr() { return FLEXT_VERSTR; }
@@ -77,7 +79,7 @@ void flext::Setup()
sym_buffer = flext::MakeSymbol("buffer~");
sym_size = flext::MakeSymbol("size");
#endif
-
+
sym_attributes = flext::MakeSymbol("attributes");
sym_methods = flext::MakeSymbol("methods");
diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h
index eb358647..2a1b7a6d 100644
--- a/externals/grill/flext/source/flsupport.h
+++ b/externals/grill/flext/source/flsupport.h
@@ -339,6 +339,9 @@ public:
//! Copy an atom
static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
+ //! Copy atoms
+ static void CopyAtoms(int cnt,t_atom *dst,const t_atom *src);
+
//! Print an atom
static bool PrintAtom(const t_atom &a,char *buf,size_t bufsz);
@@ -707,27 +710,68 @@ public:
};
-//! @} FLEXT_S_ATOM
+ //! @} FLEXT_S_ATOM
// --- messages -------------------------------------------------------
- /*! \defgroup FLEXT_S_MSG Flext message handling
+ /*! \defgroup FLEXT_S_MSGBUNDLE Flext message handling
@{
*/
- //! Send a message to a symbol (bound to an object)
- static bool Forward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv,bool forcedirect = false);
+ class MsgBundle;
+
+ //! Make new message bundle
+ static MsgBundle *MsgNew();
+
+ //! Destroy message bundle
+ static void MsgFree(MsgBundle *mb);
+
+ //! Send (and destroy) message bundle
+ static void ToSysMsg(MsgBundle *mb);
+
+ //! Send (and destroy) message bundle
+ static void ToOutMsg(MsgBundle *mb);
- static bool Forward(const t_symbol *sym,const AtomAnything &args,bool forcedirect = false) { return Forward(sym,args.Header(),args.Count(),args.Atoms(),forcedirect); }
- static bool Forward(const char *sym,const AtomAnything &args,bool forcedirect = false) { return Forward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms(),forcedirect); }
+ //! Send low priority (and destroy) message bundle
+ static void ToQueueMsg(MsgBundle *mb);
- static bool Forward(const t_symbol *sym,int argc,const t_atom *argv,bool forcedirect = false) { return Forward(sym,sym_list,argc,argv,forcedirect); }
+ //! @} FLEXT_S_MSGBUNDLE
- static bool Forward(const t_symbol *sym,const AtomList &args,bool forcedirect = false) { return Forward(sym,args.Count(),args.Atoms(),forcedirect); }
- static bool Forward(const char *sym,const AtomList &args,bool forcedirect = false) { return Forward(MakeSymbol(sym),args.Count(),args.Atoms(),forcedirect); }
-//! @} FLEXT_S_MSG
+ /*! \defgroup FLEXT_S_MSG Flext message handling
+ @{
+ */
+
+ static bool Forward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
+ static bool Forward(const t_symbol *sym,const AtomAnything &args) { return Forward(sym,args.Header(),args.Count(),args.Atoms()); }
+ static bool Forward(const char *sym,const AtomAnything &args) { return Forward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
+ static bool Forward(const t_symbol *sym,int argc,const t_atom *argv) { return Forward(sym,sym_list,argc,argv); }
+ static bool Forward(const t_symbol *sym,const AtomList &args) { return Forward(sym,args.Count(),args.Atoms()); }
+ static bool Forward(const char *sym,const AtomList &args) { return Forward(MakeSymbol(sym),args.Count(),args.Atoms()); }
+
+ static bool SysForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
+ static bool SysForward(const t_symbol *sym,const AtomAnything &args) { return SysForward(sym,args.Header(),args.Count(),args.Atoms()); }
+ static bool SysForward(const char *sym,const AtomAnything &args) { return SysForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
+ static bool SysForward(const t_symbol *sym,int argc,const t_atom *argv) { return SysForward(sym,sym_list,argc,argv); }
+ static bool SysForward(const t_symbol *sym,const AtomList &args) { return SysForward(sym,args.Count(),args.Atoms()); }
+ static bool SysForward(const char *sym,const AtomList &args) { return SysForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
+
+ static bool QueueForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
+ static bool QueueForward(const t_symbol *sym,const AtomAnything &args) { return QueueForward(sym,args.Header(),args.Count(),args.Atoms()); }
+ static bool QueueForward(const char *sym,const AtomAnything &args) { return QueueForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
+ static bool QueueForward(const t_symbol *sym,int argc,const t_atom *argv) { return QueueForward(sym,sym_list,argc,argv); }
+ static bool QueueForward(const t_symbol *sym,const AtomList &args) { return QueueForward(sym,args.Count(),args.Atoms()); }
+ static bool QueueForward(const char *sym,const AtomList &args) { return QueueForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
+
+ static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
+ static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomAnything &args) { return MsgForward(mb,sym,args.Header(),args.Count(),args.Atoms()); }
+ static bool MsgForward(MsgBundle *mb,const char *sym,const AtomAnything &args) { return MsgForward(mb,MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
+ static bool MsgForward(MsgBundle *mb,const t_symbol *sym,int argc,const t_atom *argv) { return MsgForward(mb,sym,sym_list,argc,argv); }
+ static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomList &args) { return MsgForward(mb,sym,args.Count(),args.Atoms()); }
+ static bool MsgForward(MsgBundle *mb,const char *sym,const AtomList &args) { return MsgForward(mb,MakeSymbol(sym),args.Count(),args.Atoms()); }
+
+ //! @} FLEXT_S_MSG
@@ -1164,6 +1208,9 @@ public:
//! @} FLEXT_S_TIMER
+ //! Check if we are in DSP time
+ static bool InDSP() { return indsp; }
+
// --- SIMD functionality -----------------------------------------------
/*! \defgroup FLEXT_S_SIMD Cross platform SIMD support for modern CPUs
@@ -1210,6 +1257,9 @@ protected:
static const t_symbol *sym_size;
static const t_symbol *sym_attributes;
static const t_symbol *sym_methods;
+
+ //! flag if we are within DSP
+ static bool indsp;
};