object.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. *
  10. * The cost of dynamic (virtual calls) vs. static (CRTP) dispatch in C++
  11. * https://eli.thegreenplace.net/2013/12/05/the-cost-of-dynamic-virtual-calls-vs-static-crtp-dispatch-in-c/
  12. */
  13. #ifndef __ASIO2_OBJECT_HPP__
  14. #define __ASIO2_OBJECT_HPP__
  15. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #pragma once
  17. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  18. #include <memory>
  19. #include <asio2/base/error.hpp>
  20. namespace asio2
  21. {
  22. class object
  23. {
  24. public:
  25. };
  26. }
  27. namespace asio2::detail
  28. {
  29. /**
  30. * the lowest based class used fo CRTP
  31. * see : CRTP and multilevel inheritance
  32. * https://stackoverflow.com/questions/18174441/crtp-and-multilevel-inheritance
  33. */
  34. template<class derived_t, bool enable_shared_from_this = true>
  35. class object_t : public asio2::object, public std::enable_shared_from_this<derived_t>
  36. {
  37. protected:
  38. /**
  39. * @brief constructor
  40. */
  41. object_t() = default;
  42. /**
  43. * @brief destructor
  44. */
  45. ~object_t() = default;
  46. protected:
  47. /**
  48. * @brief obtain derived class object through CRTP mechanism
  49. */
  50. inline const derived_t & derived() const noexcept
  51. {
  52. return static_cast<const derived_t &>(*this);
  53. }
  54. /**
  55. * @brief obtain derived class object through CRTP mechanism
  56. */
  57. inline derived_t & derived() noexcept
  58. {
  59. return static_cast<derived_t &>(*this);
  60. }
  61. /**
  62. * @brief if the "derived_t" is created like a "shared_ptr", it will return
  63. * a not empty shared_ptr<derived_t>, othwise it will return a empty
  64. * shared_ptr<derived_t>.
  65. */
  66. inline std::shared_ptr<derived_t> selfptr() noexcept
  67. {
  68. // if the "derived_t" (maybe server,client,session...) is created like a
  69. // "shared_ptr", then here will return a not empty shared_ptr, otherwise
  70. // here will return a empty shared_ptr.
  71. // e.g : when the "derived_t" is udp_cast, and user has called post_condition_event,
  72. // and hold the "event_ptr" into another thread, and when the udp_cast is
  73. // soppted and destroyed, and user called the "event_ptr->notify()"
  74. // in the "another thread", if the udp_cast is created like a "shared_ptr",
  75. // then the event_ptr's member variable "derive_ptr_" will hold the shared_ptr
  76. // of udp_cast, this has no problem. but if the udp_cast is created as a
  77. // local variable not a "shared_ptr", then the event_ptr's member variable
  78. // "derive_ptr_" will hold a empty shared_ptr, then it will crash when
  79. // user called the "event_ptr->notify()" in the "another thread", beacuse
  80. // at this time, the "event_timer_io_" maybe destroyed already.
  81. return this->derived().weak_from_this().lock();
  82. }
  83. };
  84. template<class derived_t>
  85. class object_t<derived_t, false> : public asio2::object
  86. {
  87. protected:
  88. /**
  89. * @brief constructor
  90. */
  91. object_t() = default;
  92. /**
  93. * @brief destructor
  94. */
  95. ~object_t() = default;
  96. protected:
  97. /**
  98. * @brief obtain derived class object through CRTP mechanism
  99. */
  100. inline const derived_t & derived() const noexcept
  101. {
  102. return static_cast<const derived_t &>(*this);
  103. }
  104. /**
  105. * @brief obtain derived class object through CRTP mechanism
  106. */
  107. inline derived_t & derived() noexcept
  108. {
  109. return static_cast<derived_t &>(*this);
  110. }
  111. /**
  112. * @brief always return a empty shared_ptr<derived_t>.
  113. */
  114. inline std::shared_ptr<derived_t> selfptr() noexcept
  115. {
  116. return std::shared_ptr<derived_t>{};
  117. }
  118. };
  119. }
  120. #endif // !__ASIO2_OBJECT_HPP__