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