From d1297bad7d860014ff6a4aa3ce66002125c7d0ac Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Mon, 12 Dec 2005 00:18:21 +0000 Subject: 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 --- externals/grill/flext/changes.txt | 3 + externals/grill/flext/flext.vcproj | 2 +- externals/grill/flext/source/flatom.cpp | 22 +- externals/grill/flext/source/flbase.h | 2 +- externals/grill/flext/source/flclass.h | 108 +++++++-- externals/grill/flext/source/flext.cpp | 10 +- externals/grill/flext/source/flout.cpp | 52 +++-- externals/grill/flext/source/flqueue.cpp | 349 ++++++++++++++++++++++------- externals/grill/flext/source/flsupport.cpp | 4 +- externals/grill/flext/source/flsupport.h | 70 +++++- 10 files changed, 469 insertions(+), 153 deletions(-) (limited to 'externals') 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 @@ = 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(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 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 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(this),o); + MsgBundle *m = MsgBundle::New(); + m->Add(const_cast(this),o); + queue.Push(m); } void flext_base::ToQueueFloat(int o,float f) const { - queue.Push(const_cast(this),o,f); + MsgBundle *m = MsgBundle::New(); + m->Add(const_cast(this),o,f); + queue.Push(m); } void flext_base::ToQueueInt(int o,int f) const { - queue.Push(const_cast(this),o,f); + MsgBundle *m = MsgBundle::New(); + m->Add(const_cast(this),o,f); + queue.Push(m); } void flext_base::ToQueueSymbol(int o,const t_symbol *s) const { - queue.Push(const_cast(this),o,s); + MsgBundle *m = MsgBundle::New(); + m->Add(const_cast(this),o,s); + queue.Push(m); } void flext_base::ToQueueAtom(int o,const t_atom &at) const { - queue.Push(const_cast(this),o,at); + MsgBundle *m = MsgBundle::New(); + m->Add(const_cast(this),o,at); + queue.Push(m); } void flext_base::ToQueueList(int o,int argc,const t_atom *argv) const { - queue.Push(const_cast(this),o,argc,argv); + MsgBundle *m = MsgBundle::New(); + m->Add(const_cast(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(this),o,s,argc,argv); + MsgBundle *m = MsgBundle::New(); + m->Add(const_cast(this),o,s,argc,argv); + queue.Push(m); +} + + +void flext_base::MsgAddBang(MsgBundle *m,int n) const +{ + m->Add(const_cast(this),n); +} + +void flext_base::MsgAddFloat(MsgBundle *m,int n,float f) const +{ + m->Add(const_cast(this),n,f); +} + +void flext_base::MsgAddInt(MsgBundle *m,int n,int f) const +{ + m->Add(const_cast(this),n,f); +} + +void flext_base::MsgAddSymbol(MsgBundle *m,int n,const t_symbol *s) const +{ + m->Add(const_cast(this),n,s); } +void flext_base::MsgAddAtom(MsgBundle *m,int n,const t_atom &at) const +{ + m->Add(const_cast(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(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(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; }; -- cgit v1.2.1