| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 | //// detail/call_stack.hpp// ~~~~~~~~~~~~~~~~~~~~~//// Copyright (c) 2003-2020 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 BOOST_ASIO_DETAIL_CALL_STACK_HPP#define BOOST_ASIO_DETAIL_CALL_STACK_HPP#if defined(_MSC_VER) && (_MSC_VER >= 1200)# pragma once#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)#include <boost/asio/detail/config.hpp>#include <boost/asio/detail/noncopyable.hpp>#include <boost/asio/detail/tss_ptr.hpp>#include <boost/asio/detail/push_options.hpp>namespace boost {namespace asio {namespace detail {// Helper class to determine whether or not the current thread is inside an// invocation of io_context::run() for a specified io_context 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} // namespace boost#include <boost/asio/detail/pop_options.hpp>#endif // BOOST_ASIO_DETAIL_CALL_STACK_HPP
 |