• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // detail/call_stack.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef ASIO_DETAIL_CALL_STACK_HPP
12 #define ASIO_DETAIL_CALL_STACK_HPP
13 
14 
15 #include "asio/detail/config.hpp"
16 #include "asio/detail/noncopyable.hpp"
17 #include "asio/detail/tss_ptr.hpp"
18 
19 #include "asio/detail/push_options.hpp"
20 
21 namespace asio {
22 namespace detail {
23 
24 // Helper class to determine whether or not the current thread is inside an
25 // invocation of io_service::run() for a specified io_service object.
26 template <typename Key, typename Value = unsigned char>
27 class call_stack
28 {
29 public:
30   // Context class automatically pushes the key/value pair on to the stack.
31   class context
32     : private noncopyable
33   {
34   public:
35     // Push the key on to the stack.
context(Key * k)36     explicit context(Key* k)
37       : key_(k),
38         next_(call_stack<Key, Value>::top_)
39     {
40       value_ = reinterpret_cast<unsigned char*>(this);
41       call_stack<Key, Value>::top_ = this;
42     }
43 
44     // Push the key/value pair on to the stack.
context(Key * k,Value & v)45     context(Key* k, Value& v)
46       : key_(k),
47         value_(&v),
48         next_(call_stack<Key, Value>::top_)
49     {
50       call_stack<Key, Value>::top_ = this;
51     }
52 
53     // Pop the key/value pair from the stack.
~context()54     ~context()
55     {
56       call_stack<Key, Value>::top_ = next_;
57     }
58 
59     // Find the next context with the same key.
next_by_key() const60     Value* next_by_key() const
61     {
62       context* elem = next_;
63       while (elem)
64       {
65         if (elem->key_ == key_)
66           return elem->value_;
67         elem = elem->next_;
68       }
69       return 0;
70     }
71 
72   private:
73     friend class call_stack<Key, Value>;
74 
75     // The key associated with the context.
76     Key* key_;
77 
78     // The value associated with the context.
79     Value* value_;
80 
81     // The next element in the stack.
82     context* next_;
83   };
84 
85   friend class context;
86 
87   // Determine whether the specified owner is on the stack. Returns address of
88   // key if present, 0 otherwise.
contains(Key * k)89   static Value* contains(Key* k)
90   {
91     context* elem = top_;
92     while (elem)
93     {
94       if (elem->key_ == k)
95         return elem->value_;
96       elem = elem->next_;
97     }
98     return 0;
99   }
100 
101   // Obtain the value at the top of the stack.
top()102   static Value* top()
103   {
104     context* elem = top_;
105     return elem ? elem->value_ : 0;
106   }
107 
108 private:
109   // The top of the stack of calls for the current thread.
110   static tss_ptr<context> top_;
111 };
112 
113 template <typename Key, typename Value>
114 tss_ptr<typename call_stack<Key, Value>::context>
115 call_stack<Key, Value>::top_;
116 
117 } // namespace detail
118 } // namespace asio
119 
120 #include "asio/detail/pop_options.hpp"
121 
122 #endif // ASIO_DETAIL_CALL_STACK_HPP
123