fork(1) download
  1. #include <functional>
  2. #include <type_traits>
  3. #include <utility>
  4. #include <memory>
  5.  
  6. template <std::size_t... Is>
  7. struct indices {};
  8.  
  9. template <std::size_t N, std::size_t... Is>
  10. struct build_indices
  11. : build_indices<N - 1, N - 1, Is...> {};
  12.  
  13. template <std::size_t... Is>
  14. struct build_indices<0, Is...> : indices<Is...>{};
  15.  
  16. template<int I> struct placeholder{};
  17.  
  18. namespace std{
  19. template<int I>
  20. struct is_placeholder< ::placeholder<I>> : std::integral_constant<int, I>{};
  21. } // std::
  22.  
  23. namespace detail{
  24. template<std::size_t... Is, class F, class... Args>
  25. auto easy_bind(indices<Is...>, F const& f, Args&&... args)
  26. -> decltype(std::bind(f, std::forward<Args>(args)..., placeholder<1 + Is>{}...))
  27. {
  28. return std::bind(f, std::forward<Args>(args)..., placeholder<1 + Is>{}...);
  29. }
  30. } // detail::
  31.  
  32. template<class F, class... FArgs, class... Args>
  33. auto easy_bind(F const& f, Args&&... args)
  34. -> decltype(detail::easy_bind(build_indices<sizeof...(FArgs)-sizeof...(Args)>{}, f, std::forward<Args>(args)...))
  35. {
  36. return detail::easy_bind(build_indices<sizeof...(FArgs)-sizeof...(Args)>{}, f, std::forward<Args>(args)...);
  37. }
  38.  
  39. /*
  40. * Event
  41. *
  42. * Event()
  43. * ~Event()
  44. * // don't destroy an event while executing it
  45. *
  46. * void clear()
  47. * void reverse()
  48. *
  49. * Event::id reg(function, args...)
  50.  
  51. * Event::id->enable = true|false;
  52. * Event::id->unreg();
  53. * Event::id->replace(function, args...)
  54. *
  55. * void exec()
  56. * - runs all functions on Event
  57. */
  58.  
  59. template<typename... Params>
  60. class Event
  61. {
  62. struct Node;
  63.  
  64. public:
  65. /*
  66.   * Types
  67.   */
  68. typedef Node* id;
  69.  
  70. private:
  71.  
  72. /*
  73.   * Structures
  74.   */
  75. struct Node
  76. {
  77. std::function<void(Params...)> dat;
  78. bool enable;
  79. bool destroy;
  80. Node* next;
  81. Node* prev;
  82. Event* event;
  83.  
  84. inline void unreg()
  85. {
  86. destroy = true;
  87. } //unreg
  88.  
  89. template<class T, class... Args>
  90. void replace(T&& func, Args&&... args)
  91. {
  92. dat = easy_bindEx<T, Params..., Args...>(func, args...);
  93. } //replace
  94. }; //Node
  95.  
  96. /*
  97.   * Fields
  98.   */
  99. Node* first;
  100. Node* last;
  101.  
  102. bool reversed;
  103.  
  104. void unreg(id eventId)
  105. {
  106. if (eventId->next)
  107. {
  108. eventId->next->prev = eventId->prev;
  109. } //if
  110. else
  111. {
  112. last = eventId->prev;
  113. } //else
  114. if (eventId->prev)
  115. {
  116. eventId->prev->next = eventId->next;
  117. }
  118. else
  119. {
  120. first = eventId->next;
  121. } //else
  122. } //unreg
  123.  
  124. public:
  125. /*
  126.   * Constructors
  127.   */
  128. Event()
  129. {
  130. first = NULL;
  131. last = NULL;
  132.  
  133. reversed = false;
  134. } //Event
  135.  
  136. ~Event()
  137. {
  138. Node* next;
  139.  
  140. while (first)
  141. {
  142. next = first->next;
  143. delete first;
  144. first = next;
  145. } //while
  146.  
  147. last = NULL;
  148. } //~Event
  149.  
  150. /*
  151.   * Data Manipulation Operations
  152.   */
  153. template<class T, class... Args>
  154. id reg(T&& func, Args&&... args)
  155. {
  156. Node* node = new Node();
  157. node->dat = easy_bindEx<T, Params..., Args...>(func, args...);
  158. node->event = this;
  159. node->enable = true;
  160. node->destroy = false;
  161.  
  162. if (reversed)
  163. {
  164. node->prev = NULL;
  165. node->next = first;
  166.  
  167. if (first == NULL)
  168. {
  169. last = node;
  170. } //if
  171. else
  172. {
  173. first->prev = node;
  174. } //else
  175.  
  176. first = node;
  177. } //if
  178. else
  179. {
  180. node->next = NULL;
  181. node->prev = last;
  182.  
  183. if (last == NULL)
  184. {
  185. first = node;
  186. } //if
  187. else
  188. {
  189. last->next = node;
  190. } //else
  191.  
  192. last = node;
  193. } //else
  194.  
  195. return node;
  196. } //reg
  197.  
  198. /*
  199.   template<class... P, class... Args>
  200.   id regEvent(Event<P...>& event, Args&&... args)
  201.   {
  202.   easy_bind(std::function<void(Event<P...>&, P...)>([](Event<P...>& event, Args&&... args, Params&&... params) { event.exec(forward<Args>(args)..., forward<Params>(params)...);}), event, args...);
  203.   return NULL;
  204.   //return reg(easy_bind(std::function<void(Event<P...>&, P...)>([](Event<P...>& event, Args&&... args, Params&&... params) { event.exec(forward<Args>(args)..., forward<Params>(params)...);}), event, args...));
  205.   } //regEvent
  206.   */
  207.  
  208. void clear()
  209. {
  210. for (Node* node = first; node; node = node->next)
  211. {
  212. node->unreg();
  213. } //for
  214. } //clear
  215.  
  216. /*
  217.   * Structure Manipulation Operations
  218.   *
  219.   */
  220. void reverse()
  221. {
  222. if (first)
  223. {
  224. Node* node = first;
  225. Node* next = node->next;
  226.  
  227. while (next)
  228. {
  229. node->next = node->prev;
  230. node->prev = next;
  231. node = next;
  232. next = node->next;
  233. } //while
  234.  
  235. last->next = last->prev;
  236. last->prev = next;
  237.  
  238. node = last;
  239. last = first;
  240. first = node;
  241.  
  242. reversed = !reversed;
  243. } //if
  244. } //reverse
  245.  
  246. /*
  247.   * Execution Operations
  248.   */
  249. void exec(Params&&... args)
  250. {
  251. Node* node = first;
  252. Node* next;
  253.  
  254. while (node)
  255. {
  256. next = node->next;
  257.  
  258. if (node->destroy)
  259. {
  260. unreg(node);
  261. delete node;
  262. } //if
  263. else if (node->enable)
  264. {
  265. node->dat(args...);
  266. } //else if
  267.  
  268. node = next;
  269. } //while
  270. } //exec
  271. }; //Event
  272.  
  273. template<>
  274. class Event<void>
  275. {
  276. struct Node;
  277.  
  278. public:
  279. /*
  280.   * Types
  281.   */
  282. typedef Node* id;
  283.  
  284. private:
  285.  
  286. /*
  287.   * Structures
  288.   */
  289. struct Node
  290. {
  291. std::function<void()> dat;
  292. bool enable;
  293. bool destroy;
  294. Node* next;
  295. Node* prev;
  296. Event* event;
  297.  
  298. inline void unreg()
  299. {
  300. destroy = true;
  301. } //unreg
  302.  
  303. template<class T, class... Args>
  304. void replace(T&& func, Args&&... args)
  305. {
  306. dat = easy_bindEx<T, Args...>(func, args...);
  307. } //replace
  308. }; //Node
  309.  
  310. /*
  311.   * Fields
  312.   */
  313. Node* first;
  314. Node* last;
  315.  
  316. bool reversed;
  317.  
  318. void unreg(id eventId)
  319. {
  320. if (eventId->next)
  321. {
  322. eventId->next->prev = eventId->prev;
  323. } //if
  324. else
  325. {
  326. last = eventId->prev;
  327. } //else
  328. if (eventId->prev)
  329. {
  330. eventId->prev->next = eventId->next;
  331. }
  332. else
  333. {
  334. first = eventId->next;
  335. } //else
  336. } //unreg
  337.  
  338. public:
  339. /*
  340.   * Constructors
  341.   */
  342. Event()
  343. {
  344. first = NULL;
  345. last = NULL;
  346.  
  347. reversed = false;
  348. } //Event
  349.  
  350. ~Event()
  351. {
  352. Node* next;
  353.  
  354. while (first)
  355. {
  356. next = first->next;
  357. delete first;
  358. first = next;
  359. } //while
  360.  
  361. last = NULL;
  362. } //~Event
  363.  
  364. /*
  365.   * Data Manipulation Operations
  366.   */
  367. template<class T, class... Args>
  368. id reg(T&& func, Args&&... args)
  369. {
  370. Node* node = new Node();
  371. node->dat = easy_bindEx<T, Args...>(func, args...);
  372. node->event = this;
  373. node->enable = true;
  374. node->destroy = false;
  375.  
  376. if (reversed)
  377. {
  378. node->prev = NULL;
  379. node->next = first;
  380.  
  381. if (first == NULL)
  382. {
  383. last = node;
  384. } //if
  385. else
  386. {
  387. first->prev = node;
  388. } //else
  389.  
  390. first = node;
  391. } //if
  392. else
  393. {
  394. node->next = NULL;
  395. node->prev = last;
  396.  
  397. if (last == NULL)
  398. {
  399. first = node;
  400. } //if
  401. else
  402. {
  403. last->next = node;
  404. } //else
  405.  
  406. last = node;
  407. } //else
  408.  
  409. return node;
  410. } //reg
  411.  
  412. void clear()
  413. {
  414. for (Node* node = first; node; node = node->next)
  415. {
  416. node->unreg();
  417. } //for
  418. } //clear
  419.  
  420. /*
  421.   * Structure Manipulation Operations
  422.   *
  423.   */
  424. void reverse()
  425. {
  426. if (first)
  427. {
  428. Node* node = first;
  429. Node* next = node->next;
  430.  
  431. while (next)
  432. {
  433. node->next = node->prev;
  434. node->prev = next;
  435. node = next;
  436. next = node->next;
  437. } //while
  438.  
  439. last->next = last->prev;
  440. last->prev = next;
  441.  
  442. node = last;
  443. last = first;
  444. first = node;
  445.  
  446. reversed = !reversed;
  447. } //if
  448. } //reverse
  449.  
  450. /*
  451.   * Execution Operations
  452.   */
  453. void exec()
  454. {
  455. Node* node = first;
  456. Node* next;
  457.  
  458. while (node)
  459. {
  460. next = node->next;
  461.  
  462. if (node->destroy)
  463. {
  464. unreg(node);
  465. delete node;
  466. } //if
  467. else if (node->enable)
  468. {
  469. node->dat();
  470. } //else if
  471.  
  472. node = next;
  473. } //while
  474. } //exec
  475. }; //Event
  476.  
  477.  
  478. #include <functional>
  479. #include <vector>
  480.  
  481. void myF1(std::vector<int>& v, int, int)
  482. {
  483. v.push_back(v.back() + 1);
  484. }
  485.  
  486. void myF2(std::vector<int>& v, int, int)
  487. {
  488. v.push_back(v.back() + 1);
  489. }
  490.  
  491. void myF3(std::vector<int>& v, int, int)
  492. {
  493. v.push_back(v.back() + 1);
  494. }
  495.  
  496. void myF4(std::vector<int>& v, int, int)
  497. {
  498. v.push_back(v.back() + 1);
  499. }
  500.  
  501. void myF5(std::vector<int>& v, int, int)
  502. {
  503. v.push_back(v.back() + 1);
  504. }
  505.  
  506. void myF6(std::vector<int>& v, int, int)
  507. {
  508. v.push_back(v.back() + 1);
  509. }
  510.  
  511. void myF7(std::vector<int>& v, int, int)
  512. {
  513. v.push_back(v.back() + 1);
  514. }
  515.  
  516. void myF8(std::vector<int>& v, int, int)
  517. {
  518. v.push_back(v.back() + 1);
  519. }
  520.  
  521. void myF9(std::vector<int>& v, int, int)
  522. {
  523. v.push_back(v.back() + 1);
  524. }
  525.  
  526. void myF10(std::vector<int>& v, int, int)
  527. {
  528. v.push_back(v.back() + 1);
  529. }
  530.  
  531.  
  532. #include <ctime>
  533. #include <iostream>
  534. #include <chrono>
  535. #include <random>
  536.  
  537.  
  538. int main()
  539. {
  540. Event<std::vector<int>&, int, int> ev;
  541.  
  542. auto ev1P = ev.reg(myF1);
  543. auto ev2P = ev.reg(myF2);
  544. auto ev3P = ev.reg(myF3);
  545. auto ev4P = ev.reg(myF4);
  546. auto ev5P = ev.reg(myF5);
  547. auto ev6P = ev.reg(myF6);
  548. auto ev7P = ev.reg(myF7);
  549. auto ev8P = ev.reg(myF8);
  550. auto ev9P = ev.reg(myF9);
  551. auto ev10P = ev.reg(myF10);
  552.  
  553. std::vector<int> v;
  554. v.reserve(10000000);
  555.  
  556. std::vector<int> rNums;
  557. rNums.reserve(v.capacity());
  558.  
  559. std::mt19937 mTwist(std::chrono::high_resolution_clock::now().time_since_epoch().count());
  560. std::uniform_int_distribution<> uDist;
  561.  
  562. for(int i = 0; i < v.capacity(); ++i)
  563. {
  564. rNums.push_back(uDist(mTwist));
  565. }
  566.  
  567. auto now = std::chrono::high_resolution_clock::now();
  568.  
  569. for(int i = 0; i < 100000; ++i)
  570. {
  571. ev.exec(v, rNums[i], rNums[i]);
  572. }
  573.  
  574. auto after = std::chrono::high_resolution_clock::now();
  575.  
  576. std::cout << "calling 100,000 fires took " <<
  577. std::chrono::duration_cast<std::chrono::microseconds>(after - now).count() << " milliseconds\n";
  578.  
  579. std::cout << "size: " << v.size() << "\n";
  580.  
  581. std::cin.get();
  582. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp: In member function ‘void Event<Params>::Node::replace(T&&, Args&& ...)’:
prog.cpp:92:19: error: ‘easy_bindEx’ was not declared in this scope
             dat = easy_bindEx<T, Params..., Args...>(func, args...);
                   ^
prog.cpp:92:32: error: expected primary-expression before ‘,’ token
             dat = easy_bindEx<T, Params..., Args...>(func, args...);
                                ^
prog.cpp:92:40: error: expected primary-expression before ‘...’ token
             dat = easy_bindEx<T, Params..., Args...>(func, args...);
                                        ^
prog.cpp:92:40: error: expected ‘;’ before ‘...’ token
prog.cpp: In member function ‘Event<Params>::Node* Event<Params>::reg(T&&, Args&& ...)’:
prog.cpp:157:21: error: ‘easy_bindEx’ was not declared in this scope
         node->dat = easy_bindEx<T, Params..., Args...>(func, args...);
                     ^
prog.cpp:157:34: error: expected primary-expression before ‘,’ token
         node->dat = easy_bindEx<T, Params..., Args...>(func, args...);
                                  ^
prog.cpp:157:42: error: expected primary-expression before ‘...’ token
         node->dat = easy_bindEx<T, Params..., Args...>(func, args...);
                                          ^
prog.cpp:157:42: error: expected ‘;’ before ‘...’ token
prog.cpp: In member function ‘void Event<void>::Node::replace(T&&, Args&& ...)’:
prog.cpp:306:19: error: ‘easy_bindEx’ was not declared in this scope
             dat = easy_bindEx<T, Args...>(func, args...);
                   ^
prog.cpp:306:32: error: expected primary-expression before ‘,’ token
             dat = easy_bindEx<T, Args...>(func, args...);
                                ^
prog.cpp:306:38: error: expected primary-expression before ‘...’ token
             dat = easy_bindEx<T, Args...>(func, args...);
                                      ^
prog.cpp:306:38: error: expected ‘;’ before ‘...’ token
prog.cpp: In member function ‘Event<void>::Node* Event<void>::reg(T&&, Args&& ...)’:
prog.cpp:371:21: error: ‘easy_bindEx’ was not declared in this scope
         node->dat = easy_bindEx<T, Args...>(func, args...);
                     ^
prog.cpp:371:34: error: expected primary-expression before ‘,’ token
         node->dat = easy_bindEx<T, Args...>(func, args...);
                                  ^
prog.cpp:371:40: error: expected primary-expression before ‘...’ token
         node->dat = easy_bindEx<T, Args...>(func, args...);
                                        ^
prog.cpp:371:40: error: expected ‘;’ before ‘...’ token
prog.cpp: In function ‘int main()’:
prog.cpp:562:35: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i = 0; i < v.capacity(); ++i)
                                   ^
prog.cpp:571:38: error: cannot bind ‘__gnu_cxx::__alloc_traits<std::allocator<int> >::value_type {aka int}’ lvalue to ‘int&&’
         ev.exec(v, rNums[i], rNums[i]);
                                      ^
prog.cpp:249:10: error:   initializing argument 2 of ‘void Event<Params>::exec(Params&& ...) [with Params = {std::vector<int, std::allocator<int> >&, int, int}]’
     void exec(Params&&... args)
          ^
prog.cpp:542:10: warning: unused variable ‘ev1P’ [-Wunused-variable]
     auto ev1P = ev.reg(myF1);
          ^
prog.cpp:543:10: warning: unused variable ‘ev2P’ [-Wunused-variable]
     auto ev2P = ev.reg(myF2);
          ^
prog.cpp:544:10: warning: unused variable ‘ev3P’ [-Wunused-variable]
     auto ev3P = ev.reg(myF3);
          ^
prog.cpp:545:10: warning: unused variable ‘ev4P’ [-Wunused-variable]
     auto ev4P = ev.reg(myF4);
          ^
prog.cpp:546:10: warning: unused variable ‘ev5P’ [-Wunused-variable]
     auto ev5P = ev.reg(myF5);
          ^
prog.cpp:547:10: warning: unused variable ‘ev6P’ [-Wunused-variable]
     auto ev6P = ev.reg(myF6);
          ^
prog.cpp:548:10: warning: unused variable ‘ev7P’ [-Wunused-variable]
     auto ev7P = ev.reg(myF7);
          ^
prog.cpp:549:10: warning: unused variable ‘ev8P’ [-Wunused-variable]
     auto ev8P = ev.reg(myF8);
          ^
prog.cpp:550:10: warning: unused variable ‘ev9P’ [-Wunused-variable]
     auto ev9P = ev.reg(myF9);
          ^
prog.cpp:551:10: warning: unused variable ‘ev10P’ [-Wunused-variable]
     auto ev10P = ev.reg(myF10);
          ^
stdout
Standard output is empty