flext  0.6.2
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-2020 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
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 
117 #ifdef FLEXT_USE_CMEM
118 # define NEWTHROW
119 # define DELTHROW
120 
121 #else
122 
123 // MFC doesn't like global overloading of allocators
124 // anyway, who likes MFC
125 
126 #if !defined(_MSC_VER) && !defined(__BORLANDC__)
127 #if __cpp_noexcept_function_type
128 # define NEWTHROW noexcept(false)
129 # define DELTHROW noexcept(true)
130 #else
131 # define NEWTHROW throw(std::bad_alloc)
132 # define DELTHROW throw()
133 #endif
134 #else
135 # define NEWTHROW
136 # define DELTHROW
137 #endif
138 
139 // define global new/delete operators
140 void *operator new(size_t bytes) NEWTHROW;
141 void operator delete(void *blk) DELTHROW;
142 #ifndef __MRC__ // doesn't allow new[] overloading?!
143 void *operator new[](size_t bytes) NEWTHROW;
144 void operator delete[](void *blk) DELTHROW;
145 #endif
146 
147 #endif // FLEXT_USE_CMEM
148 
149 /************************************************************************/
150 
152 
153 typedef FLEXT_TEMPINST(FLEXT_CLASSDEF(flext)) flext;
154 
156 
170 class FLEXT_SHARE FLEXT_CLASSDEF(flext):
171  public flext_root
172 {
176 public:
177 
178 // --- version -----------------------------------------------
179 
186  static int Version();
187 
189  static const char *VersionStr();
190 
191 // --- special typedefs ---------------------------------------------
192 
193 // later!
194 #if 0
195  typedef t_float Float;
196  typedef t_int Int;
197  typedef t_sample Sample;
198  typedef const t_symbol *Symbol;
199  typedef t_atom Atom;
200 #endif
201 
202 // --- buffer/array stuff -----------------------------------------
203 
209  class FLEXT_SHARE buffer:
210  public flext_root
211  {
212  public:
213 
214 #if FLEXT_SYS == FLEXT_SYS_PD
215  typedef bool lock_t;
216 #elif FLEXT_SYS == FLEXT_SYS_MAX
217  typedef long lock_t;
218 #else
219 #error Not implemented
220 #endif
221 
222 
223 // PD 64-bit buffer handling macros
224 #if FLEXT_SYS == FLEXT_SYS_PD
225 # if PD_MINOR_VERSION >= 41
226  /* use new garray support that is 64-bit safe */
227 # define FLEXT_PD_ARRAYGRAB garray_getfloatwords
228 # define FLEXT_ARRAYTYPE t_word
229 # define FLEXT_GETSAMPLE(x) ((x).w_float)
230 # define _FLEXT_NEED_SAMPLE_CONV 1
231 
232 # else
233  /* use old garray support, not 64-bit safe */
234 # define FLEXT_PD_ARRAYGRAB garray_getfloatarray
235 # define FLEXT_ARRAYTYPE t_sample
236 # define FLEXT_GETSAMPLE(x) (x)
237 # define _FLEXT_NEED_SAMPLE_CONV 0
238 # endif
239 
240 #elif FLEXT_SYS == FLEXT_SYS_MAX
241 # define FLEXT_ARRAYTYPE float
242 # define FLEXT_GETSAMPLE(x) (x)
243 # define _FLEXT_NEED_SAMPLE_CONV 0
244 #endif
245 
246  class Element {
247  public:
248  Element() {}
249  Element(FLEXT_ARRAYTYPE s): el(s) {}
250  operator FLEXT_ARRAYTYPE &() { return el; }
251  operator FLEXT_ARRAYTYPE () const { return el; }
252 #if _FLEXT_NEED_SAMPLE_CONV
253  Element(t_sample s) { FLEXT_GETSAMPLE(el) = s; }
254  operator t_sample &() { return FLEXT_GETSAMPLE(el); }
255  operator t_sample () const { return FLEXT_GETSAMPLE(el); }
256 #endif
257  protected:
258  FLEXT_ARRAYTYPE el;
259  };
260 
266  buffer(const t_symbol *s = NULL,bool delayed = false);
267 
269  ~buffer();
270 
274  bool Ok() const
275  {
276  return sym
277 #if FLEXT_SYS == FLEXT_SYS_PD
278  && arr
279 #endif
280  && data;
281  }
282 
286  bool Valid() const
287  {
288  FLEXT_ASSERT(sym);
289 #if FLEXT_SYS == FLEXT_SYS_PD
290  return true;
291 #elif FLEXT_SYS == FLEXT_SYS_MAX
292  const t_buffer *p = (const t_buffer *)sym->s_thing;
293  return p && p->b_valid;
294 #else
295 #error not implemented
296 #endif
297  }
298 
302  bool Update();
303 
308  lock_t Lock();
309 
314  void Unlock(lock_t prv);
315 
320  int Set(const t_symbol *s = NULL,bool nameonly = false);
321 
325  void Dirty(bool refr = false);
326 
328  void ClearDirty();
329 
333  bool IsDirty() const;
334 
336  const t_symbol *Symbol() const { return sym; }
337 
339  const char *Name() const { return sym?GetString(sym):""; }
340 
344  Element *Data() { return data; }
345 
346  const Element *Data() const { return data; }
347 
349  int Channels() const { return chns; }
351  int Frames() const { return frames; }
353  void Frames(int fr,bool keep = false,bool zero = true);
354 
356  inline Element operator [](int index) const { return data[index]; }
357 
359  inline Element &operator [](int index) { return data[index]; }
360 
362  void SetRefrIntv(float intv);
363 
365  class Locker
366  {
367  public:
368  Locker(buffer &b): buf(b),lock(b.Lock()) {}
369  ~Locker() { buf.Unlock(lock); }
370  private:
371  buffer &buf;
372  lock_t lock;
373  };
374 
375  protected:
377  const t_symbol *sym;
379  Element *data;
381  int chns;
383  int frames;
384 #if FLEXT_SYS == FLEXT_SYS_PD
386  t_garray *arr;
388  float interval;
390  bool isdirty;
392  bool ticking;
394  t_clock *tick;
396  double cleantime;
397 
398  private:
400  static void cb_tick(buffer *b);
401 #elif FLEXT_SYS == FLEXT_SYS_MAX
403  long cleantime;
404 #endif
405  };
406 
407 
409 
410 // --- utilities --------------------------------------------------
411 
417  static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
418 
420  static void CopyAtoms(int cnt,t_atom *dst,const t_atom *src);
421 
423  static bool PrintAtom(const t_atom &a,char *buf,size_t bufsz);
424 
428  static const char *ScanAtom(t_atom &a,const char *buf);
429 
431  static t_atom *CopyList(int argc,const t_atom *argv);
432 
434  static bool PrintList(int argc,const t_atom *argv,char *buf,size_t bufsz);
435 
441  static int ScanList(int argc,t_atom *argv,const char *buf);
442 
444  static void CopyMem(void *dst,const void *src,int bytes);
446  static void CopySamples(t_sample *dst,const t_sample *src,int cnt);
447  template<typename T> static void CopySamples(T *dst,const T *src,int cnt) { CopyMem(dst,src,sizeof(*src)*cnt); }
449  static void ZeroMem(void *dst,int bytes);
451  static void SetSamples(t_sample *dst,int cnt,t_sample s);
452  template<typename T> static void SetSamples(T *dst,int cnt,t_sample s) { for(int i = 0; i < cnt; ++i) dst[i] = s; }
454  static void ZeroSamples(t_sample *dst,int cnt) { SetSamples(dst,cnt,0); }
455  template<typename T> static void ZeroSamples(T *dst,int cnt) { ZeroMem(dst,sizeof(*dst)*cnt); }
456 
457 
459  static unsigned long AtomHash(const t_atom &a);
460 
462 
463 // --- various symbols --------------------------------------------
464 
470  static const t_symbol *sym__;
472  static const t_symbol *sym_float;
474  static const t_symbol *sym_symbol;
476  static const t_symbol *sym_bang;
478  static const t_symbol *sym_list;
480  static const t_symbol *sym_anything;
481 
485  static const t_symbol *sym_int;
486 
490  static const t_symbol *sym_pointer;
491 
493  static const t_symbol *sym_signal;
494 
496  static const t_symbol *MakeSymbol(const t_symbol *s) { return s; }
497 
499  static const t_symbol *MakeSymbol(const char *s) { return ::gensym(const_cast<char *>(s)); }
501  static const char *GetString(const t_symbol *s) { return s->s_name; }
503  static const char *GetAString(const t_symbol *s,const char *def = NULL) { return s?GetString(s):def; }
504 
505 // --- atom stuff ----------------------------------------
506 
508  static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); }
510  static int CmpAtom(const t_atom &a,const t_atom &b);
511 
512  // there are some more comparison functions for t_atom types outside the class
513 
515  static int GetType(const t_atom &a) { return a.a_type; }
516 
518  static bool IsNothing(const t_atom &a) { return a.a_type == A_NULL; }
520  static void SetNothing(t_atom &a) { a.a_type = A_NULL; }
521 
523  static bool IsFloat(const t_atom &a) { return a.a_type == A_FLOAT; }
524 
526  static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); }
527 
529  static float GetFloat(const t_atom &a) { return a.a_w.w_float; }
531  static void SetFloat(t_atom &a,float v) { a.a_type = A_FLOAT; a.a_w.w_float = v; }
532 
534  static bool IsSymbol(const t_atom &a) { return a.a_type == A_SYMBOL; }
535 
536 #if FLEXT_SYS == FLEXT_SYS_PD
538  static const t_symbol *GetSymbol(const t_atom &a) { return const_cast<const t_symbol *>(a.a_w.w_symbol); }
540  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); }
541 #elif FLEXT_SYS == FLEXT_SYS_MAX
543  static const t_symbol *GetSymbol(const t_atom &a) { return const_cast<const t_symbol *>(a.a_w.w_sym); }
545  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); }
546 #else
547 #error
548 #endif
550  static const t_symbol *GetASymbol(const t_atom &a,const t_symbol *def = NULL) { return IsSymbol(a)?GetSymbol(a):def; } // NULL or empty symbol?
551 
553  static bool IsString(const t_atom &a) { return IsSymbol(a); }
555  static const char *GetString(const t_atom &a) { const t_symbol *s = GetSymbol(a); return s?GetString(s):NULL; }
557  static const char *GetAString(const t_atom &a,const char *def = NULL) { return IsSymbol(a)?GetAString(GetSymbol(a),def):def; }
559  static void GetAString(const t_atom &a,char *buf,size_t szbuf);
561  static void SetString(t_atom &a,const char *c) { SetSymbol(a,MakeSymbol(c)); }
562 
564  static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); }
565 
566 #if FLEXT_SYS == FLEXT_SYS_PD
568  static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):def; }
569 
571  static bool IsInt(const t_atom &) { return false; }
573  static int GetInt(const t_atom &a) { return (int)GetFloat(a); }
575  static int GetAInt(const t_atom &a,int def = 0) { return (int)GetAFloat(a,(float)def); }
577  static void SetInt(t_atom &a,int v) { a.a_type = A_FLOAT; a.a_w.w_float = (float)v; }
578 
579 #ifndef FLEXT_COMPATIBLE
581  static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; }
583  static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
585  static t_gpointer *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; }
587  static t_gpointer *GetAPointer(const t_atom &a,t_gpointer *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
589  static void SetPointer(t_atom &a,t_gpointer *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = (t_gpointer *)p; }
590 #endif
591 
592 #elif FLEXT_SYS == FLEXT_SYS_MAX
594  static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
595 
597  static bool IsInt(const t_atom &a) { return a.a_type == A_INT; }
599  static int GetInt(const t_atom &a) { return a.a_w.w_long; }
601  static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
603  static void SetInt(t_atom &a,int v) { a.a_type = A_INT; a.a_w.w_long = v; }
604 #else
605 #error "Platform not supported"
606 #endif
607 
608  // bool type - based on int
609 
611  static void SetBool(t_atom &a,bool v) { SetInt(a,v?1:0); }
613  static bool CanbeBool(const t_atom &a) { return CanbeInt(a); }
615  static bool GetABool(const t_atom &a) { return GetAInt(a) != 0; }
617  static bool GetBool(const t_atom &a) { return GetInt(a) != 0; }
618 
619 // --- atom list stuff -------------------------------------------
620 
622  class FLEXT_SHARE AtomList
623  : public flext_root
624  {
625  public:
627  AtomList(): cnt(0),lst(NULL) {}
629  explicit AtomList(int argc,const t_atom *argv = NULL): cnt(0),lst(NULL) { operator()(argc,argv); }
631  AtomList(const AtomList &a): cnt(0),lst(NULL) { operator =(a); }
633  virtual ~AtomList();
634 
636  AtomList &Clear() { return operator()(); }
637 
639  AtomList &Set(int argc,const t_atom *argv,int offs = 0,bool resize = false);
641  int Get(t_atom *argv,int mxsz = -1) const;
642 
644  AtomList &operator()(int argc = 0,const t_atom *argv = NULL) { return Set(argc,argv,0,true); }
646  AtomList &operator =(const AtomList &a) { return operator()(a.Count(),a.Atoms()); }
647 
649  int Compare(const AtomList &a) const;
650 
651  bool operator <(const AtomList &a) const { return Compare(a) < 0; }
652  bool operator <=(const AtomList &a) const { return Compare(a) <= 0; }
653  bool operator >(const AtomList &a) const { return Compare(a) > 0; }
654  bool operator >=(const AtomList &a) const { return Compare(a) >= 0; }
655  bool operator ==(const AtomList &a) const { return Compare(a) == 0; }
656  bool operator !=(const AtomList &a) const { return Compare(a) != 0; }
657 
659  int Count() const { return cnt; }
661  t_atom &operator [](int ix) { return lst[ix]; }
663  const t_atom &operator [](int ix) const { return lst[ix]; }
664 
666  t_atom *Atoms() { return lst; }
668  const t_atom *Atoms() const { return lst; }
669 
671  AtomList &Append(int argc,const t_atom *argv = NULL)
672  {
673  int c = Count();
674  Alloc(c+argc,0,c);
675  Set(argc,argv,c);
676  return *this;
677  }
678 
680  AtomList &Prepend(int argc,const t_atom *argv = NULL)
681  {
682  int c = Count();
683  Alloc(c+argc,0,c,argc);
684  Set(argc,argv);
685  return *this;
686  }
687 
689  AtomList &Append(const t_atom &a) { return Append(1,&a); }
691  AtomList &Append(const AtomList &a) { return Append(a.Count(),a.Atoms()); }
693  AtomList &Prepend(const t_atom &a) { return Prepend(1,&a); }
695  AtomList &Prepend(const AtomList &a) { return Prepend(a.Count(),a.Atoms()); }
696 
698  void GetPart(int offs,int len,AtomList &ret) const;
700  AtomList &Part(int offs,int len) { GetPart(offs,len,*this); return *this; }
701 
703  bool Print(char *buffer,int buflen) const { return flext::PrintList(Count(),Atoms(),buffer,buflen); }
704 
708  int Scan(const char *buffer) { return flext::ScanList(Count(),Atoms(),buffer); }
709 
710  protected:
711  virtual void Alloc(int sz,int keepix = -1,int keeplen = -1,int keepto = 0);
712  virtual void Free();
713 
714  int cnt;
715  t_atom *lst;
716  };
717 
718  class FLEXT_SHARE AtomListStaticBase
719  : public AtomList
720  {
721  protected:
722  explicit AtomListStaticBase(int pc,t_atom *dt): precnt(pc),predata(dt) {}
723  virtual ~AtomListStaticBase();
724  virtual void Alloc(int sz,int keepix = -1,int keeplen = -1,int keepto = 0);
725  virtual void Free();
726 
727  AtomListStaticBase &operator =(const AtomList &a) { AtomList::operator =(a); return *this; }
728  AtomListStaticBase &operator =(const AtomListStaticBase &a) { AtomList::operator =(a); return *this; }
729 
730  const int precnt;
731  t_atom *const predata;
732  };
733 
734  template<int PRE>
735  class AtomListStatic
736  : public AtomListStaticBase
737  {
738  public:
740  explicit AtomListStatic(): AtomListStaticBase(PRE,pre) {}
742  explicit AtomListStatic(int argc,const t_atom *argv = NULL): AtomListStaticBase(PRE,pre) { AtomList::operator()(argc,argv); }
744  explicit AtomListStatic(const AtomList &a): AtomListStaticBase(PRE,pre) { operator =(a); }
745 
747  AtomListStatic &operator =(const AtomList &a) { AtomListStaticBase::operator =(a); return *this; }
748  AtomListStatic &operator =(const AtomListStatic &a) { AtomListStaticBase::operator =(a); return *this; }
749  protected:
750  t_atom pre[PRE];
751  };
752 
754  class FLEXT_SHARE AtomAnything:
755  public AtomList
756  {
757  public:
758  explicit AtomAnything(): hdr(NULL) {}
759 
761  explicit AtomAnything(const t_symbol *h,int argc = 0,const t_atom *argv = NULL)
762  : AtomList(argc,argv),hdr(h?h:sym__)
763  {}
764 
766  explicit AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL)
767  : AtomList(argc,argv),hdr(MakeSymbol(h))
768  {}
769 
771  AtomAnything(const AtomAnything &a)
772  : AtomList(a),hdr(a.hdr)
773  {}
774 
776  AtomAnything &Clear() { return operator()(); }
777 
779  const t_symbol *Header() const { return hdr; }
780 
782  void Header(const t_symbol *h) { hdr = h; }
783 
785  AtomAnything &operator()(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL)
786  {
787  hdr = h; AtomList::operator()(argc,argv);
788  return *this;
789  }
790 
792  AtomAnything &operator =(const AtomAnything &a) { return operator()(a.Header(),a.Count(),a.Atoms()); }
793 
794  protected:
795  const t_symbol *hdr;
796  };
797 
798 
799  // double type - based on two floats
800 
801 #ifdef _MSC_VER
802 #pragma optimize("p",off) // improve floating point precision consistency
803 #endif
804  static t_atom *SetDouble(t_atom *dbl,double d)
805  {
806  float f = static_cast<float>(d);
807  float r = static_cast<float>(d-f);
808  SetFloat(dbl[0],f);
809  SetFloat(dbl[1],r);
810  return dbl;
811  }
812 #ifdef _MSC_VER
813 #pragma optimize("p",on)
814 #endif
815 
816  static double GetDouble(int argc,const t_atom *argv)
817  {
818  double d = argc >= 1?GetAFloat(argv[0]):0;
819  return argc >= 2?d+GetAFloat(argv[1]):d;
820  }
821 
822  static AtomList &SetDouble(AtomList &l,double d) { SetDouble(l(2).Atoms(),d); return l; }
823 
824  static double GetDouble(const AtomList &l) { return GetDouble(l.Count(),l.Atoms()); }
825 
827 
828 
829 // --- messages -------------------------------------------------------
830 
835  class MsgBundle;
836 
838  static MsgBundle *MsgNew();
839 
841  static void MsgFree(MsgBundle *mb);
842 
844  static void ToSysMsg(MsgBundle *mb);
845 
847  static void ToOutMsg(MsgBundle *mb);
848 
850  static void ToQueueMsg(MsgBundle *mb);
851 
853 
854 
859  static bool Forward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
860  static bool Forward(const t_symbol *sym,const AtomAnything &args) { return Forward(sym,args.Header(),args.Count(),args.Atoms()); }
861  static bool Forward(const char *sym,const AtomAnything &args) { return Forward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
862  static bool Forward(const t_symbol *sym,int argc,const t_atom *argv) { return Forward(sym,sym_list,argc,argv); }
863  static bool Forward(const t_symbol *sym,const AtomList &args) { return Forward(sym,args.Count(),args.Atoms()); }
864  static bool Forward(const char *sym,const AtomList &args) { return Forward(MakeSymbol(sym),args.Count(),args.Atoms()); }
865 
866  static bool SysForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
867  static bool SysForward(const t_symbol *sym,const AtomAnything &args) { return SysForward(sym,args.Header(),args.Count(),args.Atoms()); }
868  static bool SysForward(const char *sym,const AtomAnything &args) { return SysForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
869  static bool SysForward(const t_symbol *sym,int argc,const t_atom *argv) { return SysForward(sym,sym_list,argc,argv); }
870  static bool SysForward(const t_symbol *sym,const AtomList &args) { return SysForward(sym,args.Count(),args.Atoms()); }
871  static bool SysForward(const char *sym,const AtomList &args) { return SysForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
872 
873  static bool QueueForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
874  static bool QueueForward(const t_symbol *sym,const AtomAnything &args) { return QueueForward(sym,args.Header(),args.Count(),args.Atoms()); }
875  static bool QueueForward(const char *sym,const AtomAnything &args) { return QueueForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
876  static bool QueueForward(const t_symbol *sym,int argc,const t_atom *argv) { return QueueForward(sym,sym_list,argc,argv); }
877  static bool QueueForward(const t_symbol *sym,const AtomList &args) { return QueueForward(sym,args.Count(),args.Atoms()); }
878  static bool QueueForward(const char *sym,const AtomList &args) { return QueueForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
879 
880  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
881  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomAnything &args) { return MsgForward(mb,sym,args.Header(),args.Count(),args.Atoms()); }
882  static bool MsgForward(MsgBundle *mb,const char *sym,const AtomAnything &args) { return MsgForward(mb,MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
883  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,int argc,const t_atom *argv) { return MsgForward(mb,sym,sym_list,argc,argv); }
884  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomList &args) { return MsgForward(mb,sym,args.Count(),args.Atoms()); }
885  static bool MsgForward(MsgBundle *mb,const char *sym,const AtomList &args) { return MsgForward(mb,MakeSymbol(sym),args.Count(),args.Atoms()); }
886 
888 
889 
890 
891 // --- thread stuff -----------------------------------------------
892 
897 #if FLEXT_SYS == FLEXT_SYS_PD
898  #if PD_MINOR_VERSION >= 38 || (PD_MINOR_VERSION >= 37 && defined(PD_DEVEL_VERSION))
899  static void Lock() { sys_lock(); }
900  static void Unlock() { sys_unlock(); }
901  #else
902  // no system locking for old PD versions
903  static void Lock() {}
904  static void Unlock() {}
905  #endif
906 #elif FLEXT_SYS == FLEXT_SYS_MAX
907  // Max 4.2 upwards!
908  static void Lock() { critical_enter(0); }
909  static void Unlock() { critical_exit(0); }
910 #else
911 #error
912 #endif
913 
915 
921 #ifdef FLEXT_THREADS
922  static bool IsThreadRegistered();
923 #else
924  static bool IsThreadRegistered() { return false; }
925 #endif
926 
927 #ifdef FLEXT_THREADS
928 
930 # if FLEXT_THREADS == FLEXT_THR_MP
931  typedef MPTaskID thrid_t;
932 # elif FLEXT_THREADS == FLEXT_THR_POSIX
933  typedef pthread_t thrid_t;
934 # elif FLEXT_THREADS == FLEXT_THR_WIN32
935  typedef DWORD thrid_t;
936 # else
937 # error Threading model not supported
938 # endif
939 
942  static thrid_t GetThreadId() {
943 #if FLEXT_THREADS == FLEXT_THR_POSIX
944  return pthread_self();
945 #elif FLEXT_THREADS == FLEXT_THR_MP
946  return MPCurrentTaskID();
947 #elif FLEXT_THREADS == FLEXT_THR_WIN32
948  return GetCurrentThreadId();
949 #else
950 #error
951 #endif
952  }
953 
956  static thrid_t GetSysThreadId() { return thrid; }
957 
959  static bool ShouldExit();
960 
962  static bool IsThread(thrid_t t,thrid_t ref = GetThreadId()) {
963 #if FLEXT_THREADS == FLEXT_THR_POSIX
964  return pthread_equal(ref,t) != 0;
965 #else
966  return ref == t;
967 #endif
968  }
969 
970 
974  class FLEXT_SHARE thr_params:
975  public flext_root
976  {
977  public:
978  thr_params(int n = 1): cl(NULL),var(new _data[n]) {}
979  ~thr_params() { delete[] var; }
980 
981  void set_any(const t_symbol *s,int argc,const t_atom *argv) { var[0]._any = new AtomAnything(s,argc,argv); }
982  void set_list(int argc,const t_atom *argv) { var[0]._list = new AtomList(argc,argv); }
983 
985  union _data {
986  bool _bool;
987  float _float;
988  int _int;
989  t_symptr _t_symptr;
990  AtomAnything *_any;
991  AtomList *_list;
992  void *_ext;
993  } *var;
994  };
995 
996 protected:
997 
998  static thrid_t thrhelpid;
999  static thrid_t thrmsgid;
1000  static void ThrHelper(void *);
1001 
1003  static thrid_t thrid; // the system thread
1004 
1005 private:
1006  static bool StartHelper(); // used in flext::Setup()
1007 
1008 public:
1009 
1013  static void ThrYield() {
1014 #if FLEXT_THREADS == FLEXT_THR_POSIX
1015  // for a preemptive system this should do nothing
1016  sched_yield();
1017 #elif FLEXT_THREADS == FLEXT_THR_MP
1018  MPYield();
1019 #elif FLEXT_THREADS == FLEXT_THR_WIN32
1020  SwitchToThread();
1021 #else
1022 #error
1023 #endif
1024  }
1025 
1028  static bool IsThreadPreemptive(thrid_t t = GetThreadId()) {
1029 #if FLEXT_THREADS == FLEXT_THR_POSIX || FLEXT_THREADS == FLEXT_THR_WIN32
1030  return true;
1031 #elif FLEXT_THREADS == FLEXT_THR_MP
1032  return MPTaskIsPreemptive(t);
1033 #else
1034 #error
1035 #endif
1036  }
1037 
1038 
1041  static bool RelPriority(int dp,thrid_t ref = GetSysThreadId(),thrid_t thr = GetThreadId());
1042 
1045  static int GetPriority(thrid_t thr = GetThreadId());
1046 
1049  static bool SetPriority(int p,thrid_t thr = GetThreadId());
1050 
1054  class FLEXT_SHARE ThrMutex:
1055  public flext_root
1056 #if FLEXT_THREADS == FLEXT_THR_POSIX
1057  {
1058  public:
1060  ThrMutex() { pthread_mutex_init(&mutex,NULL); }
1062  ~ThrMutex() { pthread_mutex_destroy(&mutex); }
1063 
1065  bool Lock() { return pthread_mutex_lock(&mutex) == 0; }
1069 // bool WaitForLock(double tm) { return pthread_mutex_lock(&mutex) == 0; }
1071  bool TryLock() { return pthread_mutex_trylock(&mutex) == 0; }
1073  bool Unlock() { return pthread_mutex_unlock(&mutex) == 0; }
1074 
1075  protected:
1076  pthread_mutex_t mutex;
1077 // int cnt;
1078  };
1079 #elif FLEXT_THREADS == FLEXT_THR_WIN32
1080  {
1081  public:
1083  ThrMutex() { ::InitializeCriticalSection(&mutex); }
1085  ~ThrMutex() { ::DeleteCriticalSection(&mutex); }
1086 
1088  bool Lock() { ::EnterCriticalSection(&mutex); return true; }
1092 // bool WaitForLock(double tm) { return pthread_mutex_lock(&mutex) == 0; }
1094  bool TryLock() { return ::TryEnterCriticalSection(&mutex) != 0; }
1096  bool Unlock() { ::LeaveCriticalSection(&mutex); return true; }
1097 
1098  protected:
1099  CRITICAL_SECTION mutex;
1100  };
1101 #elif FLEXT_THREADS == FLEXT_THR_MP
1102  {
1103  public:
1105  ThrMutex() { MPCreateCriticalRegion(&crit); }
1107  ~ThrMutex() { MPDeleteCriticalRegion(crit); }
1108 
1110  bool Lock() { return MPEnterCriticalRegion(crit,kDurationForever) == noErr; }
1112 // bool WaitForLock(double tm) { return MPEnterCriticalRegion(crit,tm*kDurationMicrosecond*1.e6) == noErr; }
1114  bool TryLock() { return MPEnterCriticalRegion(crit,kDurationImmediate) == noErr; }
1116  bool Unlock() { return MPExitCriticalRegion(crit) == noErr; }
1117 
1118  protected:
1119  MPCriticalRegionID crit;
1120  };
1121 #else
1122 #error "Not implemented"
1123 #endif
1124 
1128  class FLEXT_SHARE ThrCond
1130  :public ThrMutex
1131  {
1132  public:
1134  ThrCond() { pthread_cond_init(&cond,NULL); }
1136  ~ThrCond() { pthread_cond_destroy(&cond); }
1137 
1139  bool Wait();
1140 
1147  bool TimedWait(double ftime);
1148 
1150  bool Signal() { return pthread_cond_signal(&cond) == 0; }
1151 
1152  protected:
1153  pthread_cond_t cond;
1154  };
1155 #elif FLEXT_THREADS == FLEXT_THR_WIN32
1156  {
1157  public:
1159  ThrCond() { cond = CreateEvent(NULL,FALSE,FALSE,NULL); }
1161  ~ThrCond() { CloseHandle(cond); }
1162 
1164  bool Wait() { return WaitForSingleObject(cond,INFINITE) == WAIT_OBJECT_0; }
1165 
1172  bool TimedWait(double ftime) { return WaitForSingleObject(cond,(LONG)(ftime*1000)) == WAIT_OBJECT_0; }
1173 
1175  bool Signal() { return SetEvent(cond) != 0; }
1176 
1177  protected:
1178  HANDLE cond;
1179  };
1180 #elif FLEXT_THREADS == FLEXT_THR_MP
1181  {
1182  public:
1184  ThrCond() { MPCreateEvent(&ev); }
1186  ~ThrCond() { MPDeleteEvent(ev); }
1187 
1189  bool Wait() { return MPWaitForEvent(ev,NULL,kDurationForever) == noErr; }
1190 
1194  bool TimedWait(double tm) { return MPWaitForEvent(ev,NULL,tm*kDurationMicrosecond*1.e6) == noErr; }
1195 
1197  bool Signal() { return MPSetEvent(ev,1) == noErr; } // one bit needs to be set at least
1198 
1199  protected:
1200  MPEventID ev;
1201  };
1202 #else
1203 #error "Not implemented"
1204 #endif
1205 
1206  protected:
1212  static bool PushThread();
1213 
1218  static void PopThread();
1219 
1220  public:
1226  static bool LaunchThread(void (*meth)(thr_params *p),thr_params *params = NULL);
1227 
1235  static bool StopThread(void (*meth)(thr_params *p),thr_params *params = NULL,bool wait = false);
1236 
1237 
1239  static void RegisterThread(thrid_t id = GetThreadId());
1240 
1242  static void UnregisterThread(thrid_t id = GetThreadId());
1243 
1244 #endif // FLEXT_THREADS
1245 
1247 
1248 
1249  public:
1250 // --- timer stuff -----------------------------------------------
1251 
1264  static double GetTime()
1265  {
1266  #if FLEXT_SYS == FLEXT_SYS_PD
1267  return clock_gettimesince(0)*0.001;
1268  #elif FLEXT_SYS == FLEXT_SYS_MAX
1269  double tm;
1270  clock_getftime(&tm);
1271  return tm*0.001;
1272  #else
1273  #error Not implemented
1274  #endif
1275  }
1276 
1280  static double GetTimeGrain()
1281  {
1282  #if FLEXT_SYS == FLEXT_SYS_PD
1283  return 0;
1284  #elif FLEXT_SYS == FLEXT_SYS_MAX
1285  return 0.001;
1286  #else
1287  #error Not implemented
1288  #endif
1289  }
1290 
1293  static double GetOSTime();
1294 
1299  static void Sleep(double s);
1300 
1304  class FLEXT_SHARE Timer:
1305  public flext_root
1306  {
1307  public:
1308  Timer(bool queued = false);
1309  virtual ~Timer();
1310 
1312  void SetCallback(void (*cb)(void *data)) { clss = NULL,cback = cb; }
1314  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; }
1315 
1317  bool Reset();
1319  bool At(double time,void *data = NULL,bool dopast = true);
1321  bool Delay(double time,void *data = NULL);
1323  bool Periodic(double time,void *data = NULL);
1325  bool Now(void *data = NULL) { return Delay(0,data); }
1326 
1328  virtual void Work();
1329 
1330  protected:
1331  static void callback(Timer *tmr);
1332 
1333 #if FLEXT_SYS == FLEXT_SYS_PD
1334  t_clock *clk;
1335 #elif FLEXT_SYS == FLEXT_SYS_MAX
1336  static void queuefun(Timer *tmr);
1337  t_clock *clk;
1338  t_qelem *qelem;
1339 #else
1340 #error Not implemented
1341 #endif
1342 
1343  const bool queued;
1344  void (*cback)(void *data);
1346  void *userdata;
1347  double period;
1348  };
1349 
1351 
1353  static bool InDSP() { return indsp; }
1354 
1355 // --- SIMD functionality -----------------------------------------------
1356 
1360  enum simd_type {
1361  simd_none = 0,
1362  simd_mmx = 0x01,
1363  simd_3dnow = 0x02,
1364  simd_sse = 0x04,
1365  simd_sse2 = 0x08,
1366  simd_altivec = 0x10
1367  };
1368 
1370  static unsigned long GetSIMDCapabilities();
1371 
1372 
1373  static void MulSamples(t_sample *dst,const t_sample *src,t_sample mul,int cnt);
1374  static void MulSamples(t_sample *dst,const t_sample *src,const t_sample *mul,int cnt);
1375  static void AddSamples(t_sample *dst,const t_sample *src,t_sample add,int cnt);
1376  static void AddSamples(t_sample *dst,const t_sample *src,const t_sample *add,int cnt);
1377  static void ScaleSamples(t_sample *dst,const t_sample *src,t_sample mul,t_sample add,int cnt);
1378  static void ScaleSamples(t_sample *dst,const t_sample *src,t_sample mul,const t_sample *add,int cnt);
1379  static void ScaleSamples(t_sample *dst,const t_sample *src,const t_sample *mul,const t_sample *add,int cnt);
1380 
1382 
1383 
1385 
1386 protected:
1387 #ifdef __MRC__
1388  friend class flext_obj;
1389 #endif
1390 
1391  static void Setup();
1392 
1393  static bool chktilde(const char *objname);
1394 
1395  static unsigned long simdcaps;
1396 
1397  static const t_symbol *sym_attributes;
1398  static const t_symbol *sym_methods;
1399 
1400 #if FLEXT_SYS == FLEXT_SYS_MAX
1401  static const t_symbol *sym_buffer;
1402  static const t_symbol *sym_size;
1403  static const t_symbol *sym_dirty;
1404 #endif
1405 
1407  static bool indsp;
1408 };
1409 
1410 
1411 // gcc doesn't like these to be included into the flext class (even if static)
1412 inline bool operator ==(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) == 0; }
1413 inline bool operator !=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) != 0; }
1414 inline bool operator <(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) < 0; }
1415 inline bool operator <=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) <= 0; }
1416 inline bool operator >(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) > 0; }
1417 inline bool operator >=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) >= 0; }
1418 
1420 
1421 #include "flpopns.h"
1422 
1423 #endif
Definition: flclass.h:60
#define FLEXT_THR_POSIX
Definition: flprefix.h:80
#define FLEXT_SHARE
Definition: flprefix.h:425
#define FLEXT_THREADS
Definition: flprefix.h:379
#define FLEXT_TEMPLATE
Definition: flprefix.h:462
Definitions to unite Max/MSP and PD notions.
#define FLEXT_ASSERT(b)
Definition: flstdc.h:316
t_symbol * t_symptr
Definition: flstdc.h:255
bool operator!=(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1413
bool operator==(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1412
bool operator>(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1416
bool operator<=(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1415
bool operator>=(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1417
bool operator<(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1414
#define DELTHROW
Definition: flsupport.h:132
#define NEWTHROW
Definition: flsupport.h:131
typedef FLEXT_TEMPINST(FLEXT_SHARE FLEXT_CLASSDEF(flext_root)) flext_root
FLEXT_TEMPLATE class FLEXT_SHARE FLEXT_CLASSDEF(flext_root)