organizer.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #include <cstddef>
  2. #include <gtest/gtest.h>
  3. #include <entt/entity/organizer.hpp>
  4. #include <entt/entity/registry.hpp>
  5. void ro_int_rw_char_double(entt::view<entt::get_t<const int, char>>, double &) {}
  6. void ro_char_rw_int(entt::view<entt::get_t<int, const char>>) {}
  7. void ro_char_rw_double(entt::view<entt::get_t<const char>>, double &) {}
  8. void ro_int_double(entt::view<entt::get_t<const int>>, const double &) {}
  9. void sync_point(entt::registry &, entt::view<entt::get_t<const int>>) {}
  10. struct clazz {
  11. void ro_int_char_double(entt::view<entt::get_t<const int, const char>>, const double &) {}
  12. void rw_int(entt::view<entt::get_t<int>>) {}
  13. void rw_int_char(entt::view<entt::get_t<int, char>>) {}
  14. void rw_int_char_double(entt::view<entt::get_t<int, char>>, double &) {}
  15. static void ro_int_with_payload(const clazz &, entt::view<entt::get_t<const int>>) {}
  16. static void ro_char_with_payload(const clazz &, entt::view<entt::get_t<const char>>) {}
  17. static void ro_int_char_with_payload(clazz &, entt::view<entt::get_t<const int, const char>>) {}
  18. };
  19. void to_args_integrity(entt::view<entt::get_t<int>> view, std::size_t &value, entt::registry &registry) {
  20. value = view.size();
  21. }
  22. TEST(Organizer, EmplaceFreeFunction) {
  23. entt::organizer organizer;
  24. entt::registry registry;
  25. organizer.emplace<&ro_int_rw_char_double>("t1");
  26. organizer.emplace<&ro_char_rw_int>("t2");
  27. organizer.emplace<&ro_char_rw_double>("t3");
  28. organizer.emplace<&ro_int_double>("t4");
  29. const auto graph = organizer.graph();
  30. ASSERT_EQ(graph.size(), 4u);
  31. ASSERT_STREQ(graph[0u].name(), "t1");
  32. ASSERT_STREQ(graph[1u].name(), "t2");
  33. ASSERT_STREQ(graph[2u].name(), "t3");
  34. ASSERT_STREQ(graph[3u].name(), "t4");
  35. ASSERT_EQ(graph[0u].ro_count(), 1u);
  36. ASSERT_EQ(graph[1u].ro_count(), 1u);
  37. ASSERT_EQ(graph[2u].ro_count(), 1u);
  38. ASSERT_EQ(graph[3u].ro_count(), 2u);
  39. ASSERT_EQ(graph[0u].rw_count(), 2u);
  40. ASSERT_EQ(graph[1u].rw_count(), 1u);
  41. ASSERT_EQ(graph[2u].rw_count(), 1u);
  42. ASSERT_EQ(graph[3u].rw_count(), 0u);
  43. ASSERT_NE(graph[0u].info(), graph[1u].info());
  44. ASSERT_NE(graph[1u].info(), graph[2u].info());
  45. ASSERT_NE(graph[2u].info(), graph[3u].info());
  46. ASSERT_TRUE(graph[0u].top_level());
  47. ASSERT_FALSE(graph[1u].top_level());
  48. ASSERT_FALSE(graph[2u].top_level());
  49. ASSERT_FALSE(graph[3u].top_level());
  50. ASSERT_EQ(graph[0u].children().size(), 2u);
  51. ASSERT_EQ(graph[1u].children().size(), 1u);
  52. ASSERT_EQ(graph[2u].children().size(), 1u);
  53. ASSERT_EQ(graph[3u].children().size(), 0u);
  54. ASSERT_EQ(graph[0u].children()[0u], 1u);
  55. ASSERT_EQ(graph[0u].children()[1u], 2u);
  56. ASSERT_EQ(graph[1u].children()[0u], 3u);
  57. ASSERT_EQ(graph[2u].children()[0u], 3u);
  58. for(auto &&vertex: graph) {
  59. ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
  60. }
  61. organizer.clear();
  62. ASSERT_EQ(organizer.graph().size(), 0u);
  63. }
  64. TEST(Organizer, EmplaceMemberFunction) {
  65. entt::organizer organizer;
  66. entt::registry registry;
  67. clazz instance;
  68. organizer.emplace<&clazz::ro_int_char_double>(instance, "t1");
  69. organizer.emplace<&clazz::rw_int>(instance, "t2");
  70. organizer.emplace<&clazz::rw_int_char>(instance, "t3");
  71. organizer.emplace<&clazz::rw_int_char_double>(instance, "t4");
  72. const auto graph = organizer.graph();
  73. ASSERT_EQ(graph.size(), 4u);
  74. ASSERT_STREQ(graph[0u].name(), "t1");
  75. ASSERT_STREQ(graph[1u].name(), "t2");
  76. ASSERT_STREQ(graph[2u].name(), "t3");
  77. ASSERT_STREQ(graph[3u].name(), "t4");
  78. ASSERT_EQ(graph[0u].ro_count(), 3u);
  79. ASSERT_EQ(graph[1u].ro_count(), 0u);
  80. ASSERT_EQ(graph[2u].ro_count(), 0u);
  81. ASSERT_EQ(graph[3u].ro_count(), 0u);
  82. ASSERT_EQ(graph[0u].rw_count(), 0u);
  83. ASSERT_EQ(graph[1u].rw_count(), 1u);
  84. ASSERT_EQ(graph[2u].rw_count(), 2u);
  85. ASSERT_EQ(graph[3u].rw_count(), 3u);
  86. ASSERT_NE(graph[0u].info(), graph[1u].info());
  87. ASSERT_NE(graph[1u].info(), graph[2u].info());
  88. ASSERT_NE(graph[2u].info(), graph[3u].info());
  89. ASSERT_TRUE(graph[0u].top_level());
  90. ASSERT_FALSE(graph[1u].top_level());
  91. ASSERT_FALSE(graph[2u].top_level());
  92. ASSERT_FALSE(graph[3u].top_level());
  93. ASSERT_EQ(graph[0u].children().size(), 1u);
  94. ASSERT_EQ(graph[1u].children().size(), 1u);
  95. ASSERT_EQ(graph[2u].children().size(), 1u);
  96. ASSERT_EQ(graph[3u].children().size(), 0u);
  97. ASSERT_EQ(graph[0u].children()[0u], 1u);
  98. ASSERT_EQ(graph[1u].children()[0u], 2u);
  99. ASSERT_EQ(graph[2u].children()[0u], 3u);
  100. for(auto &&vertex: graph) {
  101. ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
  102. }
  103. organizer.clear();
  104. ASSERT_EQ(organizer.graph().size(), 0u);
  105. }
  106. TEST(Organizer, EmplaceFreeFunctionWithPayload) {
  107. entt::organizer organizer;
  108. entt::registry registry;
  109. clazz instance;
  110. organizer.emplace<&clazz::ro_int_char_double>(instance, "t1");
  111. organizer.emplace<&clazz::ro_int_with_payload>(instance, "t2");
  112. organizer.emplace<&clazz::ro_char_with_payload, const clazz>(instance, "t3");
  113. organizer.emplace<&clazz::ro_int_char_with_payload, clazz>(instance, "t4");
  114. organizer.emplace<&clazz::rw_int_char>(instance, "t5");
  115. const auto graph = organizer.graph();
  116. ASSERT_EQ(graph.size(), 5u);
  117. ASSERT_STREQ(graph[0u].name(), "t1");
  118. ASSERT_STREQ(graph[1u].name(), "t2");
  119. ASSERT_STREQ(graph[2u].name(), "t3");
  120. ASSERT_STREQ(graph[3u].name(), "t4");
  121. ASSERT_STREQ(graph[4u].name(), "t5");
  122. ASSERT_EQ(graph[0u].ro_count(), 3u);
  123. ASSERT_EQ(graph[1u].ro_count(), 1u);
  124. ASSERT_EQ(graph[2u].ro_count(), 2u);
  125. ASSERT_EQ(graph[3u].ro_count(), 2u);
  126. ASSERT_EQ(graph[4u].ro_count(), 0u);
  127. ASSERT_EQ(graph[0u].rw_count(), 0u);
  128. ASSERT_EQ(graph[1u].rw_count(), 0u);
  129. ASSERT_EQ(graph[2u].rw_count(), 0u);
  130. ASSERT_EQ(graph[3u].rw_count(), 1u);
  131. ASSERT_EQ(graph[4u].rw_count(), 2u);
  132. ASSERT_NE(graph[0u].info(), graph[1u].info());
  133. ASSERT_NE(graph[1u].info(), graph[2u].info());
  134. ASSERT_NE(graph[2u].info(), graph[3u].info());
  135. ASSERT_NE(graph[3u].info(), graph[4u].info());
  136. ASSERT_TRUE(graph[0u].top_level());
  137. ASSERT_TRUE(graph[1u].top_level());
  138. ASSERT_TRUE(graph[2u].top_level());
  139. ASSERT_FALSE(graph[3u].top_level());
  140. ASSERT_FALSE(graph[4u].top_level());
  141. ASSERT_EQ(graph[0u].children().size(), 1u);
  142. ASSERT_EQ(graph[1u].children().size(), 1u);
  143. ASSERT_EQ(graph[2u].children().size(), 1u);
  144. ASSERT_EQ(graph[3u].children().size(), 1u);
  145. ASSERT_EQ(graph[4u].children().size(), 0u);
  146. ASSERT_EQ(graph[0u].children()[0u], 4u);
  147. ASSERT_EQ(graph[1u].children()[0u], 4u);
  148. ASSERT_EQ(graph[2u].children()[0u], 3u);
  149. ASSERT_EQ(graph[3u].children()[0u], 4u);
  150. for(auto &&vertex: graph) {
  151. ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
  152. }
  153. organizer.clear();
  154. ASSERT_EQ(organizer.graph().size(), 0u);
  155. }
  156. TEST(Organizer, EmplaceDirectFunction) {
  157. entt::organizer organizer;
  158. entt::registry registry;
  159. clazz instance;
  160. // no aggressive comdat
  161. auto t1 = +[](const void *, entt::registry &reg) { reg.clear<int>(); };
  162. auto t2 = +[](const void *, entt::registry &reg) { reg.clear<char>(); };
  163. auto t3 = +[](const void *, entt::registry &reg) { reg.clear<double>(); };
  164. auto t4 = +[](const void *, entt::registry &reg) { reg.clear(); };
  165. organizer.emplace<int>(t1, nullptr, "t1");
  166. organizer.emplace<const int>(t2, &instance, "t2");
  167. organizer.emplace<const int, char>(t3, nullptr, "t3");
  168. organizer.emplace<int, char, double>(t4, &instance, "t4");
  169. const auto graph = organizer.graph();
  170. ASSERT_EQ(graph.size(), 4u);
  171. ASSERT_STREQ(graph[0u].name(), "t1");
  172. ASSERT_STREQ(graph[1u].name(), "t2");
  173. ASSERT_STREQ(graph[2u].name(), "t3");
  174. ASSERT_STREQ(graph[3u].name(), "t4");
  175. ASSERT_EQ(graph[0u].ro_count(), 0u);
  176. ASSERT_EQ(graph[1u].ro_count(), 1u);
  177. ASSERT_EQ(graph[2u].ro_count(), 1u);
  178. ASSERT_EQ(graph[3u].ro_count(), 0u);
  179. ASSERT_EQ(graph[0u].rw_count(), 1u);
  180. ASSERT_EQ(graph[1u].rw_count(), 0u);
  181. ASSERT_EQ(graph[2u].rw_count(), 1u);
  182. ASSERT_EQ(graph[3u].rw_count(), 3u);
  183. ASSERT_TRUE(graph[0u].callback() == t1);
  184. ASSERT_TRUE(graph[1u].callback() == t2);
  185. ASSERT_TRUE(graph[2u].callback() == t3);
  186. ASSERT_TRUE(graph[3u].callback() == t4);
  187. ASSERT_EQ(graph[0u].data(), nullptr);
  188. ASSERT_EQ(graph[1u].data(), &instance);
  189. ASSERT_EQ(graph[2u].data(), nullptr);
  190. ASSERT_EQ(graph[3u].data(), &instance);
  191. ASSERT_EQ(graph[0u].info(), entt::type_id<void>());
  192. ASSERT_EQ(graph[1u].info(), entt::type_id<void>());
  193. ASSERT_EQ(graph[2u].info(), entt::type_id<void>());
  194. ASSERT_EQ(graph[3u].info(), entt::type_id<void>());
  195. ASSERT_TRUE(graph[0u].top_level());
  196. ASSERT_FALSE(graph[1u].top_level());
  197. ASSERT_FALSE(graph[2u].top_level());
  198. ASSERT_FALSE(graph[3u].top_level());
  199. ASSERT_EQ(graph[0u].children().size(), 1u);
  200. ASSERT_EQ(graph[1u].children().size(), 1u);
  201. ASSERT_EQ(graph[2u].children().size(), 1u);
  202. ASSERT_EQ(graph[3u].children().size(), 0u);
  203. ASSERT_EQ(graph[0u].children()[0u], 1u);
  204. ASSERT_EQ(graph[1u].children()[0u], 2u);
  205. ASSERT_EQ(graph[2u].children()[0u], 3u);
  206. for(auto &&vertex: graph) {
  207. ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
  208. }
  209. organizer.clear();
  210. ASSERT_EQ(organizer.graph().size(), 0u);
  211. }
  212. TEST(Organizer, SyncPoint) {
  213. entt::organizer organizer;
  214. entt::registry registry;
  215. clazz instance;
  216. organizer.emplace<&ro_int_double>("before");
  217. organizer.emplace<&sync_point>("sync_1");
  218. organizer.emplace<&clazz::ro_int_char_double>(instance, "mid_1");
  219. organizer.emplace<&ro_int_double>("mid_2");
  220. organizer.emplace<&sync_point>("sync_2");
  221. organizer.emplace<&ro_int_double>("after");
  222. const auto graph = organizer.graph();
  223. ASSERT_EQ(graph.size(), 6u);
  224. ASSERT_STREQ(graph[0u].name(), "before");
  225. ASSERT_STREQ(graph[1u].name(), "sync_1");
  226. ASSERT_STREQ(graph[2u].name(), "mid_1");
  227. ASSERT_STREQ(graph[3u].name(), "mid_2");
  228. ASSERT_STREQ(graph[4u].name(), "sync_2");
  229. ASSERT_STREQ(graph[5u].name(), "after");
  230. ASSERT_TRUE(graph[0u].top_level());
  231. ASSERT_FALSE(graph[1u].top_level());
  232. ASSERT_FALSE(graph[2u].top_level());
  233. ASSERT_FALSE(graph[3u].top_level());
  234. ASSERT_FALSE(graph[4u].top_level());
  235. ASSERT_FALSE(graph[5u].top_level());
  236. ASSERT_EQ(graph[0u].children().size(), 1u);
  237. ASSERT_EQ(graph[1u].children().size(), 2u);
  238. ASSERT_EQ(graph[2u].children().size(), 1u);
  239. ASSERT_EQ(graph[3u].children().size(), 1u);
  240. ASSERT_EQ(graph[4u].children().size(), 1u);
  241. ASSERT_EQ(graph[5u].children().size(), 0u);
  242. ASSERT_EQ(graph[0u].children()[0u], 1u);
  243. ASSERT_EQ(graph[1u].children()[0u], 2u);
  244. ASSERT_EQ(graph[1u].children()[1u], 3u);
  245. ASSERT_EQ(graph[2u].children()[0u], 4u);
  246. ASSERT_EQ(graph[3u].children()[0u], 4u);
  247. ASSERT_EQ(graph[4u].children()[0u], 5u);
  248. for(auto &&vertex: graph) {
  249. ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
  250. }
  251. }
  252. TEST(Organizer, Override) {
  253. entt::organizer organizer;
  254. organizer.emplace<&ro_int_rw_char_double, const char, const double>("t1");
  255. organizer.emplace<&ro_char_rw_double, const double>("t2");
  256. organizer.emplace<&ro_int_double, double>("t3");
  257. const auto graph = organizer.graph();
  258. ASSERT_EQ(graph.size(), 3u);
  259. ASSERT_STREQ(graph[0u].name(), "t1");
  260. ASSERT_STREQ(graph[1u].name(), "t2");
  261. ASSERT_STREQ(graph[2u].name(), "t3");
  262. ASSERT_TRUE(graph[0u].top_level());
  263. ASSERT_TRUE(graph[1u].top_level());
  264. ASSERT_FALSE(graph[2u].top_level());
  265. ASSERT_EQ(graph[0u].children().size(), 1u);
  266. ASSERT_EQ(graph[1u].children().size(), 1u);
  267. ASSERT_EQ(graph[2u].children().size(), 0u);
  268. ASSERT_EQ(graph[0u].children()[0u], 2u);
  269. ASSERT_EQ(graph[1u].children()[0u], 2u);
  270. }
  271. TEST(Organizer, Prepare) {
  272. entt::organizer organizer;
  273. entt::registry registry;
  274. clazz instance;
  275. organizer.emplace<&ro_int_double>();
  276. organizer.emplace<&clazz::rw_int_char>(instance);
  277. const auto graph = organizer.graph();
  278. ASSERT_FALSE(registry.ctx().contains<int>());
  279. ASSERT_FALSE(registry.ctx().contains<char>());
  280. ASSERT_FALSE(registry.ctx().contains<double>());
  281. for(auto &&vertex: graph) {
  282. vertex.prepare(registry);
  283. }
  284. ASSERT_FALSE(registry.ctx().contains<int>());
  285. ASSERT_FALSE(registry.ctx().contains<char>());
  286. ASSERT_TRUE(registry.ctx().contains<double>());
  287. }
  288. TEST(Organizer, Dependencies) {
  289. entt::organizer organizer;
  290. clazz instance;
  291. organizer.emplace<&ro_int_double>();
  292. organizer.emplace<&clazz::rw_int_char>(instance);
  293. organizer.emplace<char, const double>(+[](const void *, entt::registry &) {});
  294. const auto graph = organizer.graph();
  295. const entt::type_info *buffer[5u]{};
  296. ASSERT_EQ(graph.size(), 3u);
  297. ASSERT_EQ(graph[0u].ro_count(), 2u);
  298. ASSERT_EQ(graph[0u].rw_count(), 0u);
  299. ASSERT_EQ(graph[0u].ro_dependency(buffer, 0u), 0u);
  300. ASSERT_EQ(graph[0u].rw_dependency(buffer, 2u), 0u);
  301. ASSERT_EQ(graph[0u].ro_dependency(buffer, 5u), 2u);
  302. ASSERT_EQ(*buffer[0u], entt::type_id<int>());
  303. ASSERT_EQ(*buffer[1u], entt::type_id<double>());
  304. ASSERT_EQ(graph[1u].ro_count(), 0u);
  305. ASSERT_EQ(graph[1u].rw_count(), 2u);
  306. ASSERT_EQ(graph[1u].ro_dependency(buffer, 2u), 0u);
  307. ASSERT_EQ(graph[1u].rw_dependency(buffer, 0u), 0u);
  308. ASSERT_EQ(graph[1u].rw_dependency(buffer, 5u), 2u);
  309. ASSERT_EQ(*buffer[0u], entt::type_id<int>());
  310. ASSERT_EQ(*buffer[1u], entt::type_id<char>());
  311. ASSERT_EQ(graph[2u].ro_count(), 1u);
  312. ASSERT_EQ(graph[2u].rw_count(), 1u);
  313. ASSERT_EQ(graph[2u].ro_dependency(buffer, 2u), 1u);
  314. ASSERT_EQ(graph[2u].rw_dependency(buffer, 0u), 0u);
  315. ASSERT_EQ(graph[2u].ro_dependency(buffer, 5u), 1u);
  316. ASSERT_EQ(*buffer[0u], entt::type_id<double>());
  317. ASSERT_EQ(graph[2u].rw_dependency(buffer, 5u), 1u);
  318. ASSERT_EQ(*buffer[0u], entt::type_id<char>());
  319. }
  320. TEST(Organizer, ToArgsIntegrity) {
  321. entt::organizer organizer;
  322. entt::registry registry;
  323. organizer.emplace<&to_args_integrity>();
  324. registry.ctx().emplace<std::size_t>(42u);
  325. auto graph = organizer.graph();
  326. graph[0u].callback()(graph[0u].data(), registry);
  327. ASSERT_EQ(registry.ctx().at<std::size_t>(), 0u);
  328. }