126 lines
2.8 KiB
C++
126 lines
2.8 KiB
C++
|
//
|
||
|
// detail/call_stack.hpp
|
||
|
// ~~~~~~~~~~~~~~~~~~~~~
|
||
|
//
|
||
|
// Copyright (c) 2003-2023 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_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
|
||
|
|
||
|
#include "asio/detail/pop_options.hpp"
|
||
|
|
||
|
#endif // ASIO_DETAIL_CALL_STACK_HPP
|