FastExclusive.tlh 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. #pragma once
  2. #include <memory>
  3. #include <list>
  4. #include <vector>
  5. #include <deque>
  6. #include <map>
  7. #include <optional>
  8. #include <chrono>
  9. #include <algorithm>
  10. #include <condition_variable>
  11. //namespace UCT = ::Utility::Concurrent;
  12. namespace Utility
  13. {
  14. namespace Concurrent
  15. {
  16. enum class wait_result
  17. {
  18. enQuit = -2, // 收到 Quit 信号, list 状态未知
  19. enTimeOut = -1, // 等待超时, list 状态未知
  20. enEmpty = 0, // 收到通知, list 为空
  21. enOne = 1, // 收到通知, wait_pop 返回 value 有效, 返回后, list 为空
  22. enMore = 2, // 收到通知, wait_pop 返回 value 有效, 返回后, list 还有值
  23. // operator bool () const = delete;
  24. };
  25. }
  26. }
  27. namespace Utility
  28. {
  29. namespace Concurrent
  30. {
  31. //-----------------------------------------------------------------------------
  32. // ExclusiveBase
  33. //-----------------------------------------------------------------------------
  34. template <typename tItem, typename tContainer>
  35. class ExclusiveBase
  36. {
  37. protected:
  38. tContainer m_Chunk;
  39. mutable std::mutex m_Mutex;
  40. std::condition_variable m_Notify;
  41. bool m_bQuit = false;
  42. public:
  43. using container = typename tContainer;
  44. using reference = typename tContainer::reference;
  45. using const_reference = typename tContainer::const_reference;
  46. // using const_iterator = typename tContainer::const_iterator;
  47. public:
  48. ExclusiveBase () = default;
  49. ExclusiveBase (const ExclusiveBase &) = delete;
  50. ExclusiveBase (ExclusiveBase &&) = delete;
  51. virtual ~ExclusiveBase ()
  52. {
  53. clear ();
  54. }
  55. ExclusiveBase & operator = (const ExclusiveBase &) = delete;
  56. ExclusiveBase & operator = (ExclusiveBase &&) = delete;
  57. public:
  58. bool empty () const
  59. {
  60. std::lock_guard <std::mutex> lk (m_Mutex);
  61. return m_Chunk.empty ();
  62. }
  63. [[nodiscard]]
  64. size_t size () const
  65. {
  66. std::lock_guard <std::mutex> lk (m_Mutex);
  67. return m_Chunk.size ();
  68. }
  69. public:
  70. void quit ()
  71. {
  72. std::lock_guard <std::mutex> lk (m_Mutex);
  73. m_bQuit = true;
  74. m_Notify.notify_all ();
  75. }
  76. void clear ()
  77. {
  78. std::lock_guard <std::mutex> lk (m_Mutex);
  79. m_Chunk.clear ();
  80. }
  81. public: // 检查 m_bQuit ! 等待非空, 然后执行相应的 Action
  82. template <typename _Act, typename ... Args>
  83. wait_result wait (_Act _action, Args && ... args)
  84. {
  85. if (m_bQuit) return wait_result::enQuit;
  86. std::unique_lock <std::mutex> lk (m_Mutex);
  87. if (! m_Chunk.empty ())
  88. {
  89. _action (& m_Chunk, args...);
  90. return wait_result::enMore;
  91. }
  92. m_Notify.wait (lk, [ this ] { return (! m_Chunk.empty ()) || (m_bQuit); });
  93. if (m_bQuit) return wait_result::enQuit;
  94. if (m_Chunk.empty ()) return wait_result::enEmpty;
  95. _action (& m_Chunk, args...);
  96. return wait_result::enMore;
  97. }
  98. template <typename _Rep, typename _Period, typename _Act, typename ... Args>
  99. wait_result wait_for (const std::chrono::duration <_Rep, _Period> & _dur, _Act _action, Args && ... args)
  100. {
  101. if (m_bQuit) return wait_result::enQuit;
  102. std::unique_lock <std::mutex> lk (m_Mutex);
  103. if (! m_Chunk.empty ())
  104. {
  105. _action (& m_Chunk, args...);
  106. return wait_result::enMore;
  107. }
  108. {
  109. auto rc = m_Notify.wait_for (lk, _dur, [ this ] { return (! m_Chunk.empty ()) || (m_bQuit); });
  110. if (! rc) return wait_result::enTimeOut;
  111. }
  112. if (m_bQuit) return wait_result::enQuit;
  113. if (m_Chunk.empty ()) return wait_result::enEmpty;
  114. _action (& m_Chunk, args...);
  115. return wait_result::enMore;
  116. }
  117. wait_result wait ()
  118. {
  119. std::function <void (container *)> action = [ ] (auto *) { };
  120. auto rc = wait (action);
  121. return rc;
  122. }
  123. template <typename _Rep, typename _Period>
  124. wait_result wait_for (const std::chrono::duration <_Rep, _Period> & _dur)
  125. {
  126. std::function <void (container *)> action = [ ] (auto *) { };
  127. auto rc = wait_for (_dur, action);
  128. return rc;
  129. }
  130. public:
  131. void notify_all ()
  132. {
  133. m_Notify.notify_all ();
  134. }
  135. void notify_one ()
  136. {
  137. m_Notify.notify_one ();
  138. }
  139. public: // 入队
  140. size_t push (const tItem & value)
  141. {
  142. std::lock_guard <std::mutex> lk (m_Mutex);
  143. m_Chunk.push_back (value);
  144. auto sz = m_Chunk.size ();
  145. m_Notify.notify_one ();
  146. return sz;
  147. }
  148. size_t push (tItem && value)
  149. {
  150. std::lock_guard <std::mutex> lk (m_Mutex);
  151. m_Chunk.push_back (std::move (value));
  152. auto sz = m_Chunk.size ();
  153. m_Notify.notify_one ();
  154. return sz;
  155. }
  156. public: // 出队. 如队列为空则等待, 并且要检查 m_bQuit
  157. // 检查 m_bQuit
  158. wait_result wait_pop (tItem & value)
  159. {
  160. if (m_bQuit) return wait_result::enQuit;
  161. std::unique_lock <std::mutex> lk (m_Mutex);
  162. if (m_Chunk.empty ())
  163. m_Notify.wait (lk, [ this ] { return (! m_Chunk.empty ()) || (m_bQuit); });
  164. if (m_bQuit) return wait_result::enQuit;
  165. if (m_Chunk.empty ()) return wait_result::enEmpty;
  166. value = std::move (m_Chunk.front ());
  167. m_Chunk.pop_front ();
  168. if (m_Chunk.empty ()) return wait_result::enOne;
  169. return wait_result::enMore;
  170. }
  171. // 检查 m_bQuit
  172. template <typename _Rep, typename _Period>
  173. wait_result wait_pop (tItem & value, const std::chrono::duration <_Rep, _Period> & _dur)
  174. {
  175. if (m_bQuit) return wait_result::enQuit;
  176. std::unique_lock <std::mutex> lk (m_Mutex);
  177. if (m_Chunk.empty ())
  178. {
  179. auto rc = m_Notify.wait_for (lk, _dur, [ this ] { return (! m_Chunk.empty ()) || (m_bQuit); });
  180. if (! rc) return wait_result::enTimeOut;
  181. }
  182. if (m_bQuit) return wait_result::enQuit;
  183. if (m_Chunk.empty ()) return wait_result::enEmpty;
  184. value = std::move (m_Chunk.front ());
  185. m_Chunk.pop_front ();
  186. if (m_Chunk.empty ()) return wait_result::enOne;
  187. return wait_result::enMore;
  188. }
  189. public:
  190. // 不检查 m_bQuit
  191. bool try_pop (tItem & value)
  192. {
  193. std::unique_lock <std::mutex> lk (m_Mutex);
  194. if (m_Chunk.empty ()) return false;
  195. value = std::move (m_Chunk.front ());
  196. m_Chunk.pop_front ();
  197. return true;
  198. }
  199. [[nodiscard]]
  200. std::optional <tItem> try_pop ()
  201. {
  202. std::unique_lock <std::mutex> lk (m_Mutex);
  203. if (m_Chunk.empty ()) return std::nullopt;
  204. std::optional <tItem> value = std::move (m_Chunk.front ());
  205. m_Chunk.pop_front ();
  206. return value;
  207. }
  208. // 不检查 m_bQuit
  209. int try_swap (tContainer & to)
  210. {
  211. std::unique_lock <std::mutex> lk (m_Mutex);
  212. m_Chunk.swap (to);
  213. return static_cast <int> (to.size ());
  214. }
  215. [[nodiscard]]
  216. tContainer try_swap ()
  217. {
  218. std::unique_lock <std::mutex> lk (m_Mutex);
  219. if (m_Chunk.empty ()) return tContainer ();
  220. tContainer to;
  221. m_Chunk.swap (to);
  222. return std::move (to);
  223. }
  224. // 不检查 m_bQuit
  225. int try_copy (tContainer & to)
  226. {
  227. std::unique_lock <std::mutex> lk (m_Mutex);
  228. to = m_Chunk;
  229. return static_cast <int> (to.size ());
  230. }
  231. [[nodiscard]]
  232. tContainer try_copy ()
  233. {
  234. std::unique_lock <std::mutex> lk (m_Mutex);
  235. if (m_Chunk.empty ()) return tContainer ();
  236. tContainer to = m_Chunk;
  237. return std::move (to);
  238. }
  239. public: // 不检查 m_bQuit
  240. // 把所有元素都弹出, 每个元素作为参数, 用指定的函数执行
  241. template <typename _Act, typename ... Args>
  242. int try_pop_all (_Act _onEach, Args && ... args)
  243. {
  244. std::unique_lock <std::mutex> lk (this->m_Mutex);
  245. int sz = static_cast <int> (this->m_Chunk.size ());
  246. if (sz <= 0) return 0;
  247. if (sz == 1)
  248. {
  249. auto Item = std::move (this->m_Chunk.front ());
  250. this->m_Chunk.clear ();
  251. lk.unlock ();
  252. _onEach (Item, args...);
  253. return 1;
  254. }
  255. container to;
  256. this->m_Chunk.swap (to);
  257. lk.unlock ();
  258. for (auto & Item : to)
  259. _onEach (Item, args...);
  260. return static_cast <int> (to.size ());
  261. }
  262. public: // 不检查 m_bQuit
  263. [[nodiscard]]
  264. bool find (const tItem & _val) const
  265. {
  266. std::unique_lock <std::mutex> lk (m_Mutex);
  267. if (m_Chunk.empty ()) return false;
  268. auto b = m_Chunk.begin ();
  269. auto e = m_Chunk.end ();
  270. auto iter = std::find (b, e, _val);
  271. return (iter != e);
  272. }
  273. // 用指定的谓词查找
  274. // 如果能找到, 返回 true
  275. // 如果未找到, 返回 false
  276. template <typename _Pr>
  277. [[nodiscard]]
  278. bool find_if (_Pr _Pred) const
  279. {
  280. std::unique_lock <std::mutex> lk (m_Mutex);
  281. if (m_Chunk.empty ()) return false;
  282. auto b = m_Chunk.begin ();
  283. auto e = m_Chunk.end ();
  284. auto iter = std::find_if (b, e, _Pred);
  285. return (iter != e);
  286. }
  287. public:
  288. // 锁定, 然后执行 Action
  289. template <typename _Act, typename ... Args>
  290. auto action (_Act _action, Args && ... args) -> decltype (_action (& m_Chunk, args...))
  291. {
  292. std::unique_lock <std::mutex> lk (m_Mutex);
  293. return _action (& m_Chunk, args...);
  294. }
  295. // 用指定的谓词查找
  296. // 如果能找到, 就执行 Action, 然后返回 true
  297. // 如果未找到, 不执行 Action, 直接返回 false
  298. template <typename _Pr, typename _Act, typename ... Args>
  299. bool action_if (_Pr _Pred, _Act _action, Args && ... args)
  300. {
  301. std::unique_lock <std::mutex> lk (m_Mutex);
  302. if (m_Chunk.empty ()) return false;
  303. auto b = m_Chunk.begin ();
  304. auto e = m_Chunk.end ();
  305. auto iter = std::find_if (b, e, _Pred);
  306. if (iter == e) return false;
  307. _action (& m_Chunk, iter, args...);
  308. return true;
  309. }
  310. // 对首项执行指定的函数/行为.
  311. // 如果为空, 返回 0; 否则返回 1
  312. template <typename _Act, typename ... Args>
  313. int on_front (_Act _action, Args && ... args)
  314. {
  315. std::unique_lock <std::mutex> lk (m_Mutex);
  316. if (m_Chunk.empty ()) return 0;
  317. _action (m_Chunk.front (), args...);
  318. return 1;
  319. }
  320. // 对末项行指定的函数/行为.
  321. // 如果为空, 返回 0; 否则返回 1
  322. template <typename _Act, typename ... Args>
  323. int on_back (_Act _action, Args && ... args)
  324. {
  325. std::unique_lock <std::mutex> lk (m_Mutex);
  326. if (m_Chunk.empty ()) return 0;
  327. _action (m_Chunk.back (), args...);
  328. return 1;
  329. }
  330. // 对所有的元素迭代
  331. // 返回: 元素数量
  332. template <typename _Act, typename ... Args>
  333. int for_each (_Act _onEach, Args && ... args)
  334. {
  335. std::unique_lock <std::mutex> lk (m_Mutex);
  336. if (m_Chunk.empty ()) return 0;
  337. for (auto & Item : m_Chunk)
  338. _onEach (Item, args...);
  339. return static_cast <int> (m_Chunk.size ());
  340. }
  341. // 对所有的元素迭代, 用谓词判断是否继续, 如果谓词返回 true 就继续迭代, 否则停止迭代
  342. // 返回: 执行了多少次 action
  343. template <typename _Pr>
  344. int for_each_if (_Pr _Pred)
  345. {
  346. std::unique_lock <std::mutex> lk (m_Mutex);
  347. if (m_Chunk.empty ()) return 0;
  348. int nCount = 0;
  349. for (auto & Item : m_Chunk)
  350. {
  351. if (!_Pred (Item))
  352. break;
  353. nCount ++;
  354. }
  355. return nCount;
  356. }
  357. // 对所有的元素迭代, 用谓词判断是否继续, 如果谓词返回 true 就继续迭代, 否则停止迭代
  358. // 返回: 执行了多少次 action
  359. template <typename _Pr, typename _Act, typename ... Args>
  360. int for_each_if (_Pr _Pred, _Act _onEach, Args && ... args)
  361. {
  362. std::unique_lock <std::mutex> lk (m_Mutex);
  363. if (m_Chunk.empty ()) return 0;
  364. int nCount = 0;
  365. for (auto & Item : m_Chunk)
  366. {
  367. if (!_Pred (Item))
  368. break;
  369. _onEach (Item, args...);
  370. nCount ++;
  371. }
  372. return nCount;
  373. }
  374. public:
  375. // 用指定的值查找
  376. // 如果能找到, 就删除, 然后返回 true
  377. // 如果未找到, 不删除, 直接返回 false
  378. bool erase (const tItem & _val)
  379. {
  380. std::unique_lock <std::mutex> lk (m_Mutex);
  381. if (m_Chunk.empty ()) return false;
  382. auto b = m_Chunk.begin ();
  383. auto e = m_Chunk.end ();
  384. auto iter = std::find (b, e, _val);
  385. if (iter == e) return false;
  386. m_Chunk.erase (iter);
  387. return true;
  388. }
  389. // 用指定的谓词查找
  390. // 如果能找到, 就删除, 然后返回 true
  391. // 如果未找到, 不删除, 直接返回 false
  392. template <typename _Pr>
  393. bool erase_if (_Pr _Pred)
  394. {
  395. std::unique_lock <std::mutex> lk (m_Mutex);
  396. if (m_Chunk.empty ()) return false;
  397. auto b = m_Chunk.begin ();
  398. auto e = m_Chunk.end ();
  399. auto iter = std::find_if (b, e, _Pred);
  400. if (iter == e) return false;
  401. m_Chunk.erase (iter);
  402. return true;
  403. }
  404. public:
  405. // 复制一个没有锁的列表
  406. auto clone () const -> tContainer
  407. {
  408. std::unique_lock <std::mutex> lk (m_Mutex);
  409. return tContainer (m_Chunk);
  410. }
  411. };
  412. template <class T>
  413. class ExclusiveList : public ExclusiveBase <T, std::list <T> >
  414. {
  415. public:
  416. template <class _Pr>
  417. void try_sort (_Pr _Pred)
  418. {
  419. std::unique_lock <std::mutex> lk (this->m_Mutex);
  420. if (this->m_Chunk.size () <= 1) return;
  421. this->m_Chunk.sort (_Pred);
  422. }
  423. };
  424. template <class T>
  425. class ExclusiveVector : public ExclusiveBase <T, std::vector <T> >
  426. {
  427. public:
  428. template <class _Pr>
  429. void try_sort (_Pr _Pred)
  430. {
  431. std::unique_lock <std::mutex> lk (this->m_Mutex);
  432. if (this->m_Chunk.size () <= 1) return;
  433. std::sort (this->m_Chunk.begin (), this->m_Chunk.end (), _Pred);
  434. }
  435. };
  436. template <class T>
  437. class ExclusiveDeque : public ExclusiveBase <T, std::deque <T> >
  438. {
  439. public:
  440. template <class _Pr>
  441. void try_sort (_Pr _Pred)
  442. {
  443. std::unique_lock <std::mutex> lk (this->m_Mutex);
  444. if (this->m_Chunk.size () <= 1) return;
  445. std::sort (this->m_Chunk.begin (), this->m_Chunk.end (), _Pred);
  446. }
  447. };
  448. // 模板别名
  449. template <typename T> using ExclusiveListOfPtr = ExclusiveList < std::unique_ptr <T> >;
  450. template <typename T> using ExclusiveVectorOfPtr = ExclusiveVector < std::unique_ptr <T> >;
  451. template <typename T> using ExclusiveDequeOfPtr = ExclusiveDeque < std::unique_ptr <T> >;
  452. // template <typename T> using ExclusiveQueue = ExclusiveBase < T, std::queue <T> >;
  453. // template <typename T> using ExclusiveQueueOfPtr = ExclusiveQueue < std::unique_ptr <T> >;
  454. }
  455. }
  456. namespace Utility
  457. {
  458. namespace Concurrent
  459. {
  460. //-----------------------------------------------------------------------------
  461. // ExclusiveOptional.tlh
  462. // 允许互斥访问 std::optional
  463. //-----------------------------------------------------------------------------
  464. template <typename T>
  465. class ExclusiveOptional
  466. {
  467. using value_type = T;
  468. using return_type = std::optional <T>;
  469. protected:
  470. std::optional <T> m_Option;
  471. mutable std::mutex m_Mutex;
  472. std::condition_variable m_Notify;
  473. bool m_bQuit = false;
  474. public:
  475. ExclusiveOptional () = default;
  476. private:
  477. // 禁止拷贝构造函数
  478. ExclusiveOptional (const ExclusiveOptional & h) = delete;
  479. // 禁止复制
  480. ExclusiveOptional & operator = (const ExclusiveOptional & h) = delete;
  481. public:
  482. void attach (T && object)
  483. {
  484. std::lock_guard <std::mutex> lk (m_Mutex);
  485. m_Option = std::move (object);
  486. m_Notify.notify_one ();
  487. }
  488. void attach (const T & object)
  489. {
  490. std::lock_guard <std::mutex> lk (m_Mutex);
  491. m_Option = object;
  492. m_Notify.notify_one ();
  493. }
  494. return_type detach ()
  495. {
  496. std::lock_guard <std::mutex> lk (m_Mutex);
  497. auto v = std::move (m_Option);
  498. m_Option.reset ();
  499. return v;
  500. }
  501. bool empty () const
  502. {
  503. std::lock_guard <std::mutex> lk (m_Mutex);
  504. return ! m_Option.has_value ();
  505. }
  506. void quit ()
  507. {
  508. m_bQuit = true;
  509. m_Notify.notify_all ();
  510. }
  511. void clear ()
  512. {
  513. std::lock_guard <std::mutex> lk (m_Mutex);
  514. m_Option.reset ();
  515. }
  516. public: // 检查 m_bQuit ! 等待非空, 然后执行相应的 Action
  517. template <typename _Act>
  518. wait_result wait (_Act _action)
  519. {
  520. return do_wait (_action, false);
  521. }
  522. template <typename _Rep, typename _Period, typename _Act>
  523. wait_result wait_for (const std::chrono::duration <_Rep, _Period> & _dur, _Act _action)
  524. {
  525. return do_wait_for (_dur, _action, false);
  526. }
  527. template <typename _Act>
  528. wait_result wait_pop (_Act _action)
  529. {
  530. return do_wait (_action, true);
  531. }
  532. template <typename _Rep, typename _Period, typename _Act>
  533. wait_result wait_pop_for (const std::chrono::duration <_Rep, _Period> & _dur, _Act _action)
  534. {
  535. return do_wait_for (_action, true);
  536. }
  537. protected:
  538. template <typename _Act>
  539. wait_result do_wait (_Act _action, bool clearAfterAction = false)
  540. {
  541. if (m_bQuit) return wait_result::enQuit;
  542. std::unique_lock <std::mutex> lk (m_Mutex);
  543. if (m_Option)
  544. {
  545. _action (m_Option.value ());
  546. if (clearAfterAction)
  547. m_Option.reset ();
  548. return wait_result::enOne;
  549. }
  550. m_Notify.wait (lk, [ this ] { return (m_Option.has_value ()) || (m_bQuit); });
  551. if (m_bQuit) return wait_result::enQuit;
  552. if (! m_Option) return wait_result::enEmpty;
  553. _action (m_Option.value ());
  554. if (clearAfterAction)
  555. m_Option.reset ();
  556. return wait_result::enOne;
  557. }
  558. template <typename _Rep, typename _Period, typename _Act>
  559. wait_result do_wait_for (const std::chrono::duration <_Rep, _Period> & _dur, _Act _action, bool clearAfterAction = false)
  560. {
  561. if (m_bQuit) return wait_result::enQuit;
  562. std::unique_lock <std::mutex> lk (m_Mutex);
  563. if (m_Option)
  564. {
  565. _action (m_Option.value ());
  566. if (clearAfterAction)
  567. m_Option.reset ();
  568. return wait_result::enOne;
  569. }
  570. {
  571. auto rc = m_Notify.wait_for (lk, _dur, [ this ] { return (m_Option.has_value ()) || (m_bQuit); });
  572. if (! rc) return wait_result::enTimeOut;
  573. }
  574. if (m_bQuit) return wait_result::enQuit;
  575. if (! m_Option) return wait_result::enEmpty;
  576. _action (m_Option.value ());
  577. if (clearAfterAction)
  578. m_Option.reset ();
  579. return wait_result::enOne;
  580. }
  581. };
  582. }
  583. }