scheduler.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include <cstdint>
  2. #include <functional>
  3. #include <memory>
  4. #include <utility>
  5. #include <gtest/gtest.h>
  6. #include <entt/process/process.hpp>
  7. #include <entt/process/scheduler.hpp>
  8. class foo_process: public entt::process {
  9. void update(const delta_type, void *) override {
  10. on_update();
  11. }
  12. void aborted() override {
  13. on_aborted();
  14. }
  15. public:
  16. using allocator_type = entt::process::allocator_type;
  17. foo_process(const allocator_type &allocator, std::function<void()> upd, std::function<void()> abort)
  18. : entt::process{allocator},
  19. on_update{std::move(upd)},
  20. on_aborted{std::move(abort)} {}
  21. private:
  22. std::function<void()> on_update;
  23. std::function<void()> on_aborted;
  24. };
  25. class succeeded_process: public entt::process {
  26. void update(const delta_type, void *data) override {
  27. ++static_cast<std::pair<int, int> *>(data)->first;
  28. succeed();
  29. }
  30. public:
  31. using entt::process::process;
  32. };
  33. class failed_process: public entt::process {
  34. void update(const delta_type, void *data) override {
  35. ++static_cast<std::pair<int, int> *>(data)->second;
  36. fail();
  37. }
  38. public:
  39. using entt::process::process;
  40. };
  41. TEST(Scheduler, Functionalities) {
  42. entt::scheduler scheduler{};
  43. entt::scheduler other{std::move(scheduler)};
  44. scheduler = std::move(other);
  45. bool updated = false;
  46. bool aborted = false;
  47. ASSERT_EQ(scheduler.size(), 0u);
  48. ASSERT_TRUE(scheduler.empty());
  49. scheduler.attach<foo_process>([&updated]() { updated = true; }, [&aborted]() { aborted = true; });
  50. ASSERT_NE(scheduler.size(), 0u);
  51. ASSERT_FALSE(scheduler.empty());
  52. scheduler.update(0);
  53. scheduler.abort(true);
  54. ASSERT_TRUE(updated);
  55. ASSERT_TRUE(aborted);
  56. ASSERT_NE(scheduler.size(), 0u);
  57. ASSERT_FALSE(scheduler.empty());
  58. scheduler.clear();
  59. ASSERT_EQ(scheduler.size(), 0u);
  60. ASSERT_TRUE(scheduler.empty());
  61. }
  62. TEST(Scheduler, Swap) {
  63. entt::scheduler scheduler{};
  64. entt::scheduler other{};
  65. int counter{};
  66. scheduler.attach([&counter](entt::process &, std::uint32_t, void *) { ++counter; });
  67. ASSERT_EQ(scheduler.size(), 1u);
  68. ASSERT_EQ(other.size(), 0u);
  69. ASSERT_EQ(counter, 0);
  70. scheduler.update({});
  71. ASSERT_EQ(counter, 1);
  72. scheduler.swap(other);
  73. scheduler.update({});
  74. ASSERT_EQ(scheduler.size(), 0u);
  75. ASSERT_EQ(other.size(), 1u);
  76. ASSERT_EQ(counter, 1);
  77. other.update({});
  78. ASSERT_EQ(counter, 2);
  79. }
  80. TEST(Scheduler, SharedFromThis) {
  81. entt::scheduler scheduler{};
  82. auto &process = scheduler.attach<succeeded_process>();
  83. const auto &then = process.then<failed_process>();
  84. auto other = process.shared_from_this();
  85. ASSERT_TRUE(other);
  86. ASSERT_NE(&process, &then);
  87. ASSERT_EQ(&process, other.get());
  88. ASSERT_EQ(process.get_allocator(), scheduler.get_allocator());
  89. ASSERT_EQ(process.get_allocator(), other->get_allocator());
  90. ASSERT_EQ(then.get_allocator(), scheduler.get_allocator());
  91. }
  92. TEST(Scheduler, AttachThen) {
  93. entt::scheduler scheduler{};
  94. std::pair<int, int> counter{};
  95. // failing process with successor
  96. scheduler.attach<succeeded_process>()
  97. .then<succeeded_process>()
  98. .then<failed_process>()
  99. .then<succeeded_process>();
  100. // failing process without successor
  101. scheduler.attach<succeeded_process>()
  102. .then<succeeded_process>()
  103. .then<failed_process>();
  104. // non-failing process
  105. scheduler.attach<succeeded_process>()
  106. .then<succeeded_process>();
  107. while(!scheduler.empty()) {
  108. scheduler.update(0, &counter);
  109. }
  110. ASSERT_EQ(counter.first, 6u);
  111. ASSERT_EQ(counter.second, 2u);
  112. }
  113. TEST(Scheduler, Functor) {
  114. entt::scheduler scheduler{};
  115. bool first_functor = false;
  116. bool second_functor = false;
  117. scheduler
  118. .attach([&first_functor](entt::process &proc, std::uint32_t, void *) {
  119. ASSERT_FALSE(first_functor);
  120. first_functor = true;
  121. proc.succeed();
  122. })
  123. .then([&second_functor](entt::process &proc, std::uint32_t, void *) {
  124. ASSERT_FALSE(second_functor);
  125. second_functor = true;
  126. proc.fail();
  127. })
  128. .then([](entt::process &, std::uint32_t, void *) { FAIL(); });
  129. while(!scheduler.empty()) {
  130. scheduler.update(0);
  131. }
  132. ASSERT_TRUE(first_functor);
  133. ASSERT_TRUE(second_functor);
  134. ASSERT_TRUE(scheduler.empty());
  135. }
  136. TEST(Scheduler, SpawningProcess) {
  137. entt::scheduler scheduler{};
  138. std::pair<int, int> counter{};
  139. scheduler.attach([&scheduler](entt::process &proc, std::uint32_t, void *) {
  140. scheduler.attach<succeeded_process>().then<failed_process>();
  141. proc.succeed();
  142. });
  143. while(!scheduler.empty()) {
  144. scheduler.update(0, &counter);
  145. }
  146. ASSERT_EQ(counter.first, 1u);
  147. ASSERT_EQ(counter.second, 1u);
  148. }
  149. TEST(Scheduler, CustomAllocator) {
  150. const std::allocator<void> allocator{};
  151. entt::scheduler scheduler{allocator};
  152. ASSERT_EQ(scheduler.get_allocator(), allocator);
  153. ASSERT_FALSE(scheduler.get_allocator() != allocator);
  154. scheduler.attach([](entt::process &, std::uint32_t, void *) {});
  155. const decltype(scheduler) other{std::move(scheduler), allocator};
  156. ASSERT_EQ(other.size(), 1u);
  157. }