aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/flext
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2004-09-11 04:09:17 +0000
committerThomas Grill <xovo@users.sourceforge.net>2004-09-11 04:09:17 +0000
commit1fa5251f469a756d09f7f7c98113a69186688206 (patch)
tree173f1965bcde6297b4a70ac778a6cd37aa32e452 /externals/grill/flext
parentdf4fc5a5bf7bc65b610a497091f47e5ccc600874 (diff)
""
svn path=/trunk/; revision=2023
Diffstat (limited to 'externals/grill/flext')
-rw-r--r--externals/grill/flext/changes.txt1
-rw-r--r--externals/grill/flext/source/flatom.cpp3
-rw-r--r--externals/grill/flext/source/flbind.cpp4
-rw-r--r--externals/grill/flext/source/flclass.h12
-rwxr-xr-xexternals/grill/flext/source/flmeth.cpp4
-rwxr-xr-xexternals/grill/flext/source/flqueue.cpp359
6 files changed, 174 insertions, 209 deletions
diff --git a/externals/grill/flext/changes.txt b/externals/grill/flext/changes.txt
index d39e882e..8a9b6a9b 100644
--- a/externals/grill/flext/changes.txt
+++ b/externals/grill/flext/changes.txt
@@ -28,6 +28,7 @@ Version history:
- attribute editor: zoomed editor accepts , as newline separator
- attribute editor: close editor window on object destruction
- fixed $0-arguments in attribute saving
+- introducing ring buffer for message queue (thanks to Tom Schouten)
0.4.6:
- added a text edit window for list attributes
diff --git a/externals/grill/flext/source/flatom.cpp b/externals/grill/flext/source/flatom.cpp
index 45739e66..593a58b5 100644
--- a/externals/grill/flext/source/flatom.cpp
+++ b/externals/grill/flext/source/flatom.cpp
@@ -42,9 +42,8 @@ int flext::CmpAtom(const t_atom &a,const t_atom &b)
t_atom *flext::CopyList(int argc,const t_atom *argv)
{
- int i;
t_atom *dst = new t_atom[argc];
- for(i = 0; i < argc; ++i) CopyAtom(dst+i,argv+i);
+ memcpy(dst,argv,argc*sizeof(t_atom));
return dst;
}
diff --git a/externals/grill/flext/source/flbind.cpp b/externals/grill/flext/source/flbind.cpp
index 8eefefb4..ce775de0 100644
--- a/externals/grill/flext/source/flbind.cpp
+++ b/externals/grill/flext/source/flbind.cpp
@@ -35,7 +35,7 @@ void flext_base::SetupBindProxy()
#elif FLEXT_SYS == FLEXT_SYS_MAX
pxbnd_class = new t_class;
- pxbnd_class->c_sym = gensym("");
+ pxbnd_class->c_sym = sym__;
pxbnd_class->c_freelist = &px_freelist;
pxbnd_class->c_freefun = NULL;
pxbnd_class->c_size = sizeof(pxbnd_object);
@@ -43,7 +43,7 @@ void flext_base::SetupBindProxy()
pxbnd_class->c_noinlet = 1;
px_messlist[0].m_sym = (t_symbol *)pxbnd_class;
- px_messlist[1].m_sym = gensym("anything");
+ px_messlist[1].m_sym = sym_anything;
px_messlist[1].m_fun = (method)pxbnd_object::px_method;
px_messlist[1].m_type[0] = A_GIMME;
px_messlist[1].m_type[1] = 0;
diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h
index cd1d4943..5183c5fa 100644
--- a/externals/grill/flext/source/flclass.h
+++ b/externals/grill/flext/source/flclass.h
@@ -276,29 +276,29 @@ public:
//! Send bang to self (inlet n)
- void ToSelfBang(int n) const;
+ void ToSelfBang(int n) const { ToQueueBang(-1-n); }
//! Send float to self (inlet n)
- void ToSelfFloat(int n,float f) const;
+ void ToSelfFloat(int n,float f) const { ToQueueFloat(-1-n,f); }
//! Send integer to self (inlet n)
- void ToSelfInt(int n,int f) const;
+ void ToSelfInt(int n,int f) const { ToQueueInt(-1-n,f); }
//! Send boolean to self (inlet n)
void ToSelfBool(int n,bool f) const { ToSelfInt(n,f?1:0); }
//! Send symbol to self (inlet n)
- void ToSelfSymbol(int n,const t_symbol *s) const;
+ void ToSelfSymbol(int n,const t_symbol *s) const { ToQueueSymbol(-1-n,s); }
//! Send string aka symbol to self (inlet 0)
void ToSelfString(int n,const char *s) const { ToSelfSymbol(n,MakeSymbol(s)); }
//! Send list to self (inlet n)
- void ToSelfList(int n,int argc,const t_atom *argv) const;
+ void ToSelfList(int n,int argc,const t_atom *argv) const { ToQueueList(-1-n,argc,argv); }
//! Send list to self (inlet n)
void ToSelfList(int n,const AtomList &list) const { ToSelfList(n,list.Count(),list.Atoms()); }
//! Send anything to self (inlet n)
- void ToSelfAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const;
+ void ToSelfAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const { ToQueueAnything(-1-n,s,argc,argv); }
//! Send anything to self (inlet n)
void ToSelfAnything(int n,const AtomAnything &any) const { ToSelfAnything(n,any.Header(),any.Count(),any.Atoms()); }
diff --git a/externals/grill/flext/source/flmeth.cpp b/externals/grill/flext/source/flmeth.cpp
index 21e15f5c..eaaca622 100755
--- a/externals/grill/flext/source/flmeth.cpp
+++ b/externals/grill/flext/source/flmeth.cpp
@@ -125,10 +125,12 @@ void flext_base::ListMethods(AtomList &la,int inlet) const
bool flext_base::ListMethods(int inlet) const
{
+ static const t_symbol *sym_methods = MakeSymbol("methods");
+
if(procattr) {
AtomList la;
ListMethods(la,inlet);
- ToOutAnything(GetOutAttr(),MakeSymbol("methods"),la.Count(),la.Atoms());
+ ToOutAnything(GetOutAttr(),sym_methods,la.Count(),la.Atoms());
return true;
}
else
diff --git a/externals/grill/flext/source/flqueue.cpp b/externals/grill/flext/source/flqueue.cpp
index 41941734..4165e968 100755
--- a/externals/grill/flext/source/flqueue.cpp
+++ b/externals/grill/flext/source/flqueue.cpp
@@ -19,55 +19,160 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#include "flext.h"
#include "flinternal.h"
+
#ifdef FLEXT_THREADS
//! Thread id of message queue thread
flext::thrid_t flext::thrmsgid = 0;
#endif
+
+#define QUEUE_LENGTH 256
+#define QUEUE_ATOMS 1024
+
class qmsg
{
public:
- qmsg(flext_base *b): nxt(NULL),th(b),tp(tp_none) {}
- ~qmsg();
-
- qmsg *nxt;
-
- void Clear();
+ void Set(flext_base *t,int o,const t_symbol *s,int ac,const t_atom *av) { th = t,out = o,sym = s,argc = ac,argv = av; }
+
+ // \note PD lock must already be held by caller
+ void Send() const
+ {
+ if(out < 0)
+ // message to self
+ th->m_methodmain(-1-out,sym,argc,argv);
+ else
+ // message to outlet
+ th->ToSysAnything(out,sym,argc,argv);
+ }
- void SetBang(int o) { Clear(); out = o; tp = tp_bang; }
- void SetFloat(int o,float f) { Clear(); out = o; tp = tp_float; _float = f; }
- void SetInt(int o,int i) { Clear(); out = o; tp = tp_int; _int = i; }
- void SetSymbol(int o,const t_symbol *s) { Clear(); out = o; tp = tp_sym; _sym = s; }
- void SetList(int o,int argc,const t_atom *argv) { Clear(); out = o; tp = tp_list; _list.argc = argc,_list.argv = flext::CopyList(argc,argv); }
- void SetAny(int o,const t_symbol *s,int argc,const t_atom *argv) { Clear(); out = o; tp = tp_any; _any.s = s,_any.argc = argc,_any.argv = flext::CopyList(argc,argv); }
+ int Args() const { return argc; }
+private:
flext_base *th;
int out;
- enum { tp_none,tp_bang,tp_float,tp_int,tp_sym,tp_list,tp_any } tp;
- union {
- float _float;
- int _int;
- const t_symbol *_sym;
- struct { int argc; t_atom *argv; } _list;
- struct { const t_symbol *s; int argc; t_atom *argv; } _any;
- };
+ const t_symbol *sym;
+ int argc;
+ const t_atom *argv;
};
-qmsg::~qmsg()
-{
- Clear();
- if(nxt) delete nxt;
-}
+// _should_ work without locks.... have yet to check if it really does....
+class Queue:
+ public flext
+{
+public:
+ Queue()
+ {
+ qhead = qtail = 0;
+ ahead = atail = 0;
+ }
-void qmsg::Clear()
-{
- if(tp == tp_list) { if(_list.argv) delete[] _list.argv; }
- else if(tp == tp_any) { if(_any.argv) delete[] _any.argv; }
- tp = tp_none;
-}
+ bool Empty() const { return qhead == qtail; }
+
+ int Count() const
+ {
+ int c = qtail-qhead;
+ return c >= 0?c:c+QUEUE_LENGTH;
+ }
+
+ const qmsg &Head() { return lst[qhead]; }
+
+ void Pop()
+ {
+ PopAtoms(Head().Args());
+ qhead = (qhead+1)%QUEUE_LENGTH;
+ }
+
+ void Push(flext_base *th,int o) // bang
+ {
+ Set(th,o,sym_bang,0,NULL);
+ }
+
+ void Push(flext_base *th,int o,float dt)
+ {
+ t_atom *at = GetAtoms(1);
+ SetFloat(*at,dt);
+ Set(th,o,sym_float,1,at);
+ }
+
+ void Push(flext_base *th,int o,int dt)
+ {
+ t_atom *at = GetAtoms(1);
+ SetInt(*at,dt);
+#if FLEXT_SYS == FLEXT_SYS_PD
+ const t_symbol *sym = sym_float;
+#elif FLEXT_SYS == FLEXT_SYS_MAX
+ const t_symbol *sym = sym_int;
+#else
+#error Not implemented!
+#endif
+ Set(th,o,sym,1,at);
+ }
+
+ void Push(flext_base *th,int o,const t_symbol *dt)
+ {
+ t_atom *at = GetAtoms(1);
+ SetSymbol(*at,dt);
+ Set(th,o,sym_symbol,1,at);
+ }
+
+ void Push(flext_base *th,int o,int argc,const t_atom *argv)
+ {
+ t_atom *at = GetAtoms(argc);
+ memcpy(at,argv,argc*sizeof(t_atom));
+ Set(th,o,sym_list,argc,at);
+ }
+
+ void Push(flext_base *th,int o,const t_symbol *sym,int argc,const t_atom *argv)
+ {
+ t_atom *at = GetAtoms(argc);
+ memcpy(at,argv,argc*sizeof(t_atom));
+ Set(th,o,sym,argc,at);
+ }
+
+protected:
+ void Set(flext_base *th,int o,const t_symbol *sym,int argc,const t_atom *argv)
+ {
+ FLEXT_ASSERT(Count() < QUEUE_LENGTH-1);
+ lst[qtail].Set(th,o,sym,argc,argv);
+ qtail = (qtail+1)%QUEUE_LENGTH;
+ }
+
+ int CntAtoms() const
+ {
+ int c = atail-ahead;
+ return c >= 0?c:c+QUEUE_ATOMS;
+ }
+
+ // must return contiguous region
+ t_atom *GetAtoms(int argc)
+ {
+ // \todo check for available space
+
+ if(atail+argc >= QUEUE_ATOMS) {
+ atail = argc;
+ return atoms;
+ }
+ else {
+ t_atom *at = atoms+atail;
+ atail += argc;
+ return at;
+ }
+ }
+
+ void PopAtoms(int argc)
+ {
+ const int p = ahead+argc;
+ ahead = p >= QUEUE_ATOMS?argc:p;
+ }
+
+ int qhead,qtail;
+ qmsg lst[QUEUE_LENGTH];
+ int ahead,atail;
+ t_atom atoms[QUEUE_ATOMS];
+};
+
+static Queue queue;
-static volatile int qcnt = 0;
-static qmsg *volatile qhead = NULL,*volatile qtail = NULL;
#ifdef FLEXT_QTHR
static flext::ThrCond qthrcond;
@@ -75,102 +180,33 @@ static flext::ThrCond qthrcond;
static t_qelem *qclk = NULL;
#endif
-#ifdef FLEXT_THREADS
-static flext::ThrMutex qmutex;
-#endif
#define CHUNK 10
-static void QWork(bool qlock,bool syslock)
+static void QWork(bool syslock)
{
for(;;) {
// Since qcnt can only be increased from any other function than QWork
// qc will be a minimum guaranteed number of present queue elements.
// On the other hand, if new queue elements are added by the methods called
// in the loop, these will be sent in the next tick to avoid recursion overflow.
- int qc = qcnt;
+ int qc = queue.Count();
if(!qc) break;
#ifdef FLEXT_QTHR
if(syslock) sys_lock();
#endif
- for(int i = 0; i < qc && qhead; ++i) {
- #ifdef FLEXT_THREADS
- if(qlock) qmutex.Lock();
- #endif
- qmsg *m = qhead;
- qcnt--;
- qhead = m->nxt;
- if(!qhead) qtail = NULL;
- m->nxt = NULL;
- #ifdef FLEXT_THREADS
- if(qlock) qmutex.Unlock();
- #endif
-
- if(m->out < 0) {
- // message to self
-
- const int n = -1-m->out;
- t_atom tmp;
-
- switch(m->tp) {
- case qmsg::tp_bang:
- m->th->m_methodmain(n,flext::sym_bang,0,&tmp);
- break;
- case qmsg::tp_float:
- flext::SetFloat(tmp,m->_float);
- m->th->m_methodmain(n,flext::sym_float,1,&tmp);
- break;
- case qmsg::tp_int:
- flext::SetInt(tmp,m->_int);
- #if FLEXT_SYS == FLEXT_SYS_PD
- m->th->m_methodmain(n,flext::sym_float,1,&tmp);
- #elif FLEXT_SYS == FLEXT_SYS_MAX
- m->th->m_methodmain(n,flext::sym_int,1,&tmp);
- #else
- #error Not implemented!
- #endif
- case qmsg::tp_sym:
- flext::SetSymbol(tmp,m->_sym);
- m->th->m_methodmain(n,flext::sym_symbol,1,&tmp);
- break;
- case qmsg::tp_list:
- m->th->m_methodmain(n,flext::sym_list,m->_list.argc,m->_list.argv);
- break;
- case qmsg::tp_any:
- m->th->m_methodmain(n,m->_any.s,m->_any.argc,m->_any.argv);
- break;
- #ifdef FLEXT_DEBUG
- default: ERRINTERNAL();
- #endif
- }
- }
- else {
- // message to outlet
-
- switch(m->tp) {
- case qmsg::tp_bang: m->th->ToSysBang(m->out); break;
- case qmsg::tp_float: m->th->ToSysFloat(m->out,m->_float); break;
- case qmsg::tp_int: m->th->ToSysInt(m->out,m->_int); break;
- case qmsg::tp_sym: m->th->ToSysSymbol(m->out,m->_sym); break;
- case qmsg::tp_list: m->th->ToSysList(m->out,m->_list.argc,m->_list.argv); break;
- case qmsg::tp_any: m->th->ToSysAnything(m->out,m->_any.s,m->_any.argc,m->_any.argv); break;
- #ifdef FLEXT_DEBUG
- default: ERRINTERNAL();
- #endif
- }
- }
-
- // delete processed queue element
- delete m;
+ for(int i = 0; i < qc; ++i) {
+ queue.Head().Send();
+ queue.Pop();
} // inner loop
#ifdef FLEXT_QTHR
if(syslock) sys_unlock();
#endif
- } // for(;;)
+ }
}
#if !defined(FLEXT_QTHR)
@@ -181,11 +217,10 @@ static void QTick(fts_object_t *c,int winlet, fts_symbol_t s, int ac, const fts_
static void QTick(flext_base *c)
{
#endif
-// post("qtick");
#ifdef FLEXT_THREADS
FLEXT_ASSERT(flext::IsSystemThread());
#endif
- QWork(true,false);
+ QWork(false);
}
#endif
@@ -201,30 +236,12 @@ void flext_base::QFlush(flext_base *th)
return;
}
#endif
-#ifdef FLEXT_THREADS
- qmutex.Lock();
-#endif
- while(qcnt) QWork(false,false);
-#ifdef FLEXT_THREADS
- qmutex.Unlock();
-#endif
+
+ while(!queue.Empty()) QWork(false);
}
-static void Queue(qmsg *m)
+static void Trigger()
{
-// post("Queue");
-
-#ifdef FLEXT_THREADS
- qmutex.Lock();
-#endif
- if(qtail) qtail->nxt = m;
- else qhead = m;
- qtail = m;
- qcnt++;
-#ifdef FLEXT_THREADS
- qmutex.Unlock();
-#endif
-
#if FLEXT_SYS == FLEXT_SYS_PD
#ifdef FLEXT_QTHR
// wake up a worker thread
@@ -249,7 +266,7 @@ void flext_base::QWorker(thr_params *)
thrmsgid = GetThreadId();
for(;;) {
qthrcond.Wait();
- QWork(true,true);
+ QWork(true);
}
}
#endif
@@ -260,10 +277,6 @@ void flext_base::StartQueue()
if(started) return;
else started = true;
- // message queue ticker
- qhead = qtail = NULL;
- qcnt = 0;
-
#ifdef FLEXT_QTHR
LaunchThread(QWorker,NULL);
#else
@@ -277,86 +290,36 @@ void flext_base::StartQueue()
void flext_base::ToQueueBang(int o) const
{
- FLEXT_ASSERT(o >= 0);
- qmsg *m = new qmsg(const_cast<flext_base *>(this));
- m->SetBang(o);
- Queue(m);
+ queue.Push(const_cast<flext_base *>(this),o);
+ Trigger();
}
void flext_base::ToQueueFloat(int o,float f) const
{
- FLEXT_ASSERT(o >= 0);
- qmsg *m = new qmsg(const_cast<flext_base *>(this));
- m->SetFloat(o,f);
- Queue(m);
+ queue.Push(const_cast<flext_base *>(this),o,f);
+ Trigger();
}
void flext_base::ToQueueInt(int o,int f) const
{
- FLEXT_ASSERT(o >= 0);
- qmsg *m = new qmsg(const_cast<flext_base *>(this));
- m->SetInt(o,f);
- Queue(m);
+ queue.Push(const_cast<flext_base *>(this),o,f);
+ Trigger();
}
void flext_base::ToQueueSymbol(int o,const t_symbol *s) const
{
- FLEXT_ASSERT(o >= 0);
- qmsg *m = new qmsg(const_cast<flext_base *>(this));
- m->SetSymbol(o,s);
- Queue(m);
+ queue.Push(const_cast<flext_base *>(this),o,s);
+ Trigger();
}
void flext_base::ToQueueList(int o,int argc,const t_atom *argv) const
{
- FLEXT_ASSERT(o >= 0);
- qmsg *m = new qmsg(const_cast<flext_base *>(this));
- m->SetList(o,argc,argv);
- Queue(m);
+ queue.Push(const_cast<flext_base *>(this),o,argc,argv);
+ Trigger();
}
void flext_base::ToQueueAnything(int o,const t_symbol *s,int argc,const t_atom *argv) const
{
- FLEXT_ASSERT(o >= 0);
- qmsg *m = new qmsg(const_cast<flext_base *>(this));
- m->SetAny(o,s,argc,argv);
- Queue(m);
-}
-
-
-void flext_base::ToSelfBang(int n) const
-{
- FLEXT_ASSERT(n >= 0);
- ToQueueBang(-1-n);
-}
-
-void flext_base::ToSelfFloat(int n,float f) const
-{
- FLEXT_ASSERT(n >= 0);
- ToQueueFloat(-1-n,f);
-}
-
-void flext_base::ToSelfInt(int n,int f) const
-{
- FLEXT_ASSERT(n >= 0);
- ToQueueInt(-1-n,f);
+ queue.Push(const_cast<flext_base *>(this),o,s,argc,argv);
+ Trigger();
}
-
-void flext_base::ToSelfSymbol(int n,const t_symbol *s) const
-{
- FLEXT_ASSERT(n >= 0);
- ToQueueSymbol(-1-n,s);
-}
-
-void flext_base::ToSelfList(int n,int argc,const t_atom *argv) const
-{
- FLEXT_ASSERT(n >= 0);
- ToQueueList(-1-n,argc,argv);
-}
-
-void flext_base::ToSelfAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const
-{
- FLEXT_ASSERT(n >= 0);
- ToQueueAnything(-1-n,s,argc,argv);
-}
-