flext  0.6.0
flsupport.h
Go to the documentation of this file.
1 /*
2 flext - C++ layer for Max and Pure Data externals
3 
4 Copyright (c) 2001-2017 Thomas Grill (gr@grrrr.org)
5 For information on usage and redistribution, and for a DISCLAIMER OF ALL
6 WARRANTIES, see the file, "license.txt," in this distribution.
7 */
8 
13 #ifndef __FLSUPPORT_H
14 #define __FLSUPPORT_H
15 
16 #include "flstdc.h"
17 #include <new>
18 #include <cstring>
19 
20 
21 #include "flpushns.h"
22 
23 #if C74_MAX_SDK_VERSION >= 0x0610
24 // really bad: post and error are #defines in Max SDK >= 610
25 #undef post
26 #undef error
27 #endif
28 
34 
35 typedef FLEXT_TEMPINST(FLEXT_SHARE FLEXT_CLASSDEF(flext_root)) flext_root;
36 
43 class FLEXT_SHARE FLEXT_CLASSDEF(flext_root) {
44 public:
45 // --- console output -----------------------------------------------
46 
48  static void post(const char *fmt,...);
50  static void error(const char *fmt,...);
51 
52 // --- memory -------------------------------------------------------
53 
58 #ifdef FLEXT_NOGLOBALNEW
59 #error FLEXT_NOGLOBALNEW is deprecated, define FLEXT_USE_CMEM instead
60 #define FLEXT_USE_CMEM
61 #endif
62 
63 #ifdef FLEXT_USE_CMEM
64  inline void *operator new(size_t bytes) { return ::operator new(bytes); }
65  inline void operator delete(void *blk) { ::operator delete(blk); }
66 
67  inline void *operator new[](size_t bytes) { return ::operator new[](bytes); }
68  inline void operator delete[](void *blk) { ::operator delete[](blk); }
69 
70  static bool MemCheck(void *) { return true; }
71 #else
72 
76  void *operator new(size_t bytes);
78  void operator delete(void *blk);
79 
80 #ifndef __MRC__ // doesn't allow new[] overloading?!
81  inline void *operator new[](size_t bytes) { return operator new(bytes); }
82  inline void operator delete[](void *blk) { operator delete(blk); }
83 #endif
84 
85 #ifdef FLEXT_DEBUGMEM
86  static bool MemCheck(void *blk);
87 #else
88  static bool MemCheck(void *) { return true; }
89 #endif
90 
91 #endif // USECMEM
92 
93 #ifndef __BORLANDC__
94  inline void *operator new(size_t,void *p) { return p; }
95  inline void operator delete(void *,void *) {}
96 #ifndef __MRC__
97  inline void *operator new[](size_t,void *p) { return p; }
98  inline void operator delete[](void *,void *) {}
99 #endif
100 #endif
101 
103  static void *NewAligned(size_t bytes,int bitalign = 128);
104  // same with templated type
105  template<typename T>
106  static T *NewAligned(size_t times,int bitalign = 128) { return static_cast<T *>(NewAligned(times*sizeof(T),bitalign)); }
108  static void FreeAligned(void *blk);
110  static bool IsAligned(void *ptr,int bitalign = 128) {
111  return (reinterpret_cast<size_t>(ptr)&(bitalign-1)) == 0;
112  }
114 };
115 
116 #ifdef FLEXT_USE_CMEM
117 #define NEWTHROW
118 #define DELTHROW
119 #else
120 
121 /************************************************************************/
122 // MFC doesn't like global overloading of allocators
123 // anyway, who likes MFC
124 
125 #if !defined(_MSC_VER) && !defined(__BORLANDC__)
126 #define NEWTHROW throw(std::bad_alloc)
127 #define DELTHROW throw()
128 #else
129 #define NEWTHROW
130 #define DELTHROW
131 #endif
132 
133 // define global new/delete operators
134 void *operator new(size_t bytes) NEWTHROW;
135 void operator delete(void *blk) DELTHROW;
136 #ifndef __MRC__ // doesn't allow new[] overloading?!
137 void *operator new[](size_t bytes) NEWTHROW;
138 void operator delete[](void *blk) DELTHROW;
139 #endif
140 
141 #endif // FLEXT_USE_CMEM
142 
143 /************************************************************************/
144 
146 
147 typedef FLEXT_TEMPINST(FLEXT_CLASSDEF(flext)) flext;
148 
150 
164 class FLEXT_SHARE FLEXT_CLASSDEF(flext):
165  public flext_root
166 {
170 public:
171 
172 // --- version -----------------------------------------------
173 
180  static int Version();
181 
183  static const char *VersionStr();
184 
185 // --- special typedefs ---------------------------------------------
186 
187 // later!
188 #if 0
189  typedef t_float Float;
190  typedef t_int Int;
191  typedef t_sample Sample;
192  typedef const t_symbol *Symbol;
193  typedef t_atom Atom;
194 #endif
195 
196 // --- buffer/array stuff -----------------------------------------
197 
202  class FLEXT_SHARE buffer:
204  public flext_root
205  {
206  public:
207 
208 #if FLEXT_SYS == FLEXT_SYS_PD
209  typedef bool lock_t;
210 #elif FLEXT_SYS == FLEXT_SYS_MAX
211  typedef long lock_t;
212 #else
213 #error Not implemented
214 #endif
215 
216 
217 // PD 64-bit buffer handling macros
218 #if FLEXT_SYS == FLEXT_SYS_PD
219 # if PD_MINOR_VERSION >= 41
220  /* use new garray support that is 64-bit safe */
221 # define FLEXT_PD_ARRAYGRAB garray_getfloatwords
222 # define FLEXT_ARRAYTYPE t_word
223 # define FLEXT_GETSAMPLE(x) ((x).w_float)
224 # define _FLEXT_NEED_SAMPLE_CONV 1
225 
226 # else
227  /* use old garray support, not 64-bit safe */
228 # define FLEXT_PD_ARRAYGRAB garray_getfloatarray
229 # define FLEXT_ARRAYTYPE t_sample
230 # define FLEXT_GETSAMPLE(x) (x)
231 # define _FLEXT_NEED_SAMPLE_CONV 0
232 # endif
233 
234 #elif FLEXT_SYS == FLEXT_SYS_MAX
235 # define FLEXT_ARRAYTYPE float
236 # define FLEXT_GETSAMPLE(x) (x)
237 # define _FLEXT_NEED_SAMPLE_CONV 0
238 #endif
239 
240  class Element {
241  public:
242  Element() {}
243  Element(FLEXT_ARRAYTYPE s): el(s) {}
244  operator FLEXT_ARRAYTYPE &() { return el; }
245  operator FLEXT_ARRAYTYPE () const { return el; }
246 #if _FLEXT_NEED_SAMPLE_CONV
247  Element(t_sample s) { FLEXT_GETSAMPLE(el) = s; }
248  operator t_sample &() { return FLEXT_GETSAMPLE(el); }
249  operator t_sample () const { return FLEXT_GETSAMPLE(el); }
250 #endif
251  protected:
252  FLEXT_ARRAYTYPE el;
253  };
254 
260  buffer(const t_symbol *s = NULL,bool delayed = false);
261 
263  ~buffer();
264 
268  bool Ok() const
269  {
270  return sym
271 #if FLEXT_SYS == FLEXT_SYS_PD
272  && arr
273 #endif
274  && data;
275  }
276 
280  bool Valid() const
281  {
282  FLEXT_ASSERT(sym);
283 #if FLEXT_SYS == FLEXT_SYS_PD
284  return true;
285 #elif FLEXT_SYS == FLEXT_SYS_MAX
286  const t_buffer *p = (const t_buffer *)sym->s_thing;
287  return p && p->b_valid;
288 #else
289 #error not implemented
290 #endif
291  }
292 
296  bool Update();
297 
302  lock_t Lock();
303 
308  void Unlock(lock_t prv);
309 
314  int Set(const t_symbol *s = NULL,bool nameonly = false);
315 
319  void Dirty(bool refr = false);
320 
322  void ClearDirty();
323 
327  bool IsDirty() const;
328 
330  const t_symbol *Symbol() const { return sym; }
331 
333  const char *Name() const { return sym?GetString(sym):""; }
334 
338  Element *Data() { return data; }
339 
340  const Element *Data() const { return data; }
341 
343  int Channels() const { return chns; }
345  int Frames() const { return frames; }
347  void Frames(int fr,bool keep = false,bool zero = true);
348 
350  inline Element operator [](int index) const { return data[index]; }
351 
353  inline Element &operator [](int index) { return data[index]; }
354 
356  void SetRefrIntv(float intv);
357 
359  class Locker
360  {
361  public:
362  Locker(buffer &b): buf(b),lock(b.Lock()) {}
363  ~Locker() { buf.Unlock(lock); }
364  private:
365  buffer &buf;
366  lock_t lock;
367  };
368 
369  protected:
371  const t_symbol *sym;
373  Element *data;
375  int chns;
377  int frames;
378 #if FLEXT_SYS == FLEXT_SYS_PD
379  t_garray *arr;
382  float interval;
384  bool isdirty;
386  bool ticking;
388  t_clock *tick;
390  double cleantime;
391 
392  private:
394  static void cb_tick(buffer *b);
395 #elif FLEXT_SYS == FLEXT_SYS_MAX
396  long cleantime;
398 #endif
399  };
400 
401 
403 
404 // --- utilities --------------------------------------------------
405 
410  static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
412 
414  static void CopyAtoms(int cnt,t_atom *dst,const t_atom *src);
415 
417  static bool PrintAtom(const t_atom &a,char *buf,size_t bufsz);
418 
422  static const char *ScanAtom(t_atom &a,const char *buf);
423 
425  static t_atom *CopyList(int argc,const t_atom *argv);
426 
428  static bool PrintList(int argc,const t_atom *argv,char *buf,size_t bufsz);
429 
435  static int ScanList(int argc,t_atom *argv,const char *buf);
436 
438  static void CopyMem(void *dst,const void *src,int bytes);
440  static void CopySamples(t_sample *dst,const t_sample *src,int cnt);
441  template<typename T> static void CopySamples(T *dst,const T *src,int cnt) { CopyMem(dst,src,sizeof(*src)*cnt); }
443  static void ZeroMem(void *dst,int bytes);
445  static void SetSamples(t_sample *dst,int cnt,t_sample s);
446  template<typename T> static void SetSamples(T *dst,int cnt,t_sample s) { for(int i = 0; i < cnt; ++i) dst[i] = s; }
448  static void ZeroSamples(t_sample *dst,int cnt) { SetSamples(dst,cnt,0); }
449  template<typename T> static void ZeroSamples(T *dst,int cnt) { ZeroMem(dst,sizeof(*dst)*cnt); }
450 
451 
453  static unsigned long AtomHash(const t_atom &a);
454 
456 
457 // --- various symbols --------------------------------------------
458 
463  static const t_symbol *sym__;
466  static const t_symbol *sym_float;
468  static const t_symbol *sym_symbol;
470  static const t_symbol *sym_bang;
472  static const t_symbol *sym_list;
474  static const t_symbol *sym_anything;
475 
479  static const t_symbol *sym_int;
480 
484  static const t_symbol *sym_pointer;
485 
487  static const t_symbol *sym_signal;
488 
490  static const t_symbol *MakeSymbol(const t_symbol *s) { return s; }
491 
493  static const t_symbol *MakeSymbol(const char *s) { return ::gensym(const_cast<char *>(s)); }
495  static const char *GetString(const t_symbol *s) { return s->s_name; }
497  static const char *GetAString(const t_symbol *s,const char *def = NULL) { return s?GetString(s):def; }
498 
499 // --- atom stuff ----------------------------------------
500 
502  static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); }
504  static int CmpAtom(const t_atom &a,const t_atom &b);
505 
506  // there are some more comparison functions for t_atom types outside the class
507 
509  static int GetType(const t_atom &a) { return a.a_type; }
510 
512  static bool IsNothing(const t_atom &a) { return a.a_type == A_NULL; }
514  static void SetNothing(t_atom &a) { a.a_type = A_NULL; }
515 
517  static bool IsFloat(const t_atom &a) { return a.a_type == A_FLOAT; }
518 
520  static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); }
521 
523  static float GetFloat(const t_atom &a) { return a.a_w.w_float; }
525  static void SetFloat(t_atom &a,float v) { a.a_type = A_FLOAT; a.a_w.w_float = v; }
526 
528  static bool IsSymbol(const t_atom &a) { return a.a_type == A_SYMBOL; }
529 
530 #if FLEXT_SYS == FLEXT_SYS_PD
531  static const t_symbol *GetSymbol(const t_atom &a) { return const_cast<const t_symbol *>(a.a_w.w_symbol); }
534  static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_symbol = const_cast<t_symbol *>(s); }
535 #elif FLEXT_SYS == FLEXT_SYS_MAX
536  static const t_symbol *GetSymbol(const t_atom &a) { return const_cast<const t_symbol *>(a.a_w.w_sym); }
539  static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_sym = const_cast<t_symbol *>(s); }
540 #else
541 #error
542 #endif
543  static const t_symbol *GetASymbol(const t_atom &a,const t_symbol *def = NULL) { return IsSymbol(a)?GetSymbol(a):def; } // NULL or empty symbol?
545 
547  static bool IsString(const t_atom &a) { return IsSymbol(a); }
549  static const char *GetString(const t_atom &a) { const t_symbol *s = GetSymbol(a); return s?GetString(s):NULL; }
551  static const char *GetAString(const t_atom &a,const char *def = NULL) { return IsSymbol(a)?GetAString(GetSymbol(a),def):def; }
553  static void GetAString(const t_atom &a,char *buf,size_t szbuf);
555  static void SetString(t_atom &a,const char *c) { SetSymbol(a,MakeSymbol(c)); }
556 
558  static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); }
559 
560 #if FLEXT_SYS == FLEXT_SYS_PD
561  static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):def; }
563 
565  static bool IsInt(const t_atom &) { return false; }
567  static int GetInt(const t_atom &a) { return (int)GetFloat(a); }
569  static int GetAInt(const t_atom &a,int def = 0) { return (int)GetAFloat(a,(float)def); }
571  static void SetInt(t_atom &a,int v) { a.a_type = A_FLOAT; a.a_w.w_float = (float)v; }
572 
573 #ifndef FLEXT_COMPATIBLE
574  static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; }
577  static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
579  static t_gpointer *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; }
581  static t_gpointer *GetAPointer(const t_atom &a,t_gpointer *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
583  static void SetPointer(t_atom &a,t_gpointer *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = (t_gpointer *)p; }
584 #endif
585 
586 #elif FLEXT_SYS == FLEXT_SYS_MAX
587  static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
589 
591  static bool IsInt(const t_atom &a) { return a.a_type == A_INT; }
593  static int GetInt(const t_atom &a) { return a.a_w.w_long; }
595  static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
597  static void SetInt(t_atom &a,int v) { a.a_type = A_INT; a.a_w.w_long = v; }
598 #else
599 #error "Platform not supported"
600 #endif
601 
602  // bool type - based on int
603 
605  static void SetBool(t_atom &a,bool v) { SetInt(a,v?1:0); }
607  static bool CanbeBool(const t_atom &a) { return CanbeInt(a); }
609  static bool GetABool(const t_atom &a) { return GetAInt(a) != 0; }
611  static bool GetBool(const t_atom &a) { return GetInt(a) != 0; }
612 
613 // --- atom list stuff -------------------------------------------
614 
616  class FLEXT_SHARE AtomList
617  : public flext_root
618  {
619  public:
621  AtomList(): cnt(0),lst(NULL) {}
623  explicit AtomList(int argc,const t_atom *argv = NULL): cnt(0),lst(NULL) { operator()(argc,argv); }
625  AtomList(const AtomList &a): cnt(0),lst(NULL) { operator =(a); }
627  virtual ~AtomList();
628 
630  AtomList &Clear() { return operator()(); }
631 
633  AtomList &Set(int argc,const t_atom *argv,int offs = 0,bool resize = false);
635  int Get(t_atom *argv,int mxsz = -1) const;
636 
638  AtomList &operator()(int argc = 0,const t_atom *argv = NULL) { return Set(argc,argv,0,true); }
640  AtomList &operator =(const AtomList &a) { return operator()(a.Count(),a.Atoms()); }
641 
643  int Compare(const AtomList &a) const;
644 
645  bool operator <(const AtomList &a) const { return Compare(a) < 0; }
646  bool operator <=(const AtomList &a) const { return Compare(a) <= 0; }
647  bool operator >(const AtomList &a) const { return Compare(a) > 0; }
648  bool operator >=(const AtomList &a) const { return Compare(a) >= 0; }
649  bool operator ==(const AtomList &a) const { return Compare(a) == 0; }
650  bool operator !=(const AtomList &a) const { return Compare(a) != 0; }
651 
653  int Count() const { return cnt; }
655  t_atom &operator [](int ix) { return lst[ix]; }
657  const t_atom &operator [](int ix) const { return lst[ix]; }
658 
660  t_atom *Atoms() { return lst; }
662  const t_atom *Atoms() const { return lst; }
663 
665  AtomList &Append(int argc,const t_atom *argv = NULL)
666  {
667  int c = Count();
668  Alloc(c+argc,0,c);
669  Set(argc,argv,c);
670  return *this;
671  }
672 
674  AtomList &Prepend(int argc,const t_atom *argv = NULL)
675  {
676  int c = Count();
677  Alloc(c+argc,0,c,argc);
678  Set(argc,argv);
679  return *this;
680  }
681 
683  AtomList &Append(const t_atom &a) { return Append(1,&a); }
685  AtomList &Append(const AtomList &a) { return Append(a.Count(),a.Atoms()); }
687  AtomList &Prepend(const t_atom &a) { return Prepend(1,&a); }
689  AtomList &Prepend(const AtomList &a) { return Prepend(a.Count(),a.Atoms()); }
690 
692  void GetPart(int offs,int len,AtomList &ret) const;
694  AtomList &Part(int offs,int len) { GetPart(offs,len,*this); return *this; }
695 
697  bool Print(char *buffer,int buflen) const { return flext::PrintList(Count(),Atoms(),buffer,buflen); }
698 
702  int Scan(const char *buffer) { return flext::ScanList(Count(),Atoms(),buffer); }
703 
704  protected:
705  virtual void Alloc(int sz,int keepix = -1,int keeplen = -1,int keepto = 0);
706  virtual void Free();
707 
708  int cnt;
709  t_atom *lst;
710  };
711 
712  class FLEXT_SHARE AtomListStaticBase
713  : public AtomList
714  {
715  protected:
716  explicit AtomListStaticBase(int pc,t_atom *dt): precnt(pc),predata(dt) {}
717  virtual ~AtomListStaticBase();
718  virtual void Alloc(int sz,int keepix = -1,int keeplen = -1,int keepto = 0);
719  virtual void Free();
720 
721  AtomListStaticBase &operator =(const AtomList &a) { AtomList::operator =(a); return *this; }
722  AtomListStaticBase &operator =(const AtomListStaticBase &a) { AtomList::operator =(a); return *this; }
723 
724  const int precnt;
725  t_atom *const predata;
726  };
727 
728  template<int PRE>
729  class AtomListStatic
730  : public AtomListStaticBase
731  {
732  public:
734  explicit AtomListStatic(): AtomListStaticBase(PRE,pre) {}
736  explicit AtomListStatic(int argc,const t_atom *argv = NULL): AtomListStaticBase(PRE,pre) { AtomList::operator()(argc,argv); }
738  explicit AtomListStatic(const AtomList &a): AtomListStaticBase(PRE,pre) { operator =(a); }
739 
741  AtomListStatic &operator =(const AtomList &a) { AtomListStaticBase::operator =(a); return *this; }
742  AtomListStatic &operator =(const AtomListStatic &a) { AtomListStaticBase::operator =(a); return *this; }
743  protected:
744  t_atom pre[PRE];
745  };
746 
748  class FLEXT_SHARE AtomAnything:
749  public AtomList
750  {
751  public:
752  explicit AtomAnything(): hdr(NULL) {}
753 
755  explicit AtomAnything(const t_symbol *h,int argc = 0,const t_atom *argv = NULL)
756  : AtomList(argc,argv),hdr(h?h:sym__)
757  {}
758 
760  explicit AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL)
761  : AtomList(argc,argv),hdr(MakeSymbol(h))
762  {}
763 
765  AtomAnything(const AtomAnything &a)
766  : AtomList(a),hdr(a.hdr)
767  {}
768 
770  AtomAnything &Clear() { return operator()(); }
771 
773  const t_symbol *Header() const { return hdr; }
774 
776  void Header(const t_symbol *h) { hdr = h; }
777 
779  AtomAnything &operator()(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL)
780  {
781  hdr = h; AtomList::operator()(argc,argv);
782  return *this;
783  }
784 
786  AtomAnything &operator =(const AtomAnything &a) { return operator()(a.Header(),a.Count(),a.Atoms()); }
787 
788  protected:
789  const t_symbol *hdr;
790  };
791 
792 
793  // double type - based on two floats
794 
795 #ifdef _MSC_VER
796 #pragma optimize("p",off) // improve floating point precision consistency
797 #endif
798  static t_atom *SetDouble(t_atom *dbl,double d)
799  {
800  float f = static_cast<float>(d);
801  float r = static_cast<float>(d-f);
802  SetFloat(dbl[0],f);
803  SetFloat(dbl[1],r);
804  return dbl;
805  }
806 #ifdef _MSC_VER
807 #pragma optimize("p",on)
808 #endif
809 
810  static double GetDouble(int argc,const t_atom *argv)
811  {
812  double d = argc >= 1?GetAFloat(argv[0]):0;
813  return argc >= 2?d+GetAFloat(argv[1]):d;
814  }
815 
816  static AtomList &SetDouble(AtomList &l,double d) { SetDouble(l(2).Atoms(),d); return l; }
817 
818  static double GetDouble(const AtomList &l) { return GetDouble(l.Count(),l.Atoms()); }
819 
821 
822 
823 // --- messages -------------------------------------------------------
824 
829  class MsgBundle;
830 
832  static MsgBundle *MsgNew();
833 
835  static void MsgFree(MsgBundle *mb);
836 
838  static void ToSysMsg(MsgBundle *mb);
839 
841  static void ToOutMsg(MsgBundle *mb);
842 
844  static void ToQueueMsg(MsgBundle *mb);
845 
847 
848 
853  static bool Forward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
854  static bool Forward(const t_symbol *sym,const AtomAnything &args) { return Forward(sym,args.Header(),args.Count(),args.Atoms()); }
855  static bool Forward(const char *sym,const AtomAnything &args) { return Forward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
856  static bool Forward(const t_symbol *sym,int argc,const t_atom *argv) { return Forward(sym,sym_list,argc,argv); }
857  static bool Forward(const t_symbol *sym,const AtomList &args) { return Forward(sym,args.Count(),args.Atoms()); }
858  static bool Forward(const char *sym,const AtomList &args) { return Forward(MakeSymbol(sym),args.Count(),args.Atoms()); }
859 
860  static bool SysForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
861  static bool SysForward(const t_symbol *sym,const AtomAnything &args) { return SysForward(sym,args.Header(),args.Count(),args.Atoms()); }
862  static bool SysForward(const char *sym,const AtomAnything &args) { return SysForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
863  static bool SysForward(const t_symbol *sym,int argc,const t_atom *argv) { return SysForward(sym,sym_list,argc,argv); }
864  static bool SysForward(const t_symbol *sym,const AtomList &args) { return SysForward(sym,args.Count(),args.Atoms()); }
865  static bool SysForward(const char *sym,const AtomList &args) { return SysForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
866 
867  static bool QueueForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
868  static bool QueueForward(const t_symbol *sym,const AtomAnything &args) { return QueueForward(sym,args.Header(),args.Count(),args.Atoms()); }
869  static bool QueueForward(const char *sym,const AtomAnything &args) { return QueueForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
870  static bool QueueForward(const t_symbol *sym,int argc,const t_atom *argv) { return QueueForward(sym,sym_list,argc,argv); }
871  static bool QueueForward(const t_symbol *sym,const AtomList &args) { return QueueForward(sym,args.Count(),args.Atoms()); }
872  static bool QueueForward(const char *sym,const AtomList &args) { return QueueForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
873 
874  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
875  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomAnything &args) { return MsgForward(mb,sym,args.Header(),args.Count(),args.Atoms()); }
876  static bool MsgForward(MsgBundle *mb,const char *sym,const AtomAnything &args) { return MsgForward(mb,MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
877  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,int argc,const t_atom *argv) { return MsgForward(mb,sym,sym_list,argc,argv); }
878  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomList &args) { return MsgForward(mb,sym,args.Count(),args.Atoms()); }
879  static bool MsgForward(MsgBundle *mb,const char *sym,const AtomList &args) { return MsgForward(mb,MakeSymbol(sym),args.Count(),args.Atoms()); }
880 
882 
883 
884 
885 // --- thread stuff -----------------------------------------------
886 
891 #if FLEXT_SYS == FLEXT_SYS_PD
892  #if PD_MINOR_VERSION >= 38 || (PD_MINOR_VERSION >= 37 && defined(PD_DEVEL_VERSION))
893  static void Lock() { sys_lock(); }
894  static void Unlock() { sys_unlock(); }
895  #else
896  // no system locking for old PD versions
897  static void Lock() {}
898  static void Unlock() {}
899  #endif
900 #elif FLEXT_SYS == FLEXT_SYS_MAX
901  // Max 4.2 upwards!
902  static void Lock() { critical_enter(0); }
903  static void Unlock() { critical_exit(0); }
904 #else
905 #error
906 #endif
907 
909 
914 #ifdef FLEXT_THREADS
916  static bool IsThreadRegistered();
917 #else
918  static bool IsThreadRegistered() { return false; }
919 #endif
920 
921 #ifdef FLEXT_THREADS
922 
924 # if FLEXT_THREADS == FLEXT_THR_MP
925  typedef MPTaskID thrid_t;
926 # elif FLEXT_THREADS == FLEXT_THR_POSIX
927  typedef pthread_t thrid_t;
928 # elif FLEXT_THREADS == FLEXT_THR_WIN32
929  typedef DWORD thrid_t;
930 # else
931 # error Threading model not supported
932 # endif
933 
936  static thrid_t GetThreadId() {
937 #if FLEXT_THREADS == FLEXT_THR_POSIX
938  return pthread_self();
939 #elif FLEXT_THREADS == FLEXT_THR_MP
940  return MPCurrentTaskID();
941 #elif FLEXT_THREADS == FLEXT_THR_WIN32
942  return GetCurrentThreadId();
943 #else
944 #error
945 #endif
946  }
947 
950  static thrid_t GetSysThreadId() { return thrid; }
951 
953  static bool ShouldExit();
954 
956  static bool IsThread(thrid_t t,thrid_t ref = GetThreadId()) {
957 #if FLEXT_THREADS == FLEXT_THR_POSIX
958  return pthread_equal(ref,t) != 0;
959 #else
960  return ref == t;
961 #endif
962  }
963 
964 
968  class FLEXT_SHARE thr_params:
969  public flext_root
970  {
971  public:
972  thr_params(int n = 1): cl(NULL),var(new _data[n]) {}
973  ~thr_params() { delete[] var; }
974 
975  void set_any(const t_symbol *s,int argc,const t_atom *argv) { var[0]._any = new AtomAnything(s,argc,argv); }
976  void set_list(int argc,const t_atom *argv) { var[0]._list = new AtomList(argc,argv); }
977 
979  union _data {
980  bool _bool;
981  float _float;
982  int _int;
983  t_symptr _t_symptr;
984  AtomAnything *_any;
985  AtomList *_list;
986  void *_ext;
987  } *var;
988  };
989 
990 protected:
991 
992  static thrid_t thrhelpid;
993  static thrid_t thrmsgid;
994  static void ThrHelper(void *);
995 
997  static thrid_t thrid; // the system thread
998 
999 private:
1000  static bool StartHelper(); // used in flext::Setup()
1001 
1002 public:
1003 
1007  static void ThrYield() {
1008 #if FLEXT_THREADS == FLEXT_THR_POSIX
1009  // for a preemptive system this should do nothing
1010  sched_yield();
1011 #elif FLEXT_THREADS == FLEXT_THR_MP
1012  MPYield();
1013 #elif FLEXT_THREADS == FLEXT_THR_WIN32
1014  SwitchToThread();
1015 #else
1016 #error
1017 #endif
1018  }
1019 
1022  static bool IsThreadPreemptive(thrid_t t = GetThreadId()) {
1023 #if FLEXT_THREADS == FLEXT_THR_POSIX || FLEXT_THREADS == FLEXT_THR_WIN32
1024  return true;
1025 #elif FLEXT_THREADS == FLEXT_THR_MP
1026  return MPTaskIsPreemptive(t);
1027 #else
1028 #error
1029 #endif
1030  }
1031 
1032 
1035  static bool RelPriority(int dp,thrid_t ref = GetSysThreadId(),thrid_t thr = GetThreadId());
1036 
1039  static int GetPriority(thrid_t thr = GetThreadId());
1040 
1043  static bool SetPriority(int p,thrid_t thr = GetThreadId());
1044 
1048  class FLEXT_SHARE ThrMutex:
1049  public flext_root
1050 #if FLEXT_THREADS == FLEXT_THR_POSIX
1051  {
1052  public:
1054  ThrMutex() { pthread_mutex_init(&mutex,NULL); }
1056  ~ThrMutex() { pthread_mutex_destroy(&mutex); }
1057 
1059  bool Lock() { return pthread_mutex_lock(&mutex) == 0; }
1063 // bool WaitForLock(double tm) { return pthread_mutex_lock(&mutex) == 0; }
1065  bool TryLock() { return pthread_mutex_trylock(&mutex) == 0; }
1067  bool Unlock() { return pthread_mutex_unlock(&mutex) == 0; }
1068 
1069  protected:
1070  pthread_mutex_t mutex;
1071 // int cnt;
1072  };
1073 #elif FLEXT_THREADS == FLEXT_THR_WIN32
1074  {
1075  public:
1077  ThrMutex() { ::InitializeCriticalSection(&mutex); }
1079  ~ThrMutex() { ::DeleteCriticalSection(&mutex); }
1080 
1082  bool Lock() { ::EnterCriticalSection(&mutex); return true; }
1086 // bool WaitForLock(double tm) { return pthread_mutex_lock(&mutex) == 0; }
1088  bool TryLock() { return ::TryEnterCriticalSection(&mutex) != 0; }
1090  bool Unlock() { ::LeaveCriticalSection(&mutex); return true; }
1091 
1092  protected:
1093  CRITICAL_SECTION mutex;
1094  };
1095 #elif FLEXT_THREADS == FLEXT_THR_MP
1096  {
1097  public:
1099  ThrMutex() { MPCreateCriticalRegion(&crit); }
1101  ~ThrMutex() { MPDeleteCriticalRegion(crit); }
1102 
1104  bool Lock() { return MPEnterCriticalRegion(crit,kDurationForever) == noErr; }
1106 // bool WaitForLock(double tm) { return MPEnterCriticalRegion(crit,tm*kDurationMicrosecond*1.e6) == noErr; }
1108  bool TryLock() { return MPEnterCriticalRegion(crit,kDurationImmediate) == noErr; }
1110  bool Unlock() { return MPExitCriticalRegion(crit) == noErr; }
1111 
1112  protected:
1113  MPCriticalRegionID crit;
1114  };
1115 #else
1116 #error "Not implemented"
1117 #endif
1118 
1122  class FLEXT_SHARE ThrCond
1124  :public ThrMutex
1125  {
1126  public:
1128  ThrCond() { pthread_cond_init(&cond,NULL); }
1130  ~ThrCond() { pthread_cond_destroy(&cond); }
1131 
1133  bool Wait();
1134 
1141  bool TimedWait(double ftime);
1142 
1144  bool Signal() { return pthread_cond_signal(&cond) == 0; }
1145 
1146  protected:
1147  pthread_cond_t cond;
1148  };
1149 #elif FLEXT_THREADS == FLEXT_THR_WIN32
1150  {
1151  public:
1153  ThrCond() { cond = CreateEvent(NULL,FALSE,FALSE,NULL); }
1155  ~ThrCond() { CloseHandle(cond); }
1156 
1158  bool Wait() { return WaitForSingleObject(cond,INFINITE) == WAIT_OBJECT_0; }
1159 
1166  bool TimedWait(double ftime) { return WaitForSingleObject(cond,(LONG)(ftime*1000)) == WAIT_OBJECT_0; }
1167 
1169  bool Signal() { return SetEvent(cond) != 0; }
1170 
1171  protected:
1172  HANDLE cond;
1173  };
1174 #elif FLEXT_THREADS == FLEXT_THR_MP
1175  {
1176  public:
1178  ThrCond() { MPCreateEvent(&ev); }
1180  ~ThrCond() { MPDeleteEvent(ev); }
1181 
1183  bool Wait() { return MPWaitForEvent(ev,NULL,kDurationForever) == noErr; }
1184 
1188  bool TimedWait(double tm) { return MPWaitForEvent(ev,NULL,tm*kDurationMicrosecond*1.e6) == noErr; }
1189 
1191  bool Signal() { return MPSetEvent(ev,1) == noErr; } // one bit needs to be set at least
1192 
1193  protected:
1194  MPEventID ev;
1195  };
1196 #else
1197 #error "Not implemented"
1198 #endif
1199 
1200  protected:
1206  static bool PushThread();
1207 
1212  static void PopThread();
1213 
1214  public:
1220  static bool LaunchThread(void (*meth)(thr_params *p),thr_params *params = NULL);
1221 
1229  static bool StopThread(void (*meth)(thr_params *p),thr_params *params = NULL,bool wait = false);
1230 
1231 
1233  static void RegisterThread(thrid_t id = GetThreadId());
1234 
1236  static void UnregisterThread(thrid_t id = GetThreadId());
1237 
1238 #endif // FLEXT_THREADS
1239 
1241 
1242 
1243  public:
1244 // --- timer stuff -----------------------------------------------
1245 
1258  static double GetTime()
1259  {
1260  #if FLEXT_SYS == FLEXT_SYS_PD
1261  return clock_gettimesince(0)*0.001;
1262  #elif FLEXT_SYS == FLEXT_SYS_MAX
1263  double tm;
1264  clock_getftime(&tm);
1265  return tm*0.001;
1266  #else
1267  #error Not implemented
1268  #endif
1269  }
1270 
1274  static double GetTimeGrain()
1275  {
1276  #if FLEXT_SYS == FLEXT_SYS_PD
1277  return 0;
1278  #elif FLEXT_SYS == FLEXT_SYS_MAX
1279  return 0.001;
1280  #else
1281  #error Not implemented
1282  #endif
1283  }
1284 
1287  static double GetOSTime();
1288 
1293  static void Sleep(double s);
1294 
1298  class FLEXT_SHARE Timer:
1299  public flext_root
1300  {
1301  public:
1302  Timer(bool queued = false);
1303  virtual ~Timer();
1304 
1306  void SetCallback(void (*cb)(void *data)) { clss = NULL,cback = cb; }
1308  void SetCallback(FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_base)) &th,bool (*cb)(FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_base)) *th,void *data)) { clss = &th,cback = (void (*)(void *))cb; }
1309 
1311  bool Reset();
1313  bool At(double time,void *data = NULL,bool dopast = true);
1315  bool Delay(double time,void *data = NULL);
1317  bool Periodic(double time,void *data = NULL);
1319  bool Now(void *data = NULL) { return Delay(0,data); }
1320 
1322  virtual void Work();
1323 
1324  protected:
1325  static void callback(Timer *tmr);
1326 
1327 #if FLEXT_SYS == FLEXT_SYS_PD
1328  t_clock *clk;
1329 #elif FLEXT_SYS == FLEXT_SYS_MAX
1330  static void queuefun(Timer *tmr);
1331  t_clock *clk;
1332  t_qelem *qelem;
1333 #else
1334 #error Not implemented
1335 #endif
1336 
1337  const bool queued;
1338  void (*cback)(void *data);
1340  void *userdata;
1341  double period;
1342  };
1343 
1345 
1347  static bool InDSP() { return indsp; }
1348 
1349 // --- SIMD functionality -----------------------------------------------
1350 
1354  enum simd_type {
1355  simd_none = 0,
1356  simd_mmx = 0x01,
1357  simd_3dnow = 0x02,
1358  simd_sse = 0x04,
1359  simd_sse2 = 0x08,
1360  simd_altivec = 0x10
1361  };
1362 
1364  static unsigned long GetSIMDCapabilities();
1365 
1366 
1367  static void MulSamples(t_sample *dst,const t_sample *src,t_sample mul,int cnt);
1368  static void MulSamples(t_sample *dst,const t_sample *src,const t_sample *mul,int cnt);
1369  static void AddSamples(t_sample *dst,const t_sample *src,t_sample add,int cnt);
1370  static void AddSamples(t_sample *dst,const t_sample *src,const t_sample *add,int cnt);
1371  static void ScaleSamples(t_sample *dst,const t_sample *src,t_sample mul,t_sample add,int cnt);
1372  static void ScaleSamples(t_sample *dst,const t_sample *src,t_sample mul,const t_sample *add,int cnt);
1373  static void ScaleSamples(t_sample *dst,const t_sample *src,const t_sample *mul,const t_sample *add,int cnt);
1374 
1376 
1377 
1379 
1380 protected:
1381 #ifdef __MRC__
1382  friend class flext_obj;
1383 #endif
1384 
1385  static void Setup();
1386 
1387  static bool chktilde(const char *objname);
1388 
1389  static unsigned long simdcaps;
1390 
1391  static const t_symbol *sym_attributes;
1392  static const t_symbol *sym_methods;
1393 
1394 #if FLEXT_SYS == FLEXT_SYS_MAX
1395  static const t_symbol *sym_buffer;
1396  static const t_symbol *sym_size;
1397  static const t_symbol *sym_dirty;
1398 #endif
1399 
1401  static bool indsp;
1402 };
1403 
1404 
1405 // gcc doesn't like these to be included into the flext class (even if static)
1406 inline bool operator ==(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) == 0; }
1407 inline bool operator !=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) != 0; }
1408 inline bool operator <(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) < 0; }
1409 inline bool operator <=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) <= 0; }
1410 inline bool operator >(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) > 0; }
1411 inline bool operator >=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) >= 0; }
1412 
1414 
1415 #include "flpopns.h"
1416 
1417 #endif
FLEXT_ASSERT
#define FLEXT_ASSERT(b)
Definition: flstdc.h:284
flext_base
Definition: flclass.h:60
flpopns.h
operator==
bool operator==(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1406
FLEXT_CLASSDEF
FLEXT_TEMPLATE class FLEXT_SHARE FLEXT_CLASSDEF(flext_root)
FLEXT_THREADS
#define FLEXT_THREADS
Definition: flcwmax-thr.h:18
DELTHROW
#define DELTHROW
Definition: flsupport.h:127
operator<=
bool operator<=(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1409
FLEXT_TEMPLATE
#define FLEXT_TEMPLATE
Definition: flprefix.h:462
t_symptr
t_symbol * t_symptr
Definition: flstdc.h:225
operator!=
bool operator!=(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1407
FLEXT_TEMPINST
typedef FLEXT_TEMPINST(FLEXT_SHARE FLEXT_CLASSDEF(flext_root)) flext_root
operator>=
bool operator>=(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1411
FLEXT_SHARE
#define FLEXT_SHARE
Definition: flprefix.h:425
flpushns.h
flstdc.h
Definitions to unite Max/MSP and PD notions.
operator<
bool operator<(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1408
NEWTHROW
#define NEWTHROW
Definition: flsupport.h:126
operator>
bool operator>(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1410
FLEXT_THR_POSIX
#define FLEXT_THR_POSIX
Definition: flprefix.h:80