00001 #ifndef PROTON_THREAD_SAFE_HPP
00002 #define PROTON_THREAD_SAFE_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "./internal/config.hpp"
00026 #include "./connection.hpp"
00027 #include "./event_loop.hpp"
00028 #include "./internal/object.hpp"
00029 #include "./internal/type_traits.hpp"
00030
00031 #include <functional>
00032
00033 namespace proton {
00034
00035 class connection;
00036 class session;
00037 class link;
00038 class sender;
00039 class receiver;
00040
00041 namespace internal {
00042 template <class T> struct endpoint_traits;
00043 template<> struct endpoint_traits<connection> {};
00044 template<> struct endpoint_traits<session> {};
00045 template<> struct endpoint_traits<link> {};
00046 template<> struct endpoint_traits<sender> {};
00047 template<> struct endpoint_traits<receiver> {};
00048 }
00049
00050 template <class T> class returned;
00051
00068 template <class T>
00069 class thread_safe : private internal::pn_ptr_base, private internal::endpoint_traits<T> {
00070 typedef typename T::pn_type pn_type;
00071
00072 struct inject_decref : public void_function0 {
00073 pn_type* ptr_;
00074 inject_decref(pn_type* p) : ptr_(p) {}
00075 void operator()() PN_CPP_OVERRIDE { decref(ptr_); delete this; }
00076 };
00077
00078 public:
00080 static void operator delete(void*) {}
00082
00083 ~thread_safe() {
00084 if (ptr()) {
00085 if (event_loop()) {
00086 #if PN_CPP_HAS_CPP11
00087 event_loop()->inject(std::bind(&decref, ptr()));
00088 #else
00089 event_loop()->inject(*new inject_decref(ptr()));
00090 #endif
00091 } else {
00092 decref(ptr());
00093 }
00094 }
00095 }
00096
00098 class event_loop* event_loop() { return event_loop::get(ptr()); }
00099
00101 T unsafe() { return T(ptr()); }
00102
00103 private:
00104 static thread_safe* create(const T& obj) { return new (obj.pn_object()) thread_safe(); }
00105 static void* operator new(size_t, pn_type* p) { return p; }
00106 static void operator delete(void*, pn_type*) {}
00107 thread_safe() { incref(ptr()); }
00108 pn_type* ptr() { return reinterpret_cast<pn_type*>(this); }
00109
00110
00111
00112 thread_safe(const thread_safe&);
00113 thread_safe& operator=(const thread_safe&);
00114
00116 friend class returned<T>;
00118 };
00119
00120
00121
00122
00123
00124 template <class T>
00125 class returned : private internal::endpoint_traits<T>
00126 {
00127 public:
00129 explicit returned(thread_safe<T>* p) : ptr_(p) {}
00131 explicit returned(const T& obj) : ptr_(thread_safe<T>::create(obj)) {}
00134 returned(const returned& x) : ptr_(const_cast<returned&>(x).release()) {}
00136 ~returned() { if (ptr_) delete ptr_; }
00137
00139 thread_safe<T>* release() const { thread_safe<T>* p = ptr_; ptr_ = 0; return p; }
00140
00142 thread_safe<T>* get() const { return ptr_; }
00143
00145 operator T() { return ptr_->unsafe(); }
00146
00147 #if PN_CPP_HAS_CPP11
00149 operator std::shared_ptr<thread_safe<T> >() {
00150 return std::shared_ptr<thread_safe<T> >(release());
00151 }
00152
00154 operator std::unique_ptr<thread_safe<T> >() {
00155 return std::unique_ptr<thread_safe<T> >(release());
00156 }
00157 #endif
00158
00159 private:
00160 void operator=(const returned&);
00161 mutable thread_safe<T>* ptr_;
00162 };
00163
00165 template <class T> returned<T> make_thread_safe(const T& obj) { return returned<T>(obj); }
00166
00167 #if PN_CPP_HAS_CPP11
00168 template <class T> std::shared_ptr<thread_safe<T> > make_shared_thread_safe(const T& obj) {
00169 return make_thread_safe(obj);
00170 }
00171 template <class T> std::unique_ptr<thread_safe<T> > make_unique_thread_safe(const T& obj) {
00172 return make_thread_safe(obj);
00173 }
00174 #endif
00175
00176 }
00177
00178 #endif // PROTON_THREAD_SAFE_HPP