Qpid Proton C++  0.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
thread_safe.hpp
1 #ifndef PROTON_THREAD_SAFE_HPP
2 #define PROTON_THREAD_SAFE_HPP
3 
4 /*
5  *
6  * Licensed to the Apache Software Foundation (ASF) under one
7  * or more contributor license agreements. See the NOTICE file
8  * distributed with this work for additional information
9  * regarding copyright ownership. The ASF licenses this file
10  * to you under the Apache License, Version 2.0 (the
11  * "License"); you may not use this file except in compliance
12  * with the License. You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing,
17  * software distributed under the License is distributed on an
18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19  * KIND, either express or implied. See the License for the
20  * specific language governing permissions and limitations
21  * under the License.
22  *
23  */
24 
25 #include "./internal/config.hpp"
26 #include "./connection.hpp"
27 #include "./event_loop.hpp"
28 #include "./internal/object.hpp"
29 #include "./internal/type_traits.hpp"
30 
31 #include <functional>
32 
33 namespace proton {
34 
35 class connection;
36 class session;
37 class link;
38 class sender;
39 class receiver;
40 
41 namespace internal {
42 template <class T> struct endpoint_traits;
43 template<> struct endpoint_traits<connection> {};
44 template<> struct endpoint_traits<session> {};
45 template<> struct endpoint_traits<link> {};
46 template<> struct endpoint_traits<sender> {};
47 template<> struct endpoint_traits<receiver> {};
48 }
49 
50 template <class T> class returned;
51 
68 template <class T>
69 class thread_safe : private internal::pn_ptr_base, private internal::endpoint_traits<T> {
70  typedef typename T::pn_type pn_type;
71 
72  struct inject_decref : public void_function0 {
73  pn_type* ptr_;
74  inject_decref(pn_type* p) : ptr_(p) {}
75  void operator()() PN_CPP_OVERRIDE { decref(ptr_); delete this; }
76  };
77 
78  public:
80  static void operator delete(void*) {}
82 
83  ~thread_safe() {
84  if (ptr()) {
85  if (event_loop()) {
86 #if PN_CPP_HAS_CPP11
87  event_loop()->inject(std::bind(&decref, ptr()));
88 #else
89  event_loop()->inject(*new inject_decref(ptr()));
90 #endif
91  } else {
92  decref(ptr());
93  }
94  }
95  }
96 
98  class event_loop* event_loop() { return event_loop::get(ptr()); }
99 
101  T unsafe() { return T(ptr()); }
102 
103  private:
104  static thread_safe* create(const T& obj) { return new (obj.pn_object()) thread_safe(); }
105  static void* operator new(size_t, pn_type* p) { return p; }
106  static void operator delete(void*, pn_type*) {}
107  thread_safe() { incref(ptr()); }
108  pn_type* ptr() { return reinterpret_cast<pn_type*>(this); }
109 
110 
111  // Non-copyable.
112  thread_safe(const thread_safe&);
113  thread_safe& operator=(const thread_safe&);
114 
116  friend class returned<T>;
118 };
119 
120 // return value for functions returning a thread_safe<> object.
121 //
122 // Temporary return value only, you should release() to get a plain pointer or
123 // assign to a smart pointer type.
124 template <class T>
125 class returned : private internal::endpoint_traits<T>
126 {
127  public:
129  explicit returned(thread_safe<T>* p) : ptr_(p) {}
131  explicit returned(const T& obj) : ptr_(thread_safe<T>::create(obj)) {}
134  returned(const returned& x) : ptr_(const_cast<returned&>(x).release()) {}
136  ~returned() { if (ptr_) delete ptr_; }
137 
139  thread_safe<T>* release() const { thread_safe<T>* p = ptr_; ptr_ = 0; return p; }
140 
142  operator T() { return ptr_->unsafe(); }
143 
144 #if PN_CPP_HAS_CPP11
145  operator std::shared_ptr<thread_safe<T> >() {
147  return std::shared_ptr<thread_safe<T> >(release());
148  }
149 
151  operator std::unique_ptr<thread_safe<T> >() {
152  return std::unique_ptr<thread_safe<T> >(release());
153  }
154 #endif
155 
156  private:
157  void operator=(const returned&);
158  mutable thread_safe<T>* ptr_;
159 };
160 
162 template <class T> returned<T> make_thread_safe(const T& obj) { return returned<T>(obj); }
163 
164 #if PN_CPP_HAS_CPP11
165 template <class T> std::shared_ptr<thread_safe<T> > make_shared_thread_safe(const T& obj) {
166  return make_thread_safe(obj);
167 }
168 template <class T> std::unique_ptr<thread_safe<T> > make_unique_thread_safe(const T& obj) {
169  return make_thread_safe(obj);
170 }
171 #endif
172 
173 } // proton
174 
175 #endif // PROTON_THREAD_SAFE_HPP
Experimental - A serial execution context.
Definition: event_loop.hpp:57
T unsafe()
Get the thread-unsafe proton object wrapped by this thread_safe&lt;T&gt;
Definition: thread_safe.hpp:101
class event_loop * event_loop()
Get the event loop for this object.
Definition: thread_safe.hpp:98
virtual bool inject(void_function0 &f)=0
Arrange to have f() called in the event_loop&#39;s sequence: possibly deferred, possibly in another threa...
returned< T > make_thread_safe(const T &obj)
Make a thread-safe wrapper for obj.
Definition: thread_safe.hpp:162
Experimental - A thread-safe object wrapper.
Definition: connection.hpp:45