thread_safe.hpp
#ifndef PROTON_THREAD_SAFE_HPP
#define PROTON_THREAD_SAFE_HPP
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
#include "./internal/config.hpp"
#include "./connection.hpp"
#include "./event_loop.hpp"
#include "./internal/object.hpp"
#include "./internal/type_traits.hpp"
#include <functional>
namespace proton {
class connection;
class session;
class link;
class sender;
class receiver;
namespace internal {
template <class T> struct endpoint_traits;
template<> struct endpoint_traits<connection> {};
template<> struct endpoint_traits<session> {};
template<> struct endpoint_traits<link> {};
template<> struct endpoint_traits<sender> {};
template<> struct endpoint_traits<receiver> {};
}
template <class T> class returned;
template <class T>
class thread_safe : private internal::pn_ptr_base, private internal::endpoint_traits<T> {
typedef typename T::pn_type pn_type;
struct inject_decref : public void_function0 {
pn_type* ptr_;
inject_decref(pn_type* p) : ptr_(p) {}
void operator()() PN_CPP_OVERRIDE { decref(ptr_); delete this; }
};
public:
static void operator delete(void*) {}
~thread_safe() {
if (ptr()) {
if (event_loop()) {
#if PN_CPP_HAS_CPP11
event_loop()->inject(std::bind(&decref, ptr()));
#else
event_loop()->inject(*new inject_decref(ptr()));
#endif
} else {
decref(ptr());
}
}
}
class event_loop* event_loop() { return event_loop::get(ptr()); }
T unsafe() { return T(ptr()); }
private:
static thread_safe* create(const T& obj) { return new (obj.pn_object()) thread_safe(); }
static void* operator new(size_t, pn_type* p) { return p; }
static void operator delete(void*, pn_type*) {}
thread_safe() { incref(ptr()); }
pn_type* ptr() { return reinterpret_cast<pn_type*>(this); }
// Non-copyable.
thread_safe(const thread_safe&);
thread_safe& operator=(const thread_safe&);
friend class returned<T>;
};
// return value for functions returning a thread_safe<> object.
//
// Temporary return value only, you should release() to get a plain pointer or
// assign to a smart pointer type.
template <class T>
class returned : private internal::endpoint_traits<T>
{
public:
explicit returned(thread_safe<T>* p) : ptr_(p) {}
explicit returned(const T& obj) : ptr_(thread_safe<T>::create(obj)) {}
returned(const returned& x) : ptr_(const_cast<returned&>(x).release()) {}
~returned() { if (ptr_) delete ptr_; }
thread_safe<T>* release() const { thread_safe<T>* p = ptr_; ptr_ = 0; return p; }
thread_safe<T>* get() const { return ptr_; }
operator T() { return ptr_->unsafe(); }
#if PN_CPP_HAS_CPP11
operator std::shared_ptr<thread_safe<T> >() {
return std::shared_ptr<thread_safe<T> >(release());
}
operator std::unique_ptr<thread_safe<T> >() {
return std::unique_ptr<thread_safe<T> >(release());
}
#endif
private:
void operator=(const returned&);
mutable thread_safe<T>* ptr_;
};
template <class T> returned<T> make_thread_safe(const T& obj) { return returned<T>(obj); }
#if PN_CPP_HAS_CPP11
template <class T> std::shared_ptr<thread_safe<T> > make_shared_thread_safe(const T& obj) {
return make_thread_safe(obj);
}
template <class T> std::unique_ptr<thread_safe<T> > make_unique_thread_safe(const T& obj) {
return make_thread_safe(obj);
}
#endif
} // proton
#endif // PROTON_THREAD_SAFE_HPP
proton::event_loop
Experimental - A serial execution context.
Definition: event_loop.hpp:57
proton::thread_safe::unsafe
T unsafe()
Get the thread-unsafe proton object wrapped by this thread_safe<T>
Definition: thread_safe.hpp:101
proton::thread_safe::event_loop
class event_loop * event_loop()
Get the event loop for this object.
Definition: thread_safe.hpp:98
proton::make_thread_safe
returned< T > make_thread_safe(const T &obj)
Make a thread-safe wrapper for obj.
Definition: thread_safe.hpp:165
proton
Type traits for mapping between AMQP and C++ types.
Definition: annotation_key.hpp:28
proton::thread_safe
Experimental - A thread-safe object wrapper.
Definition: connection.hpp:45