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