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