diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2006-09-20 14:24:10 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2006-09-20 14:24:10 +0000 |
commit | b1224f91730af6a729f7e7a428eb660a6d734926 (patch) | |
tree | c49a430ed4700743c2851556a10d8685df748b2d /externals/grill/flext/source | |
parent | b6d992055164079e3943dd0e75d8734214a9b280 (diff) |
enabled templates for flext classes, inlined timer functions, some more ToOut/Sys methods
fixed help name definition
added flfeatures.h for compile-time version-specific feature detection
changed eol-style
adapted for pd-devel 0.39
minimal fix for timers
cosmetic changes to calm the compiler
changes for Mac/Intel
svn path=/trunk/; revision=5979
Diffstat (limited to 'externals/grill/flext/source')
-rw-r--r-- | externals/grill/flext/source/flbase.cpp | 9 | ||||
-rw-r--r-- | externals/grill/flext/source/flbase.h | 28 | ||||
-rw-r--r-- | externals/grill/flext/source/flclass.h | 6 | ||||
-rw-r--r-- | externals/grill/flext/source/flcontainers.h | 946 | ||||
-rw-r--r-- | externals/grill/flext/source/fldefs_hdr.h | 8 | ||||
-rw-r--r-- | externals/grill/flext/source/flfeatures.h | 68 | ||||
-rwxr-xr-x | externals/grill/flext/source/fllib.cpp | 41 | ||||
-rw-r--r-- | externals/grill/flext/source/flsupport.h | 27 | ||||
-rwxr-xr-x | externals/grill/flext/source/fltimer.cpp | 52 |
9 files changed, 617 insertions, 568 deletions
diff --git a/externals/grill/flext/source/flbase.cpp b/externals/grill/flext/source/flbase.cpp index a1cc37d3..404588d9 100644 --- a/externals/grill/flext/source/flbase.cpp +++ b/externals/grill/flext/source/flbase.cpp @@ -98,10 +98,11 @@ void flext_obj::DefineHelp(t_classid c,const char *ref,const char *dir,bool addt { #if FLEXT_SYS == FLEXT_SYS_PD char tmp[256]; - if(dir) { - strcpy(tmp,dir); - strcat(tmp,"/"); - strcat(tmp,ref); + if(dir && *dir) { + strcpy(tmp,dir); + char *last = tmp+strlen(tmp)-1; + if(*last != '/') strcat(last,"/"); + strcat(last,ref); } else strcpy(tmp,ref); diff --git a/externals/grill/flext/source/flbase.h b/externals/grill/flext/source/flbase.h index c37036c1..73b1a21a 100644 --- a/externals/grill/flext/source/flbase.h +++ b/externals/grill/flext/source/flbase.h @@ -331,6 +331,34 @@ static void __setup__(t_classid classid) { \ thisType::SETUPFUN(classid); \ } +#define FLEXT_REALHDR_T(NEW_CLASS, PARENT_CLASS) \ +public: \ +typedef NEW_CLASS thisType; \ +typedef PARENT_CLASS thisParent; \ +typedef typename thisParent::t_classid t_classid; \ +static FLEXT_CLASSDEF(flext_obj) *__init__(int argc,t_atom *argv); \ +static void __free__(flext_hdr *hdr) { \ + FLEXT_CLASSDEF(flext_obj) *mydata = hdr->data; delete mydata; \ + hdr->flext_hdr::~flext_hdr(); \ +} \ +static void __setup__(t_classid classid) { thisParent::__setup__(classid); } + + +#define FLEXT_REALHDR_TS(NEW_CLASS, PARENT_CLASS,SETUPFUN) \ +public: \ +typedef NEW_CLASS thisType; \ +typedef PARENT_CLASS thisParent; \ +typedef typename thisParent::t_classid t_classid; \ +static FLEXT_CLASSDEF(flext_obj) *__init__(int argc,t_atom *argv); \ +static void __free__(flext_hdr *hdr) { \ + FLEXT_CLASSDEF(flext_obj) *mydata = hdr->data; delete mydata; \ + hdr->flext_hdr::~flext_hdr(); \ +} \ +static void __setup__(t_classid classid) { \ + thisParent::__setup__(classid); \ + thisType::SETUPFUN(classid); \ +} + // generate name of dsp/non-dsp setup function #if FLEXT_SYS == FLEXT_SYS_PD || FLEXT_SYS == FLEXT_SYS_MAX diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h index 4356ee8f..cbaa5b1b 100644 --- a/externals/grill/flext/source/flclass.h +++ b/externals/grill/flext/source/flclass.h @@ -226,6 +226,8 @@ public: void ToOutAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const; //! Output anything (index n starts with 0) void ToOutAnything(int n,const AtomAnything &any) const { ToOutAnything(n,any.Header(),any.Count(),any.Atoms()); } + //! Output anything (index n starts with 0) + void ToOutAnything(int n,const t_symbol *s,const AtomList &list) const { ToOutAnything(n,s,list.Count(),list.Atoms()); } //! @} FLEXT_C_IO_OUT @@ -828,8 +830,12 @@ protected: void ToSysFloat(int n,float f) const { outlet *o = GetOut(n); if(o) { CRITON(); outlet_float((t_outlet *)o,f); CRITOFF(); } } void ToSysInt(int n,int f) const { outlet *o = GetOut(n); if(o) { CRITON(); outlet_flint((t_outlet *)o,f); CRITOFF(); } } void ToSysSymbol(int n,const t_symbol *s) const { outlet *o = GetOut(n); if(o) { CRITON(); outlet_symbol((t_outlet *)o,const_cast<t_symbol *>(s)); CRITOFF(); } } + void ToSysString(int n,const char *s) const { ToSysSymbol(n,MakeSymbol(s)); } void ToSysList(int n,int argc,const t_atom *argv) const { outlet *o = GetOut(n); if(o) { CRITON(); outlet_list((t_outlet *)o,const_cast<t_symbol *>(sym_list),argc,(t_atom *)argv); CRITOFF(); } } + void ToSysList(int n,const AtomList &list) const { ToSysList(n,list.Count(),list.Atoms()); } void ToSysAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const { outlet *o = GetOut(n); if(o) { CRITON(); outlet_anything((t_outlet *)o,const_cast<t_symbol *>(s),argc,(t_atom *)argv); CRITOFF(); } } + void ToSysAnything(int n,const AtomAnything &any) const { ToSysAnything(n,any.Header(),any.Count(),any.Atoms()); } + void ToSysAnything(int n,const t_symbol *s,const AtomList &list) const { ToSysAnything(n,s,list.Count(),list.Atoms()); } void ToSysBool(int n,bool f) const { ToSysInt(n,f?1:0); } void ToSysAtom(int n,const t_atom &at) const; diff --git a/externals/grill/flext/source/flcontainers.h b/externals/grill/flext/source/flcontainers.h index 43ea03ed..2b33c4e5 100644 --- a/externals/grill/flext/source/flcontainers.h +++ b/externals/grill/flext/source/flcontainers.h @@ -1,473 +1,473 @@ -/*
-
-flext - C++ layer for Max/MSP and pd (pure data) externals
-
-Copyright (c) 2001-2006 Thomas Grill (gr@grrrr.org)
-For information on usage and redistribution, and for a DISCLAIMER OF ALL
-WARRANTIES, see the file, "license.txt," in this distribution.
-
-*/
-
-/*! \file flcontainers.h
- \brief Lock-free container classes
-
- This code has been adapted from the MidiShare project (c)Grame
- http://midishare.sourceforge.net
-*/
-
-#ifndef __FLCONTAINERS_H
-#define __FLCONTAINERS_H
-
-
-#include "flprefix.h"
-
-
-// define that precautiously...
-// it's faster without that but we can't really know...
-#define __SMP__
-
-
-class FLEXT_SHARE Lifo
-{
-public:
- class Cell
- {
- friend class Lifo;
- friend class Fifo;
- private:
- Cell *link;
- };
-
- inline Lifo() { Init(); }
-
- inline void Init() { ic = oc = 0; top = NULL; }
-
- inline Cell *Avail() { return (Cell *)top; }
-
-#if defined(_MSC_VER) && FLEXT_CPU == FLEXT_CPU_IA32
- #ifdef __SMP__
- #define LOCK lock
- #else
- #define LOCK
- #endif
-
- inline void Push(Cell *cell)
- {
- __asm
- {
- push eax
- push ebx
- push ecx
- push edx
- push esi
- mov esi, this
- mov eax, dword ptr [esi]
- mov ecx, cell
- mov edx, dword ptr [esi+4]
- _loop:
- mov ebx, eax
- inc ebx
- mov [ecx], edx
- LOCK cmpxchg8b qword ptr [esi]
- jnz _loop
- pop esi
- pop edx
- pop ecx
- pop ebx
- pop eax
- }
- }
-
- inline Cell *Pop()
- {
- __asm
- {
- push ebx
- push ecx
- push edx
- push esi
- mov esi, this
- add esi, 4 /* point to top */
- mov edx, dword ptr [esi+4]
- mov eax, dword ptr [esi]
- test eax, eax
- jz _end
- _loop:
- mov ebx, dword ptr [eax]
- mov ecx, edx
- inc ecx
- LOCK cmpxchg8b qword ptr [esi]
- jz _end
- test eax, eax
- jnz _loop
- _end:
- pop esi
- pop edx
- pop ecx
- pop ebx
- }
- }
-
- inline size_t Size() const { return ic-oc; }
-#elif defined(__GNUC__) && FLEXT_CPU == FLEXT_CPU_IA32
- #ifndef SMPLOCK
- # ifdef __SMP__
- # define SMPLOCK "lock ; "
- # else
- # define SMPLOCK ""
- # endif
- #endif
-
- inline void Push(Cell *cl)
- {
- __asm__ __volatile__ (
- "# LFPUSH \n\t"
- "pushl %%ebx \n\t"
- "pushl %%ecx \n\t"
- "movl 0(%%esi), %%eax \n\t"
- "movl 4(%%esi), %%edx \n"
- "1: \t"
- "movl %%eax, %%ebx \n\t"
- "incl %%ebx \n\t"
- "movl %%edx, (%%ecx) \n\t"
- SMPLOCK "cmpxchg8b (%%esi) \n\t"
- "jnz 1b \n\t"
- "popl %%ecx \n\t"
- "popl %%ebx \n\t"
- :/* no output */
- :"S" (this), "c" (cl)
- :"memory", "eax", "edx");
- }
-
- inline Cell *Pop()
- {
- Cell *v=0;
- __asm__ __volatile__ (
- "# LFPOP \n\t"
- "pushl %%ebx \n\t"
- "pushl %%ecx \n\t"
- "movl 4(%%esi), %%edx \n\t"
- "movl (%%esi), %%eax \n\t"
- "testl %%eax, %%eax \n\t"
- "jz 2f \n"
- "1: \t"
- "movl (%%eax), %%ebx \n\t"
- "movl %%edx, %%ecx \n\t"
- "incl %%ecx \n\t"
- SMPLOCK "cmpxchg8b (%%esi) \n\t"
- "jz 2f \n\t"
- "testl %%eax, %%eax \n\t"
- "jnz 1b \n"
- "2: \t"
- "popl %%ecx \n\t"
- "popl %%ebx \n\t"
- :"=a" (v)
- :"S" (&this->top)
- :"memory", "edx");
- return v;
- }
-
- inline size_t Size() const
- {
- size_t n;
- __asm__ __volatile__ (
- "# LFSIZE \n\t"
- "movl 8(%%esi), %%edx \n\t"
- "movl (%%esi), %%eax \n\t"
- "subl %%edx, %%eax \n\t"
- :"=a" (n)
- :"S" (this)
- :"memory", "edx");
- return n;
- }
-#elif 0 //defined(__GNUC__) && FLEXT_CPU == FLEXT_CPU_X86_64
-/* attention - this only works for EMT64 or newer revisions of AMD 64-bit cpus */
- #ifndef SMPLOCK
- # ifdef __SMP__
- # define SMPLOCK "lock ; "
- # else
- # define SMPLOCK ""
- # endif
- #endif
-
- inline void Push(Cell *cl)
- {
- __asm__ __volatile__ (
- "# LFPUSH \n\t"
- "push %%rbx \n\t"
- "push %%rcx \n\t"
- "mov 0(%%rsi), %%rax \n\t"
- "mov 8(%%rsi), %%rdx \n"
- "1: \t"
- "mov %%rax, %%rbx \n\t"
- "inc %%rbx \n\t"
- "mov %%rdx, (%%rcx) \n\t"
- SMPLOCK "cmpxchg16b (%%rsi) \n\t"
- "jnz 1b \n\t"
- "pop %%rcx \n\t"
- "pop %%rbx \n\t"
- :/* no output */
- :"S" (this), "c" (cl)
- :"memory", "rax", "rdx");
- }
-
- inline Cell *Pop()
- {
- Cell *v=0;
- __asm__ __volatile__ (
- "# LFPOP \n\t"
- "push %%rbx \n\t"
- "push %%rcx \n\t"
- "mov 8(%%rsi), %%rdx \n\t"
- "mov (%%rsi), %%rax \n\t"
- "test %%rax, %%rax \n\t"
- "jz 2f \n"
- "1: \t"
- "mov (%%rax), %%rbx \n\t"
- "mov %%rdx, %%rcx \n\t"
- "inc %%rcx \n\t"
- SMPLOCK "cmpxchg16b (%%rsi) \n\t"
- "jz 2f \n\t"
- "test %%rax, %%rax \n\t"
- "jnz 1b \n"
- "2: \t"
- "pop %%rcx \n\t"
- "pop %%rbx \n\t"
- :"=a" (v)
- :"S" (&this->top)
- :"memory", "rdx");
- return v;
- }
-
- inline size_t Size() const
- {
- size_t n;
- __asm__ __volatile__ (
- "# LFSIZE \n\t"
- "mov 16(%%rsi), %%rdx \n\t"
- "mov (%%rsi), %%rax \n\t"
- "sub %%rdx, %%rax \n\t"
- :"=a" (n)
- :"S" (this)
- :"memory", "rdx");
- return n;
- }
-
-#elif defined(__GNUC__) && FLEXT_CPU == FLEXT_CPU_PPC
- inline void Push(register Cell *cl)
- {
- register volatile long t1;
- register long t2=0;
- asm volatile (
- "# LFPUSH \n"
- "0: \n"
- " lwarx %0, %3, %1 \n"
- " stw %0, 0(%2) \n"
- " sync \n"
- " stwcx. %2, %3, %1 \n"
- " bne- 0b \n"
- "0: \n"
- " lwarx %0, %3, %4 \n"
- " addi %0, %0, 1 \n"
- " sync \n"
- " stwcx. %0, %3, %4 \n"
- " bne- 0b \n"
- : "=r" (t1)
- : "r" (&this->top), "r" (cl), "r" (t2), "r" (&this->oc), "0" (t1)
- : "r0" /* prevents using r0 because of the ambiguity of 'addi' coding: */
- /* gcc version 2.95.3 20010315 (release - Linux-Mandrake 8.0 for PPC) */
- /* compiles the instruction "addi 0, 0, n" as li 0, n */
- );
- }
-
- inline Cell *Pop()
- {
- register Cell *result;
- register volatile long a, b;
- register long c=0;
- asm volatile (
- "# LFPOP \n"
- "0: \n"
- " lwarx %4, %1, %2 \n" /* creates a reservation on lf */
- " cmpwi %4, 0 \n" /* test if the lifo is empty */
- " beq- 1f \n"
- " lwz %5, 0(%4) \n" /* next cell in b */
- " sync \n" /* synchronize instructions */
- " stwcx. %5, %1, %2 \n" /* if the reservation is not altered */
- /* modify lifo top */
- " bne- 0b \n" /* otherwise: loop and try again */
- "0: \n"
- " lwarx %5, %1, %3 \n" /* creates a reservation on lf->count */
- " addi %5, %5, -1 \n" /* dec count */
- " sync \n" /* synchronize instructions */
- " stwcx. %5, %1, %3 \n" /* conditionnal store */
- " bne- 0b \n"
- "1: \n"
- " mr %0, %4 \n"
- :"=r" (result), "=r" (c)
- : "r" (&this->top), "r" (&this->oc), "r" (a), "r" (b), "1" (c)
- : "r0" /* prevents using r0 because of the ambiguity of 'addi' coding: */
- /* gcc version 2.95.3 20010315 (release - Linux-Mandrake 8.0 for PPC) */
- /* compiles the instruction "addi 0, 0, n" as li 0, n */
- );
- return result;
- }
-
- inline size_t Size() const { return oc; }
-
-#else
- // no lock free code available for this compiler/platform
-
- inline void Push(Cell *c)
- {
-#ifdef FLEXT_THREADS
- mutex.Lock();
-#endif
- c->link = (Cell *)top;
- top = c;
- ++oc;
-#ifdef FLEXT_THREADS
- mutex.Unlock();
-#endif
- }
-
- inline Cell *Pop()
- {
- if(top) {
- Cell *r;
-#ifdef FLEXT_THREADS
- mutex.Lock();
-#endif
- r = (Cell *)top;
- top = r->link;
- --oc;
-#ifdef FLEXT_THREADS
- mutex.Unlock();
-#endif
- return r;
- }
- else
- return NULL;
- }
-
- inline size_t Size() const { return oc; }
-
-private:
-#ifdef FLEXT_THREADS
- flext::ThrMutex mutex;
-#endif
-
-#endif
-
-private:
- // don't change order!
- volatile size_t ic; // input (push) count
- volatile Cell *top; // top of the stack
- volatile size_t oc; // output (pop) count
-#ifdef __POWERPC__
- size_t unused[5]; // lifo size must be at least 32 bytes
- // to avoid livelock in multiprocessor
-#endif
-};
-
-template <typename T>
-class TypedLifo
- : public Lifo
-{
-public:
- inline T *Avail() { return static_cast<T *>(Lifo::Avail()); }
- inline void Push(T *c) { Lifo::Push(static_cast<T *>(c)); }
- inline T *Pop() { return static_cast<T *>(Lifo::Pop()); }
-};
-
-template <typename T,int M = 2,int O = 1>
-class PooledLifo
- : public TypedLifo<T>
-{
-public:
- inline T *New() { T *n = reuse.Pop(); return n?n:new T; }
- inline size_t Size() const { return TypedLifo<T>::Size(); }
- inline void Free(T *p) { if(reuse.Size() < Size()*M+O) reuse.Push(p); else delete p; }
-private:
- TypedLifo<T> reuse;
-};
-
-
-class FLEXT_SHARE Fifo
-{
-public:
- typedef Lifo::Cell Cell;
-
- void Init() { in.Init(); out.Init(); }
-
- inline size_t Size() const { return in.Size()+out.Size(); }
-
- inline void Put(Cell *cl) { in.Push(cl); }
-
- Cell *Get()
- {
- Cell *v1 = out.Pop();
- if(!v1) {
- v1 = in.Pop();
- if(v1)
- for(Cell *v2; (v2 = in.Pop()) != NULL; v1 = v2)
- out.Push(v1);
- }
- return v1;
- }
-
- Cell *Avail()
- {
- Cell *v1 = out.Avail();
- if(v1)
- return v1;
- else {
- for(Cell *v2; (v2 = in.Pop()) != NULL; )
- out.Push(v2);
- return out.Avail();
- }
- }
-
- Cell *Clear()
- {
- Cell *first = Get();
- if(!first) return NULL;
-
- Cell *next,*cur = first;
- while((next = Get()) != NULL) {
- cur->link = next;
- cur = next;
- }
- cur->link = NULL;
-
- Init();
- return first;
- }
-
- Lifo in,out;
-};
-
-template <typename T>
-class TypedFifo
- : public Fifo
-{
-public:
- inline T *Avail() { return static_cast<T *>(Fifo::Avail()); }
- inline void Put(T *c) { Fifo::Put(static_cast<T *>(c)); }
- inline T *Get() { return static_cast<T *>(Fifo::Get()); }
- inline T *Clear() { return static_cast<T *>(Fifo::Clear()); }
-};
-
-template <typename T,int M = 2,int O = 1>
-class PooledFifo
- : public TypedFifo<T>
-{
-public:
- inline T *New() { T *n = reuse.Pop(); return n?n:new T; }
- inline size_t Size() const { return TypedFifo<T>::Size(); }
- inline void Free(T *p) { if(reuse.Size() < Size()*M+O) reuse.Push(p); else delete p; }
-private:
- TypedLifo<T> reuse;
-};
-
-#endif
+/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001-2006 Thomas Grill (gr@grrrr.org) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flcontainers.h + \brief Lock-free container classes + + This code has been adapted from the MidiShare project (c)Grame + http://midishare.sourceforge.net +*/ + +#ifndef __FLCONTAINERS_H +#define __FLCONTAINERS_H + + +#include "flprefix.h" + + +// define that precautiously... +// it's faster without that but we can't really know... +#define __SMP__ + + +class FLEXT_SHARE Lifo +{ +public: + class Cell + { + friend class Lifo; + friend class Fifo; + private: + Cell *link; + }; + + inline Lifo() { Init(); } + + inline void Init() { ic = oc = 0; top = NULL; } + + inline Cell *Avail() { return (Cell *)top; } + +#if defined(_MSC_VER) && FLEXT_CPU == FLEXT_CPU_IA32 + #ifdef __SMP__ + #define LOCK lock + #else + #define LOCK + #endif + + inline void Push(Cell *cell) + { + __asm + { + push eax + push ebx + push ecx + push edx + push esi + mov esi, this + mov eax, dword ptr [esi] + mov ecx, cell + mov edx, dword ptr [esi+4] + _loop: + mov ebx, eax + inc ebx + mov [ecx], edx + LOCK cmpxchg8b qword ptr [esi] + jnz _loop + pop esi + pop edx + pop ecx + pop ebx + pop eax + } + } + + inline Cell *Pop() + { + __asm + { + push ebx + push ecx + push edx + push esi + mov esi, this + add esi, 4 /* point to top */ + mov edx, dword ptr [esi+4] + mov eax, dword ptr [esi] + test eax, eax + jz _end + _loop: + mov ebx, dword ptr [eax] + mov ecx, edx + inc ecx + LOCK cmpxchg8b qword ptr [esi] + jz _end + test eax, eax + jnz _loop + _end: + pop esi + pop edx + pop ecx + pop ebx + } + } + + inline size_t Size() const { return ic-oc; } +#elif defined(__GNUC__) && FLEXT_CPU == FLEXT_CPU_IA32 + #ifndef SMPLOCK + # ifdef __SMP__ + # define SMPLOCK "lock ; " + # else + # define SMPLOCK "" + # endif + #endif + + inline void Push(Cell *cl) + { + __asm__ __volatile__ ( + "# LFPUSH \n\t" + "pushl %%ebx \n\t" + "pushl %%ecx \n\t" + "movl 0(%%esi), %%eax \n\t" + "movl 4(%%esi), %%edx \n" + "1: \t" + "movl %%eax, %%ebx \n\t" + "incl %%ebx \n\t" + "movl %%edx, (%%ecx) \n\t" + SMPLOCK "cmpxchg8b (%%esi) \n\t" + "jnz 1b \n\t" + "popl %%ecx \n\t" + "popl %%ebx \n\t" + :/* no output */ + :"S" (this), "c" (cl) + :"memory", "eax", "edx"); + } + + inline Cell *Pop() + { + Cell *v=0; + __asm__ __volatile__ ( + "# LFPOP \n\t" + "pushl %%ebx \n\t" + "pushl %%ecx \n\t" + "movl 4(%%esi), %%edx \n\t" + "movl (%%esi), %%eax \n\t" + "testl %%eax, %%eax \n\t" + "jz 2f \n" + "1: \t" + "movl (%%eax), %%ebx \n\t" + "movl %%edx, %%ecx \n\t" + "incl %%ecx \n\t" + SMPLOCK "cmpxchg8b (%%esi) \n\t" + "jz 2f \n\t" + "testl %%eax, %%eax \n\t" + "jnz 1b \n" + "2: \t" + "popl %%ecx \n\t" + "popl %%ebx \n\t" + :"=a" (v) + :"S" (&this->top) + :"memory", "edx"); + return v; + } + + inline size_t Size() const + { + size_t n; + __asm__ __volatile__ ( + "# LFSIZE \n\t" + "movl 8(%%esi), %%edx \n\t" + "movl (%%esi), %%eax \n\t" + "subl %%edx, %%eax \n\t" + :"=a" (n) + :"S" (this) + :"memory", "edx"); + return n; + } +#elif 0 //defined(__GNUC__) && FLEXT_CPU == FLEXT_CPU_X86_64 +/* attention - this only works for EMT64 or newer revisions of AMD 64-bit cpus */ + #ifndef SMPLOCK + # ifdef __SMP__ + # define SMPLOCK "lock ; " + # else + # define SMPLOCK "" + # endif + #endif + + inline void Push(Cell *cl) + { + __asm__ __volatile__ ( + "# LFPUSH \n\t" + "push %%rbx \n\t" + "push %%rcx \n\t" + "mov 0(%%rsi), %%rax \n\t" + "mov 8(%%rsi), %%rdx \n" + "1: \t" + "mov %%rax, %%rbx \n\t" + "inc %%rbx \n\t" + "mov %%rdx, (%%rcx) \n\t" + SMPLOCK "cmpxchg16b (%%rsi) \n\t" + "jnz 1b \n\t" + "pop %%rcx \n\t" + "pop %%rbx \n\t" + :/* no output */ + :"S" (this), "c" (cl) + :"memory", "rax", "rdx"); + } + + inline Cell *Pop() + { + Cell *v=0; + __asm__ __volatile__ ( + "# LFPOP \n\t" + "push %%rbx \n\t" + "push %%rcx \n\t" + "mov 8(%%rsi), %%rdx \n\t" + "mov (%%rsi), %%rax \n\t" + "test %%rax, %%rax \n\t" + "jz 2f \n" + "1: \t" + "mov (%%rax), %%rbx \n\t" + "mov %%rdx, %%rcx \n\t" + "inc %%rcx \n\t" + SMPLOCK "cmpxchg16b (%%rsi) \n\t" + "jz 2f \n\t" + "test %%rax, %%rax \n\t" + "jnz 1b \n" + "2: \t" + "pop %%rcx \n\t" + "pop %%rbx \n\t" + :"=a" (v) + :"S" (&this->top) + :"memory", "rdx"); + return v; + } + + inline size_t Size() const + { + size_t n; + __asm__ __volatile__ ( + "# LFSIZE \n\t" + "mov 16(%%rsi), %%rdx \n\t" + "mov (%%rsi), %%rax \n\t" + "sub %%rdx, %%rax \n\t" + :"=a" (n) + :"S" (this) + :"memory", "rdx"); + return n; + } + +#elif defined(__GNUC__) && FLEXT_CPU == FLEXT_CPU_PPC + inline void Push(register Cell *cl) + { + register volatile long t1; + register long t2=0; + asm volatile ( + "# LFPUSH \n" + "0: \n" + " lwarx %0, %3, %1 \n" + " stw %0, 0(%2) \n" + " sync \n" + " stwcx. %2, %3, %1 \n" + " bne- 0b \n" + "0: \n" + " lwarx %0, %3, %4 \n" + " addi %0, %0, 1 \n" + " sync \n" + " stwcx. %0, %3, %4 \n" + " bne- 0b \n" + : "=r" (t1) + : "r" (&this->top), "r" (cl), "r" (t2), "r" (&this->oc), "0" (t1) + : "r0" /* prevents using r0 because of the ambiguity of 'addi' coding: */ + /* gcc version 2.95.3 20010315 (release - Linux-Mandrake 8.0 for PPC) */ + /* compiles the instruction "addi 0, 0, n" as li 0, n */ + ); + } + + inline Cell *Pop() + { + register Cell *result; + register volatile long a, b; + register long c=0; + asm volatile ( + "# LFPOP \n" + "0: \n" + " lwarx %4, %1, %2 \n" /* creates a reservation on lf */ + " cmpwi %4, 0 \n" /* test if the lifo is empty */ + " beq- 1f \n" + " lwz %5, 0(%4) \n" /* next cell in b */ + " sync \n" /* synchronize instructions */ + " stwcx. %5, %1, %2 \n" /* if the reservation is not altered */ + /* modify lifo top */ + " bne- 0b \n" /* otherwise: loop and try again */ + "0: \n" + " lwarx %5, %1, %3 \n" /* creates a reservation on lf->count */ + " addi %5, %5, -1 \n" /* dec count */ + " sync \n" /* synchronize instructions */ + " stwcx. %5, %1, %3 \n" /* conditionnal store */ + " bne- 0b \n" + "1: \n" + " mr %0, %4 \n" + :"=r" (result), "=r" (c) + : "r" (&this->top), "r" (&this->oc), "r" (a), "r" (b), "1" (c) + : "r0" /* prevents using r0 because of the ambiguity of 'addi' coding: */ + /* gcc version 2.95.3 20010315 (release - Linux-Mandrake 8.0 for PPC) */ + /* compiles the instruction "addi 0, 0, n" as li 0, n */ + ); + return result; + } + + inline size_t Size() const { return oc; } + +#else + // no lock free code available for this compiler/platform + + inline void Push(Cell *c) + { +#ifdef FLEXT_THREADS + mutex.Lock(); +#endif + c->link = (Cell *)top; + top = c; + ++oc; +#ifdef FLEXT_THREADS + mutex.Unlock(); +#endif + } + + inline Cell *Pop() + { + if(top) { + Cell *r; +#ifdef FLEXT_THREADS + mutex.Lock(); +#endif + r = (Cell *)top; + top = r->link; + --oc; +#ifdef FLEXT_THREADS + mutex.Unlock(); +#endif + return r; + } + else + return NULL; + } + + inline size_t Size() const { return oc; } + +private: +#ifdef FLEXT_THREADS + flext::ThrMutex mutex; +#endif + +#endif + +private: + // don't change order! + volatile size_t ic; // input (push) count + volatile Cell *top; // top of the stack + volatile size_t oc; // output (pop) count +#ifdef __POWERPC__ + size_t unused[5]; // lifo size must be at least 32 bytes + // to avoid livelock in multiprocessor +#endif +}; + +template <typename T> +class TypedLifo + : public Lifo +{ +public: + inline T *Avail() { return static_cast<T *>(Lifo::Avail()); } + inline void Push(T *c) { Lifo::Push(static_cast<T *>(c)); } + inline T *Pop() { return static_cast<T *>(Lifo::Pop()); } +}; + +template <typename T,int M = 2,int O = 1> +class PooledLifo + : public TypedLifo<T> +{ +public: + inline T *New() { T *n = reuse.Pop(); return n?n:new T; } + inline size_t Size() const { return TypedLifo<T>::Size(); } + inline void Free(T *p) { if(reuse.Size() < Size()*M+O) reuse.Push(p); else delete p; } +private: + TypedLifo<T> reuse; +}; + + +class FLEXT_SHARE Fifo +{ +public: + typedef Lifo::Cell Cell; + + void Init() { in.Init(); out.Init(); } + + inline size_t Size() const { return in.Size()+out.Size(); } + + inline void Put(Cell *cl) { in.Push(cl); } + + Cell *Get() + { + Cell *v1 = out.Pop(); + if(!v1) { + v1 = in.Pop(); + if(v1) + for(Cell *v2; (v2 = in.Pop()) != NULL; v1 = v2) + out.Push(v1); + } + return v1; + } + + Cell *Avail() + { + Cell *v1 = out.Avail(); + if(v1) + return v1; + else { + for(Cell *v2; (v2 = in.Pop()) != NULL; ) + out.Push(v2); + return out.Avail(); + } + } + + Cell *Clear() + { + Cell *first = Get(); + if(!first) return NULL; + + Cell *next,*cur = first; + while((next = Get()) != NULL) { + cur->link = next; + cur = next; + } + cur->link = NULL; + + Init(); + return first; + } + + Lifo in,out; +}; + +template <typename T> +class TypedFifo + : public Fifo +{ +public: + inline T *Avail() { return static_cast<T *>(Fifo::Avail()); } + inline void Put(T *c) { Fifo::Put(static_cast<T *>(c)); } + inline T *Get() { return static_cast<T *>(Fifo::Get()); } + inline T *Clear() { return static_cast<T *>(Fifo::Clear()); } +}; + +template <typename T,int M = 2,int O = 1> +class PooledFifo + : public TypedFifo<T> +{ +public: + inline T *New() { T *n = reuse.Pop(); return n?n:new T; } + inline size_t Size() const { return TypedFifo<T>::Size(); } + inline void Free(T *p) { if(reuse.Size() < Size()*M+O) reuse.Push(p); else delete p; } +private: + TypedLifo<T> reuse; +}; + +#endif diff --git a/externals/grill/flext/source/fldefs_hdr.h b/externals/grill/flext/source/fldefs_hdr.h index 12b17c79..01bcd477 100644 --- a/externals/grill/flext/source/fldefs_hdr.h +++ b/externals/grill/flext/source/fldefs_hdr.h @@ -32,6 +32,10 @@ WARRANTIES, see the file, "license.txt," in this distribution. \ FLEXT_REALHDR(NEW_CLASS, PARENT_CLASS) +#define FLEXT_HEADER_T(NEW_CLASS,PARENT_CLASS) \ +\ +FLEXT_REALHDR_T(NEW_CLASS, PARENT_CLASS) + /*! \brief Flext class header with setup function \param NEW_CLASS name of the current C++ class \param PARENT_CLASS name of the base C++ class (e.g. flext_base or flext_dsp) @@ -46,6 +50,10 @@ FLEXT_REALHDR(NEW_CLASS, PARENT_CLASS) \ FLEXT_REALHDR_S(NEW_CLASS, PARENT_CLASS, SETUPFUN) +#define FLEXT_HEADER_TS(NEW_CLASS, PARENT_CLASS, SETUPFUN)\ +\ +FLEXT_REALHDR_TS(NEW_CLASS, PARENT_CLASS, SETUPFUN) + //! @} FLEXT_D_HEADER diff --git a/externals/grill/flext/source/flfeatures.h b/externals/grill/flext/source/flfeatures.h index 915f44a9..efb198d0 100644 --- a/externals/grill/flext/source/flfeatures.h +++ b/externals/grill/flext/source/flfeatures.h @@ -1,34 +1,34 @@ -/*
-
-flext - C++ layer for Max/MSP and pd (pure data) externals
-
-Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org)
-For information on usage and redistribution, and for a DISCLAIMER OF ALL
-WARRANTIES, see the file, "license.txt," in this distribution.
-
-*/
-
-/*! \file flfeatures.h
- \brief Detect version-specific features.
-*/
-
-#ifndef __FLFEATURES_H
-#define __FLFEATURES_H
-
-// check if PD API supports buffer dirty time
-#if defined(PD_DEVEL_VERSION) && defined(PD_MAJOR_VERSION) && defined(PD_MINOR_VERSION)
-#if PD_MINOR_VERSION >= 36 && PD_MINOR_VERSION <= 38
-// array locks have been removed in devel_0_39
- #define _FLEXT_HAVE_PD_GARRAYLOCKS
-#endif
-#if PD_MINOR_VERSION >= 36
- #define _FLEXT_HAVE_PD_GARRAYUPDATETIME
-#endif
-#endif
-
-#if defined(MAC_VERSION) || defined(WIN_VERSION)
- // not for OS9
- #define _FLEXT_HAVE_MAX_INUSEFLAG
-#endif
-
-#endif
+/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flfeatures.h + \brief Detect version-specific features. +*/ + +#ifndef __FLFEATURES_H +#define __FLFEATURES_H + +// check if PD API supports buffer dirty time +#if defined(PD_DEVEL_VERSION) && defined(PD_MAJOR_VERSION) && defined(PD_MINOR_VERSION) +#if PD_MINOR_VERSION >= 36 && PD_MINOR_VERSION <= 38 +// array locks have been removed in devel_0_39 + #define _FLEXT_HAVE_PD_GARRAYLOCKS +#endif +#if PD_MINOR_VERSION >= 36 + #define _FLEXT_HAVE_PD_GARRAYUPDATETIME +#endif +#endif + +#if defined(MAC_VERSION) || defined(WIN_VERSION) + // not for OS9 + #define _FLEXT_HAVE_MAX_INUSEFLAG +#endif + +#endif diff --git a/externals/grill/flext/source/fllib.cpp b/externals/grill/flext/source/fllib.cpp index ff70da2f..a7b98335 100755 --- a/externals/grill/flext/source/fllib.cpp +++ b/externals/grill/flext/source/fllib.cpp @@ -41,27 +41,31 @@ WARRANTIES, see the file, "license.txt," in this distribution. //! Extract space-delimited words from a string static const char *extract(const char *name,int ix = 0) { - static char tmp[1024]; + char tmp[1024]; const char *n = name; const char *del = strchr(name,ALIASDEL); if(del) { - if(ix < 0) { - char *t = tmp; - while(n < del && (isspace(*n) || strchr(ALIASSLASHES,*n))) ++n; - while(n < del && !isspace(*n)) { - char c = *(n++); - *(t++) = strchr(ALIASSLASHES,c)?ALIASSLASH:c; - } - while(*t == ALIASSLASH && t > tmp) --t; - *t = 0; - - return tmp; +#if 0 + char *t = tmp; + while(n < del && (isspace(*n) || strchr(ALIASSLASHES,*n))) ++n; + while(n < del && !isspace(*n)) { + char c = *(n++); + *(t++) = strchr(ALIASSLASHES,c)?ALIASSLASH:c; } + while(*t == ALIASSLASH && t > tmp) --t; + *t = 0; +#endif + if(ix < 0) + return del+1; - n = del+1; + strncpy(tmp,name,del-name); + tmp[del-name] = 0; + n = tmp; } + else if(ix < 0) + return NULL; // no explicit help name while(*n && isspace(*n)) ++n; @@ -301,7 +305,16 @@ void flext_obj::obj_add(bool lib,bool dsp,bool attr,const char *idname,const cha t_classid clid = lo; // make help reference - flext_obj::DefineHelp(clid,idname,extract(names,-1),dsp); + const char *helptxt = extract(names,-1); + if(helptxt) { + const char *sl = strchr(helptxt,'/'); + if(sl && !sl[1]) + // helptxt is only the path (path with trailing /) + flext_obj::DefineHelp(clid,idname,helptxt,dsp); + else + // helptxt is path and patch name + flext_obj::DefineHelp(clid,helptxt,NULL,dsp); + } for(int ix = 0; ; ++ix) { // in this loop register all the possible aliases of the object diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h index dcc0acc2..f26437df 100644 --- a/externals/grill/flext/source/flsupport.h +++ b/externals/grill/flext/source/flsupport.h @@ -1124,16 +1124,37 @@ public: \remark Since this clock can be synchronized to an external clock (or e.g. the audio card) \remark it may differ from the clock of the operating system */ + /*! \brief Get time since real-time system startup. \note This is not the time of the operating system but of the real-time system. - \note It depends on the time source the system is synchronized to. + \note It may depend on the time source the system is synchronized to (e.g. audio sample rate). */ - static double GetTime(); + static double GetTime() + { + #if FLEXT_SYS == FLEXT_SYS_PD + return clock_gettimesince(0)*0.001; + #elif FLEXT_SYS == FLEXT_SYS_MAX + double tm; + clock_getftime(&tm); + return tm*0.001; + #else + #error Not implemented + #endif + } /*! \brief Get time granularity of the GetTime function. \note This can be zero if not determined. */ - static double GetTimeGrain(); + static double GetTimeGrain() + { + #if FLEXT_SYS == FLEXT_SYS_PD + return 0; + #elif FLEXT_SYS == FLEXT_SYS_MAX + return 0.001; + #else + #error Not implemented + #endif + } /*! \brief Get operating system time since flext startup. */ diff --git a/externals/grill/flext/source/fltimer.cpp b/externals/grill/flext/source/fltimer.cpp index d9bf3cc1..6f13999f 100755 --- a/externals/grill/flext/source/fltimer.cpp +++ b/externals/grill/flext/source/fltimer.cpp @@ -25,31 +25,6 @@ WARRANTIES, see the file, "license.txt," in this distribution. #endif - -double flext::GetTime() -{ -#if FLEXT_SYS == FLEXT_SYS_PD - return clock_gettimesince(0)*0.001; -#elif FLEXT_SYS == FLEXT_SYS_MAX - double tm; - clock_getftime(&tm); - return tm*0.001; -#else - #error Not implemented -#endif -} - -double flext::GetTimeGrain() -{ -#if FLEXT_SYS == FLEXT_SYS_PD - return 0; -#elif FLEXT_SYS == FLEXT_SYS_MAX - return 0.001; -#else - #error Not implemented -#endif -} - #if FLEXT_OS == FLEXT_OS_WIN static double perffrq = 0; #endif @@ -246,9 +221,9 @@ bool flext::Timer::Delay(double tm,void *data) bool flext::Timer::Periodic(double tm,void *data) { userdata = data; - period = tm; + period = tm; #if FLEXT_SYS == FLEXT_SYS_PD - clock_delay(clk,tm*1000); + clock_delay(clk,tm*1000.); #elif FLEXT_SYS == FLEXT_SYS_MAX clock_fdelay(clk,tm*1000.); #else @@ -257,29 +232,26 @@ bool flext::Timer::Periodic(double tm,void *data) return true; } -/*! \brief Callback function for system clock. - \todo Make periodic events scheduled as such. -*/ +//! \brief Callback function for system clock. void flext::Timer::callback(Timer *tmr) { +#if FLEXT_SYS == FLEXT_SYS_MAX + if(tmr->queued) + qelem_set(tmr->qelem); + else +#endif + tmr->Work(); + if(tmr->period) { - // clearly it would be more precise if the periodic event is scheduled as such - // and not retriggered every time + // reschedule #if FLEXT_SYS == FLEXT_SYS_PD - clock_delay(tmr->clk,tmr->period*1000); + clock_delay(tmr->clk,tmr->period*1000.); #elif FLEXT_SYS == FLEXT_SYS_MAX clock_fdelay(tmr->clk,tmr->period*1000.); #else #error Not implemented #endif } - -#if FLEXT_SYS == FLEXT_SYS_MAX - if(tmr->queued) - qelem_set(tmr->qelem); - else -#endif - tmr->Work(); } #if FLEXT_SYS == FLEXT_SYS_MAX |