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
 |