soft_mutex.hpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_WEBSOCKET_DETAIL_SOFT_MUTEX_HPP
  10. #define BOOST_BEAST_WEBSOCKET_DETAIL_SOFT_MUTEX_HPP
  11. #include <boost/assert.hpp>
  12. namespace boost {
  13. namespace beast {
  14. namespace websocket {
  15. namespace detail {
  16. // used to order reads, writes in websocket streams
  17. class soft_mutex
  18. {
  19. int id_ = 0;
  20. public:
  21. soft_mutex() = default;
  22. soft_mutex(soft_mutex const&) = delete;
  23. soft_mutex& operator=(soft_mutex const&) = delete;
  24. soft_mutex(soft_mutex&& other) noexcept
  25. : id_(boost::exchange(other.id_, 0))
  26. {
  27. }
  28. soft_mutex& operator=(soft_mutex&& other) noexcept
  29. {
  30. id_ = other.id_;
  31. other.id_ = 0;
  32. return *this;
  33. }
  34. // VFALCO I'm not too happy that this function is needed
  35. void
  36. reset()
  37. {
  38. id_ = 0;
  39. }
  40. bool
  41. is_locked() const noexcept
  42. {
  43. return id_ != 0;
  44. }
  45. template<class T>
  46. bool
  47. is_locked(T const*) const noexcept
  48. {
  49. return id_ == T::id;
  50. }
  51. template<class T>
  52. void
  53. lock(T const*)
  54. {
  55. BOOST_ASSERT(id_ == 0);
  56. id_ = T::id;
  57. }
  58. template<class T>
  59. void
  60. unlock(T const*)
  61. {
  62. BOOST_ASSERT(id_ == T::id);
  63. id_ = 0;
  64. }
  65. template<class T>
  66. bool
  67. try_lock(T const*)
  68. {
  69. // If this assert goes off it means you are attempting to
  70. // simultaneously initiate more than one of same asynchronous
  71. // operation, which is not allowed. For example, you must wait
  72. // for an async_read to complete before performing another
  73. // async_read.
  74. //
  75. BOOST_ASSERT(id_ != T::id);
  76. if(id_ != 0)
  77. return false;
  78. id_ = T::id;
  79. return true;
  80. }
  81. template<class T>
  82. bool
  83. try_unlock(T const*) noexcept
  84. {
  85. if(id_ != T::id)
  86. return false;
  87. id_ = 0;
  88. return true;
  89. }
  90. };
  91. } // detail
  92. } // websocket
  93. } // beast
  94. } // boost
  95. #endif