OVR_Delegates.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. /************************************************************************************
  2. Filename : OVR_Delegates.h
  3. Content : C++ Delegates
  4. Created : June 15, 2014
  5. Authors : Chris Taylor
  6. Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
  7. Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  8. you may not use the Oculus VR Rift SDK except in compliance with the License,
  9. which is provided at the time of installation or download, or which
  10. otherwise accompanies this software in either electronic or hard copy form.
  11. You may obtain a copy of the License at
  12. http://www.oculusvr.com/licenses/LICENSE-3.2
  13. Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  14. distributed under the License is distributed on an "AS IS" BASIS,
  15. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. See the License for the specific language governing permissions and
  17. limitations under the License.
  18. ************************************************************************************/
  19. /*
  20. Based on The Impossibly Fast C++ Delegates by Sergey Ryazanov from
  21. http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx (2005)
  22. */
  23. /*
  24. Usage:
  25. Declare a delegate with a void (int) signature, also known as a
  26. function that returns void and has one parameter that is an int:
  27. typedef Delegate1<void, int> MyDelegate;
  28. MyDelegate d;
  29. Point the delegate to a member function:
  30. d.SetMember<A, &A::TestFunctionA>(&a);
  31. d = MyDelegate::FromMember<A, &A::TestFunctionA>(&a);
  32. Point the delegate to a const member function:
  33. d.SetConstMember<C, &C::TestFunctionA>(&c);
  34. d = MyDelegate::FromConstMember<C, &C::TestFunctionA>(&c);
  35. Point the delegate to a free function:
  36. d.SetFree<&FreeFunctionX>();
  37. d = MyDelegate::FromFree<&FreeFunctionX>();
  38. Invoke the function via the delegate (works for all 3 cases):
  39. d(1000);
  40. By default the delegates are uninitialized.
  41. To clear an array of delegates quickly just zero the memory.
  42. This implementation is nicer than FastDelegates in my opinion
  43. because it is simple and easy to read. It is a little slower
  44. for virtual functions, but the size of the delegate is small,
  45. and it will only get better as compilers improve.
  46. */
  47. #ifndef OVR_Delegates_h
  48. #define OVR_Delegates_h
  49. #include "OVR_Types.h"
  50. namespace OVR {
  51. template <class ret_type>
  52. class Delegate0
  53. {
  54. typedef ret_type (*StubPointer)(void *);
  55. typedef Delegate0<ret_type> this_type;
  56. void *_object;
  57. StubPointer _stub;
  58. inline Delegate0(void *object, StubPointer stub)
  59. {
  60. _object = object;
  61. _stub = stub;
  62. }
  63. // Stubs
  64. template <ret_type (*F)()>
  65. static inline ret_type FreeStub(void * /*object*/)
  66. {
  67. return (F)();
  68. }
  69. template <class T, ret_type (T::*F)()>
  70. static inline ret_type MemberStub(void *object)
  71. {
  72. T *p = static_cast<T*>(object);
  73. return (p->*F)();
  74. }
  75. template <class T, ret_type (T::*F)() const>
  76. static inline ret_type ConstMemberStub(void *object)
  77. {
  78. T *p = static_cast<T*>(object);
  79. return (p->*F)();
  80. }
  81. public:
  82. inline Delegate0() : _object(0), _stub(0){}
  83. // Function invocation
  84. inline ret_type operator()() const
  85. {
  86. return (*_stub)(_object);
  87. }
  88. // Use stub pointer as a validity flag and equality checker
  89. inline bool operator==(const this_type &rhs) const
  90. {
  91. return _object == rhs._object && _stub == rhs._stub;
  92. }
  93. inline bool operator!=(const this_type &rhs) const
  94. {
  95. return _object != rhs._object || _stub != rhs._stub;
  96. }
  97. inline bool IsValid() const
  98. {
  99. return _stub != 0;
  100. }
  101. inline bool operator!() const
  102. {
  103. return _stub == 0;
  104. }
  105. inline void Invalidate()
  106. {
  107. _stub = 0;
  108. }
  109. // Delegate creation from a function
  110. template <ret_type (*F)()>
  111. static inline this_type FromFree()
  112. {
  113. return this_type(0, &FreeStub<F>);
  114. }
  115. template <class T, ret_type (T::*F)()>
  116. static inline this_type FromMember(T *object)
  117. {
  118. return this_type(object, &MemberStub<T, F>);
  119. }
  120. template <class T, ret_type (T::*F)() const>
  121. static inline this_type FromConstMember(T const *object)
  122. {
  123. return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>);
  124. }
  125. // In-place assignment to a different function
  126. template <ret_type (*F)()>
  127. inline void SetFree()
  128. {
  129. *this = FromFree<F>();
  130. }
  131. template <class T, ret_type (T::*F)()>
  132. inline void SetMember(T *object)
  133. {
  134. *this = FromMember<T, F>(object);
  135. }
  136. template <class T, ret_type (T::*F)() const>
  137. inline void SetConstMember(T const *object)
  138. {
  139. *this = FromConstMember<T, F>(object);
  140. }
  141. };
  142. template <class ret_type, class arg1_type>
  143. class Delegate1
  144. {
  145. typedef ret_type (*StubPointer)(void *, arg1_type);
  146. typedef Delegate1<ret_type, arg1_type> this_type;
  147. void *_object;
  148. StubPointer _stub;
  149. inline Delegate1(void *object, StubPointer stub)
  150. {
  151. _object = object;
  152. _stub = stub;
  153. }
  154. // Stubs
  155. template <ret_type (*F)(arg1_type)>
  156. static inline ret_type FreeStub(void * /*object*/, arg1_type a1)
  157. {
  158. return (F)(a1);
  159. }
  160. template <class T, ret_type (T::*F)(arg1_type)>
  161. static inline ret_type MemberStub(void *object, arg1_type a1)
  162. {
  163. T *p = static_cast<T*>(object);
  164. return (p->*F)(a1);
  165. }
  166. template <class T, ret_type (T::*F)(arg1_type) const>
  167. static inline ret_type ConstMemberStub(void *object, arg1_type a1)
  168. {
  169. T *p = static_cast<T*>(object);
  170. return (p->*F)(a1);
  171. }
  172. public:
  173. inline Delegate1() : _object(0), _stub(0){}
  174. // Function invocation
  175. inline ret_type operator()(arg1_type a1) const
  176. {
  177. return (*_stub)(_object, a1);
  178. }
  179. // Use stub pointer as a validity flag and equality checker
  180. inline bool operator==(const this_type &rhs) const
  181. {
  182. return _object == rhs._object && _stub == rhs._stub;
  183. }
  184. inline bool operator!=(const this_type &rhs) const
  185. {
  186. return _object != rhs._object || _stub != rhs._stub;
  187. }
  188. inline bool IsValid() const
  189. {
  190. return _stub != 0;
  191. }
  192. inline bool operator!() const
  193. {
  194. return _stub == 0;
  195. }
  196. inline void Invalidate()
  197. {
  198. _stub = 0;
  199. }
  200. // Delegate creation from a function
  201. template <ret_type (*F)(arg1_type)>
  202. static inline this_type FromFree()
  203. {
  204. return this_type(0, &FreeStub<F>);
  205. }
  206. template <class T, ret_type (T::*F)(arg1_type)>
  207. static inline this_type FromMember(T *object)
  208. {
  209. return this_type(object, &MemberStub<T, F>);
  210. }
  211. template <class T, ret_type (T::*F)(arg1_type) const>
  212. static inline this_type FromConstMember(T const *object)
  213. {
  214. return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>);
  215. }
  216. // In-place assignment to a different function
  217. template <ret_type (*F)(arg1_type)>
  218. inline void SetFree()
  219. {
  220. *this = FromFree<F>();
  221. }
  222. template <class T, ret_type (T::*F)(arg1_type)>
  223. inline void SetMember(T *object)
  224. {
  225. *this = FromMember<T, F>(object);
  226. }
  227. template <class T, ret_type (T::*F)(arg1_type) const>
  228. inline void SetConstMember(T const *object)
  229. {
  230. *this = FromConstMember<T, F>(object);
  231. }
  232. };
  233. template <class ret_type, class arg1_type, class arg2_type>
  234. class Delegate2
  235. {
  236. typedef ret_type (*StubPointer)(void *, arg1_type, arg2_type);
  237. typedef Delegate2<ret_type, arg1_type, arg2_type> this_type;
  238. void *_object;
  239. StubPointer _stub;
  240. inline Delegate2(void *object, StubPointer stub)
  241. {
  242. _object = object;
  243. _stub = stub;
  244. }
  245. // Stubs
  246. template <ret_type (*F)(arg1_type, arg2_type)>
  247. static inline ret_type FreeStub(void * /*object*/, arg1_type a1, arg2_type a2)
  248. {
  249. return (F)(a1, a2);
  250. }
  251. template <class T, ret_type (T::*F)(arg1_type, arg2_type)>
  252. static inline ret_type MemberStub(void *object, arg1_type a1, arg2_type a2)
  253. {
  254. T *p = static_cast<T*>(object);
  255. return (p->*F)(a1, a2);
  256. }
  257. template <class T, ret_type (T::*F)(arg1_type, arg2_type) const>
  258. static inline ret_type ConstMemberStub(void *object, arg1_type a1, arg2_type a2)
  259. {
  260. T *p = static_cast<T*>(object);
  261. return (p->*F)(a1, a2);
  262. }
  263. public:
  264. inline Delegate2() : _object(0), _stub(0){}
  265. // Function invocation
  266. inline ret_type operator()(arg1_type a1, arg2_type a2) const
  267. {
  268. return (*_stub)(_object, a1, a2);
  269. }
  270. // Use stub pointer as a validity flag and equality checker
  271. inline bool operator==(const this_type &rhs) const
  272. {
  273. return _object == rhs._object && _stub == rhs._stub;
  274. }
  275. inline bool operator!=(const this_type &rhs) const
  276. {
  277. return _object != rhs._object || _stub != rhs._stub;
  278. }
  279. inline bool IsValid() const
  280. {
  281. return _stub != 0;
  282. }
  283. inline bool operator!() const
  284. {
  285. return _stub == 0;
  286. }
  287. inline void Invalidate()
  288. {
  289. _stub = 0;
  290. }
  291. // Delegate creation from a function
  292. template <ret_type (*F)(arg1_type, arg2_type)>
  293. static inline this_type FromFree()
  294. {
  295. return this_type(0, &FreeStub<F>);
  296. }
  297. template <class T, ret_type (T::*F)(arg1_type, arg2_type)>
  298. static inline this_type FromMember(T *object)
  299. {
  300. return this_type(object, &MemberStub<T, F>);
  301. }
  302. template <class T, ret_type (T::*F)(arg1_type, arg2_type) const>
  303. static inline this_type FromConstMember(T const *object)
  304. {
  305. return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>);
  306. }
  307. // In-place assignment to a different function
  308. template <ret_type (*F)(arg1_type, arg2_type)>
  309. inline void SetFree()
  310. {
  311. *this = FromFree<F>();
  312. }
  313. template <class T, ret_type (T::*F)(arg1_type, arg2_type)>
  314. inline void SetMember(T *object)
  315. {
  316. *this = FromMember<T, F>(object);
  317. }
  318. template <class T, ret_type (T::*F)(arg1_type, arg2_type) const>
  319. inline void SetConstMember(T const *object)
  320. {
  321. *this = FromConstMember<T, F>(object);
  322. }
  323. };
  324. template <class ret_type, class arg1_type, class arg2_type, class arg3_type>
  325. class Delegate3
  326. {
  327. typedef ret_type (*StubPointer)(void *, arg1_type, arg2_type, arg3_type);
  328. typedef Delegate3<ret_type, arg1_type, arg2_type, arg3_type> this_type;
  329. void *_object;
  330. StubPointer _stub;
  331. inline Delegate3(void *object, StubPointer stub)
  332. {
  333. _object = object;
  334. _stub = stub;
  335. }
  336. // Stubs
  337. template <ret_type (*F)(arg1_type, arg2_type, arg3_type)>
  338. static inline ret_type FreeStub(void * /*object*/, arg1_type a1, arg2_type a2, arg3_type a3)
  339. {
  340. return (F)(a1, a2, a3);
  341. }
  342. template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)>
  343. static inline ret_type MemberStub(void *object, arg1_type a1, arg2_type a2, arg3_type a3)
  344. {
  345. T *p = static_cast<T*>(object);
  346. return (p->*F)(a1, a2, a3);
  347. }
  348. template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const>
  349. static inline ret_type ConstMemberStub(void *object, arg1_type a1, arg2_type a2, arg3_type a3)
  350. {
  351. T *p = static_cast<T*>(object);
  352. return (p->*F)(a1, a2, a3);
  353. }
  354. public:
  355. inline Delegate3() : _object(0), _stub(0){}
  356. // Function invocation
  357. inline ret_type operator()(arg1_type a1, arg2_type a2, arg3_type a3) const
  358. {
  359. return (*_stub)(_object, a1, a2, a3);
  360. }
  361. // Use stub pointer as a validity flag and equality checker
  362. inline bool operator==(const this_type &rhs) const
  363. {
  364. return _object == rhs._object && _stub == rhs._stub;
  365. }
  366. inline bool operator!=(const this_type &rhs) const
  367. {
  368. return _object != rhs._object || _stub != rhs._stub;
  369. }
  370. inline bool IsValid() const
  371. {
  372. return _stub != 0;
  373. }
  374. inline bool operator!() const
  375. {
  376. return _stub == 0;
  377. }
  378. inline void Invalidate()
  379. {
  380. _stub = 0;
  381. }
  382. // Delegate creation from a function
  383. template <ret_type (*F)(arg1_type, arg2_type, arg3_type)>
  384. static inline this_type FromFree()
  385. {
  386. return this_type(0, &FreeStub<F>);
  387. }
  388. template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)>
  389. static inline this_type FromMember(T *object)
  390. {
  391. return this_type(object, &MemberStub<T, F>);
  392. }
  393. template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const>
  394. static inline this_type FromConstMember(T const *object)
  395. {
  396. return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>);
  397. }
  398. // In-place assignment to a different function
  399. template <ret_type (*F)(arg1_type, arg2_type, arg3_type)>
  400. inline void SetFree()
  401. {
  402. *this = FromFree<F>();
  403. }
  404. template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)>
  405. inline void SetMember(T *object)
  406. {
  407. *this = FromMember<T, F>(object);
  408. }
  409. template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const>
  410. inline void SetConstMember(T const *object)
  411. {
  412. *this = FromConstMember<T, F>(object);
  413. }
  414. };
  415. // Add more here if needed, but keep in mind that a short, simple interface
  416. // is rewarded by making the delegates faster...
  417. } // namespace OVR
  418. #endif // OVR_Delegates_h