call_stack.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. //
  2. // detail/call_stack.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot 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. #ifndef BOOST_ASIO_DETAIL_CALL_STACK_HPP
  11. #define BOOST_ASIO_DETAIL_CALL_STACK_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/noncopyable.hpp>
  17. #include <boost/asio/detail/tss_ptr.hpp>
  18. #include <boost/asio/detail/push_options.hpp>
  19. namespace boost {
  20. namespace asio {
  21. namespace detail {
  22. // Helper class to determine whether or not the current thread is inside an
  23. // invocation of io_context::run() for a specified io_context object.
  24. template <typename Key, typename Value = unsigned char>
  25. class call_stack
  26. {
  27. public:
  28. // Context class automatically pushes the key/value pair on to the stack.
  29. class context
  30. : private noncopyable
  31. {
  32. public:
  33. // Push the key on to the stack.
  34. explicit context(Key* k)
  35. : key_(k),
  36. next_(call_stack<Key, Value>::top_)
  37. {
  38. value_ = reinterpret_cast<unsigned char*>(this);
  39. call_stack<Key, Value>::top_ = this;
  40. }
  41. // Push the key/value pair on to the stack.
  42. context(Key* k, Value& v)
  43. : key_(k),
  44. value_(&v),
  45. next_(call_stack<Key, Value>::top_)
  46. {
  47. call_stack<Key, Value>::top_ = this;
  48. }
  49. // Pop the key/value pair from the stack.
  50. ~context()
  51. {
  52. call_stack<Key, Value>::top_ = next_;
  53. }
  54. // Find the next context with the same key.
  55. Value* next_by_key() const
  56. {
  57. context* elem = next_;
  58. while (elem)
  59. {
  60. if (elem->key_ == key_)
  61. return elem->value_;
  62. elem = elem->next_;
  63. }
  64. return 0;
  65. }
  66. private:
  67. friend class call_stack<Key, Value>;
  68. // The key associated with the context.
  69. Key* key_;
  70. // The value associated with the context.
  71. Value* value_;
  72. // The next element in the stack.
  73. context* next_;
  74. };
  75. friend class context;
  76. // Determine whether the specified owner is on the stack. Returns address of
  77. // key if present, 0 otherwise.
  78. static Value* contains(Key* k)
  79. {
  80. context* elem = top_;
  81. while (elem)
  82. {
  83. if (elem->key_ == k)
  84. return elem->value_;
  85. elem = elem->next_;
  86. }
  87. return 0;
  88. }
  89. // Obtain the value at the top of the stack.
  90. static Value* top()
  91. {
  92. context* elem = top_;
  93. return elem ? elem->value_ : 0;
  94. }
  95. private:
  96. // The top of the stack of calls for the current thread.
  97. static tss_ptr<context> top_;
  98. };
  99. template <typename Key, typename Value>
  100. tss_ptr<typename call_stack<Key, Value>::context>
  101. call_stack<Key, Value>::top_;
  102. } // namespace detail
  103. } // namespace asio
  104. } // namespace boost
  105. #include <boost/asio/detail/pop_options.hpp>
  106. #endif // BOOST_ASIO_DETAIL_CALL_STACK_HPP