bbfunction.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. #ifndef BB_FUNCTION_H
  2. #define BB_FUNCTION_H
  3. #include "bbtypes.h"
  4. #include "bbdebug.h"
  5. namespace bbGC{
  6. void *malloc( size_t size );
  7. void free( void *p );
  8. }
  9. template<class T> class bbFunction;
  10. template<class R,class...A> struct bbFunction<R(A...)>{
  11. typedef R(*F)(A...);
  12. struct FunctionRep;
  13. struct SequenceRep;
  14. template<class C> struct MethodRep;
  15. static R castErr( A... ){
  16. puts( "Null Function Error" );
  17. exit( -1 );
  18. return R();
  19. }
  20. struct Rep{
  21. #ifdef BB_THREADS
  22. std::atomic_int refs{0};
  23. #else
  24. int refs{0};
  25. #endif
  26. virtual ~Rep(){
  27. }
  28. virtual R invoke( A... ){
  29. return R();
  30. }
  31. virtual bool equals( Rep *rep ){
  32. return rep==this;
  33. }
  34. virtual int compare( Rep *rhs ){
  35. if( this<rhs ) return -1;
  36. if( this>rhs ) return 1;
  37. return 0;
  38. }
  39. virtual Rep *remove( Rep *rep ){
  40. if( equals( rep ) ) return &_nullRep;
  41. return this;
  42. }
  43. virtual void gcMark(){
  44. }
  45. void *operator new( size_t size ){
  46. return bbGC::malloc( size );
  47. }
  48. void operator delete( void *p ){
  49. bbGC::free( p );
  50. }
  51. };
  52. struct FunctionRep : public Rep{
  53. F p;
  54. FunctionRep( F p ):p( p ){
  55. }
  56. virtual R invoke( A...a ){
  57. return p( a... );
  58. }
  59. virtual bool equals( Rep *rhs ){
  60. FunctionRep *t=dynamic_cast<FunctionRep*>( rhs );
  61. return t && p==t->p;
  62. }
  63. virtual int compare( Rep *rhs ){
  64. FunctionRep *t=dynamic_cast<FunctionRep*>( rhs );
  65. if( t && p==t->p ) return 0;
  66. return Rep::compare( rhs );
  67. }
  68. virtual F Cast(){
  69. return p;
  70. }
  71. };
  72. template<class C> struct MethodRep : public Rep{
  73. typedef R(C::*T)(A...);
  74. C *c;
  75. T p;
  76. MethodRep( C *c,T p ):c(c),p(p){
  77. }
  78. virtual R invoke( A...a ){
  79. return (c->*p)( a... );
  80. }
  81. virtual bool equals( Rep *rhs ){
  82. MethodRep *t=dynamic_cast<MethodRep*>( rhs );
  83. return t && c==t->c && p==t->p;
  84. }
  85. virtual int compare( Rep *rhs ){
  86. MethodRep *t=dynamic_cast<MethodRep*>( rhs );
  87. if( t && c==t->c && p==t->p ) return 0;
  88. return Rep::compare( rhs );
  89. }
  90. virtual void gcMark(){
  91. bbGCMark( c );
  92. }
  93. };
  94. template<class C> struct ExtMethodRep : public Rep{
  95. typedef R(*T)(C*,A...);
  96. C *c;
  97. T p;
  98. ExtMethodRep( C *c,T p ):c(c),p(p){
  99. }
  100. virtual R invoke( A...a ){
  101. return (*p)( c,a... );
  102. }
  103. virtual bool equals( Rep *rhs ){
  104. ExtMethodRep *t=dynamic_cast<ExtMethodRep*>( rhs );
  105. return t && c==t->c && p==t->p;
  106. }
  107. virtual int compare( Rep *rhs ){
  108. ExtMethodRep *t=dynamic_cast<ExtMethodRep*>( rhs );
  109. if( t && c==t->c && p==t->p ) return 0;
  110. return Rep::compare( rhs );
  111. }
  112. virtual void gcMark(){
  113. bbGCMark( c );
  114. }
  115. };
  116. struct SequenceRep : public Rep{
  117. bbFunction lhs,rhs;
  118. SequenceRep( const bbFunction &lhs,const bbFunction &rhs ):lhs( lhs ),rhs( rhs ){
  119. }
  120. virtual R invoke( A...a ){
  121. lhs( a... );
  122. return rhs( a... );
  123. }
  124. #ifdef BB_THREADS
  125. virtual Rep *remove( Rep *rep ){
  126. if( rep==this ) return &_nullRep;
  127. Rep *lhs2=lhs._rep.load()->remove( rep );
  128. Rep *rhs2=rhs._rep.load()->remove( rep );
  129. if( lhs2==lhs._rep && rhs2==rhs._rep ) return this;
  130. if( lhs2==&_nullRep ) return rhs2;
  131. if( rhs2==&_nullRep ) return lhs2;
  132. return new SequenceRep( lhs2,rhs2 );
  133. }
  134. virtual void gcMark(){
  135. lhs._rep.load()->gcMark();
  136. rhs._rep.load()->gcMark();
  137. }
  138. #else
  139. virtual Rep *remove( Rep *rep ){
  140. if( rep==this ) return &_nullRep;
  141. Rep *lhs2=lhs._rep->remove( rep );
  142. Rep *rhs2=rhs._rep->remove( rep );
  143. if( lhs2==lhs._rep && rhs2==rhs._rep ) return this;
  144. if( lhs2!=&_nullRep && rhs2 !=&_nullRep ) return new SequenceRep( lhs2,rhs2 );
  145. if( lhs2!=&_nullRep ) return lhs2;
  146. if( rhs2!=&_nullRep ) return rhs2;
  147. return &_nullRep;
  148. }
  149. virtual void gcMark(){
  150. lhs._rep->gcMark();
  151. rhs._rep->gcMark();
  152. }
  153. #endif
  154. };
  155. static Rep _nullRep;
  156. #ifdef BB_THREADS
  157. std::atomic<Rep*> _rep;
  158. void retain()const{
  159. ++_rep.load()->refs;
  160. }
  161. void release(){
  162. Rep *rep=_rep.load();
  163. if( !--rep->refs && rep!=&_nullRep ) delete rep;
  164. }
  165. #else
  166. Rep *_rep;
  167. void retain()const{
  168. ++_rep->refs;
  169. }
  170. void release(){
  171. if( !--_rep->refs && _rep!=&_nullRep ) delete _rep;
  172. }
  173. #endif
  174. bbFunction( Rep *rep ):_rep( rep ){
  175. retain();
  176. }
  177. public:
  178. bbFunction():_rep( &_nullRep ){
  179. }
  180. #ifdef BB_THREADS
  181. bbFunction( const bbFunction &p ):_rep( p._rep.load() ){
  182. retain();
  183. }
  184. #else
  185. bbFunction( const bbFunction &p ):_rep( p._rep ){
  186. retain();
  187. }
  188. #endif
  189. template<class C> bbFunction( C *c,typename MethodRep<C>::T p ):_rep( new MethodRep<C>(c,p) ){
  190. retain();
  191. }
  192. template<class C> bbFunction( C *c,typename ExtMethodRep<C>::T p ):_rep( new ExtMethodRep<C>(c,p) ){
  193. retain();
  194. }
  195. bbFunction( F p ):_rep( new FunctionRep( p ) ){
  196. retain();
  197. }
  198. ~bbFunction(){
  199. release();
  200. }
  201. #ifdef BB_THREADS
  202. bbFunction &operator=( const bbFunction &p ){
  203. Rep *oldrep=_rep,*newrep=p._rep;
  204. if( _rep.compare_exchange_strong( oldrep,newrep ) ){
  205. ++newrep->refs;
  206. if( !--oldrep->refs && oldrep!=&_nullRep ) delete oldrep;
  207. }
  208. return *this;
  209. }
  210. bbFunction operator+( const bbFunction &rhs )const{
  211. Rep *tlhs=_rep,*trhs=rhs._rep;
  212. if( tlhs==&_nullRep ) return trhs;
  213. if( trhs==&_nullRep ) return tlhs;
  214. return new SequenceRep( tlhs,trhs );
  215. }
  216. bbFunction operator-( const bbFunction &rhs )const{
  217. return _rep.load()->remove( rhs._rep );
  218. }
  219. bbBool operator==( const bbFunction &rhs )const{
  220. return _rep.load()->equals( rhs._rep );
  221. }
  222. bbBool operator!=( const bbFunction &rhs )const{
  223. return !_rep.load()->equals( rhs._rep );
  224. }
  225. operator bbBool()const{
  226. return _rep.load()==&_nullRep;
  227. }
  228. R operator()( A...a )const{
  229. return _rep.load()->invoke( a... );
  230. }
  231. operator F()const{ //cast to simple static function ptr
  232. FunctionRep *t=dynamic_cast<FunctionRep*>( _rep.load() );
  233. if( t ) return t->p;
  234. return castErr;
  235. }
  236. #else
  237. bbFunction &operator=( const bbFunction &p ){
  238. p.retain();
  239. release();
  240. _rep=p._rep;
  241. return *this;
  242. }
  243. bbFunction operator+( const bbFunction &rhs )const{
  244. if( _rep==&_nullRep ) return rhs;
  245. if( rhs._rep==&_nullRep ) return *this;
  246. return new SequenceRep( *this,rhs );
  247. }
  248. bbFunction operator-( const bbFunction &rhs )const{
  249. return _rep->remove( rhs._rep );
  250. }
  251. bbBool operator==( const bbFunction &rhs )const{
  252. return _rep->equals( rhs._rep );
  253. }
  254. bbBool operator!=( const bbFunction &rhs )const{
  255. return !_rep->equals( rhs._rep );
  256. }
  257. operator bbBool()const{
  258. return _rep==&_nullRep;
  259. }
  260. R operator()( A...a )const{
  261. return _rep->invoke( a... );
  262. }
  263. operator F()const{ //cast to simple static function ptr
  264. FunctionRep *t=dynamic_cast<FunctionRep*>( _rep );
  265. if( t ) return t->p;
  266. return castErr;
  267. }
  268. #endif
  269. bbFunction &operator+=( const bbFunction &rhs ){
  270. *this=*this+rhs;
  271. return *this;
  272. }
  273. bbFunction &operator-=( const bbFunction &rhs ){
  274. *this=*this-rhs;
  275. return *this;
  276. }
  277. };
  278. template<class R,class...A> typename bbFunction<R(A...)>::Rep bbFunction<R(A...)>::_nullRep;
  279. template<class C,class R,class...A> bbFunction<R(A...)> bbMethod( C *c,R(C::*p)(A...) ){
  280. return bbFunction<R(A...)>( c,p );
  281. }
  282. template<class C,class R,class...A> bbFunction<R(A...)> bbMethod( const bbGCVar<C> &c,R(C::*p)(A...) ){
  283. return bbFunction<R(A...)>( c.get(),p );
  284. }
  285. template<class C,class R,class...A> bbFunction<R(A...)> bbExtMethod( C *c,R(*p)(C*,A...) ){
  286. return bbFunction<R(A...)>( c,p );
  287. }
  288. template<class C,class R,class...A> bbFunction<R(A...)> bbExtMethod( const bbGCVar<C> &c,R(*p)(C*,A...) ){
  289. return bbFunction<R(A...)>( c.get(),p );
  290. }
  291. template<class R,class...A> bbFunction<R(A...)> bbMakefunc( R(*p)(A...) ){
  292. return bbFunction<R(A...)>( p );
  293. }
  294. #if BB_THREADS
  295. template<class R,class...A> void bbGCMark( const bbFunction<R(A...)> &t ){
  296. t._rep.load()->gcMark();
  297. }
  298. template<class R,class...A> int bbCompare( const bbFunction<R(A...)> &x,const bbFunction<R(A...)> &y ){
  299. return x._rep.load()->compare( y._rep.load() );
  300. }
  301. #else
  302. template<class R,class...A> void bbGCMark( const bbFunction<R(A...)> &t ){
  303. t._rep->gcMark();
  304. }
  305. template<class R,class...A> int bbCompare( const bbFunction<R(A...)> &x,const bbFunction<R(A...)> &y ){
  306. return x._rep->compare( y._rep );
  307. }
  308. #endif
  309. template<class R,class...A> bbString bbDBType( bbFunction<R(A...)> *p ){
  310. return bbDBType<R>()+"()";
  311. }
  312. template<class R,class...A> bbString bbDBValue( bbFunction<R(A...)> *p ){
  313. return "function?????";
  314. }
  315. #endif