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 21namespace asio { 22namespace 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. 26template <typename Key, typename Value = unsigned char> 27class call_stack 28{ 29public: 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. 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. 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. 54 ~context() 55 { 56 call_stack<Key, Value>::top_ = next_; 57 } 58 59 // Find the next context with the same key. 60 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. 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. 102 static Value* top() 103 { 104 context* elem = top_; 105 return elem ? elem->value_ : 0; 106 } 107 108private: 109 // The top of the stack of calls for the current thread. 110 static tss_ptr<context> top_; 111}; 112 113template <typename Key, typename Value> 114tss_ptr<typename call_stack<Key, Value>::context> 115call_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