BsEvent.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #pragma once
  2. #include "CmPrerequisitesUtil.h"
  3. #include "CmModule.h"
  4. namespace BansheeEngine
  5. {
  6. /************************************************************************/
  7. /* EVENTS */
  8. /************************************************************************/
  9. class HEvent
  10. {
  11. public:
  12. HEvent(void* connection, void* event, void (*disconnectCallback) (void*, void*))
  13. :mConnection(connection), mEvent(event), mDisconnectCallback(disconnectCallback)
  14. { }
  15. void disconnect()
  16. {
  17. mDisconnectCallback(mConnection, mEvent);
  18. }
  19. private:
  20. void (*mDisconnectCallback) (void*, void*);
  21. void* mConnection;
  22. void* mEvent;
  23. };
  24. // 1 parameter
  25. template <class P0, class RetType>
  26. class Event1
  27. {
  28. struct ConnectionData
  29. {
  30. public:
  31. ConnectionData(std::function<RetType(P0)> func)
  32. :func(func)
  33. { }
  34. std::function<RetType(P0)> func;
  35. };
  36. public:
  37. ~Event1()
  38. {
  39. clear();
  40. }
  41. HEvent connect(std::function<RetType(P0)> func)
  42. {
  43. ConnectionData* connData = cm_new<ConnectionData>(func);
  44. {
  45. ScopedSpinLock lock;
  46. mConnections.push_back(connData);
  47. }
  48. return HEvent(connData, this, &Event1::disconnectCallback);
  49. }
  50. void operator() (P0 args)
  51. {
  52. SpinLock lock;
  53. // TODO - This isn't correct as iterator isn't locked while function is executing
  54. // Fix by:
  55. // - Using stack alloc allocate N std::function objects
  56. // - Create std::function objects using a stack allocator internally
  57. lock.lock();
  58. for(auto& connection : mConnections)
  59. {
  60. std::function<RetType(P0)> func = connection->func;
  61. lock.unlock();
  62. func(args);
  63. lock.lock();
  64. }
  65. lock.unlock();
  66. }
  67. void clear()
  68. {
  69. ScopedSpinLock lock;
  70. for(auto& connection : mConnections)
  71. {
  72. cm_delete(connection);
  73. }
  74. mConnections.clear();
  75. }
  76. bool empty()
  77. {
  78. ScopedSpinLock lock;
  79. return mConnections.size() == 0;
  80. }
  81. private:
  82. friend class EventHandle1;
  83. typename Vector<ConnectionData*>::type mConnections;
  84. static void disconnectCallback(void* connection, void* event)
  85. {
  86. Event1<P0, RetType>::ConnectionData* castConnection =
  87. reinterpret_cast<Event1<P0, RetType>::ConnectionData*>(connection);
  88. Event1<P0, RetType>* castEvent = reinterpret_cast<Event1<P0, RetType>*>(event);
  89. castEvent->disconnect(castConnection);
  90. }
  91. void disconnect(ConnectionData* connData)
  92. {
  93. ScopedSpinLock lock;
  94. for(auto& iter = mConnections.begin(); iter != mConnections.end(); ++iter)
  95. {
  96. if((*iter) == connData)
  97. {
  98. cm_delete(connData);
  99. mConnections.erase(iter);
  100. return;
  101. }
  102. }
  103. }
  104. };
  105. /************************************************************************/
  106. /* SPECIALIZATIONS */
  107. /* SO YOU MAY USE FUNCTION LIKE SYNTAX FOR DECLARING EVENT SIGNATURE */
  108. /************************************************************************/
  109. template <typename Signature>
  110. class Event;
  111. // 1 parameter
  112. template <class P0, class RetType>
  113. class Event<RetType(P0) > : public Event1 <P0, RetType>
  114. { };
  115. }