Chris@16: // Chris@16: // detail/call_stack.hpp Chris@16: // ~~~~~~~~~~~~~~~~~~~~~ Chris@16: // Chris@101: // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: Chris@16: #ifndef BOOST_ASIO_DETAIL_CALL_STACK_HPP Chris@16: #define BOOST_ASIO_DETAIL_CALL_STACK_HPP Chris@16: Chris@16: #if defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: # pragma once Chris@16: #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace asio { Chris@16: namespace detail { Chris@16: Chris@16: // Helper class to determine whether or not the current thread is inside an Chris@16: // invocation of io_service::run() for a specified io_service object. Chris@16: template Chris@16: class call_stack Chris@16: { Chris@16: public: Chris@16: // Context class automatically pushes the key/value pair on to the stack. Chris@16: class context Chris@16: : private noncopyable Chris@16: { Chris@16: public: Chris@16: // Push the key on to the stack. Chris@16: explicit context(Key* k) Chris@16: : key_(k), Chris@16: next_(call_stack::top_) Chris@16: { Chris@16: value_ = reinterpret_cast(this); Chris@16: call_stack::top_ = this; Chris@16: } Chris@16: Chris@16: // Push the key/value pair on to the stack. Chris@16: context(Key* k, Value& v) Chris@16: : key_(k), Chris@16: value_(&v), Chris@16: next_(call_stack::top_) Chris@16: { Chris@16: call_stack::top_ = this; Chris@16: } Chris@16: Chris@16: // Pop the key/value pair from the stack. Chris@16: ~context() Chris@16: { Chris@16: call_stack::top_ = next_; Chris@16: } Chris@16: Chris@16: // Find the next context with the same key. Chris@16: Value* next_by_key() const Chris@16: { Chris@16: context* elem = next_; Chris@16: while (elem) Chris@16: { Chris@16: if (elem->key_ == key_) Chris@16: return elem->value_; Chris@16: elem = elem->next_; Chris@16: } Chris@16: return 0; Chris@16: } Chris@16: Chris@16: private: Chris@16: friend class call_stack; Chris@16: Chris@16: // The key associated with the context. Chris@16: Key* key_; Chris@16: Chris@16: // The value associated with the context. Chris@16: Value* value_; Chris@16: Chris@16: // The next element in the stack. Chris@16: context* next_; Chris@16: }; Chris@16: Chris@16: friend class context; Chris@16: Chris@16: // Determine whether the specified owner is on the stack. Returns address of Chris@16: // key if present, 0 otherwise. Chris@16: static Value* contains(Key* k) Chris@16: { Chris@16: context* elem = top_; Chris@16: while (elem) Chris@16: { Chris@16: if (elem->key_ == k) Chris@16: return elem->value_; Chris@16: elem = elem->next_; Chris@16: } Chris@16: return 0; Chris@16: } Chris@16: Chris@16: // Obtain the value at the top of the stack. Chris@16: static Value* top() Chris@16: { Chris@16: context* elem = top_; Chris@16: return elem ? elem->value_ : 0; Chris@16: } Chris@16: Chris@16: private: Chris@16: // The top of the stack of calls for the current thread. Chris@16: static tss_ptr top_; Chris@16: }; Chris@16: Chris@16: template Chris@16: tss_ptr::context> Chris@16: call_stack::top_; Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace asio Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_ASIO_DETAIL_CALL_STACK_HPP