/usr/include/proton/thread_safe.hpp is in libqpid-proton-cpp8-dev 0.14.0-5.1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | #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;
/// **Experimental** - A thread-safe object wrapper.
///
/// The proton::object subclasses (proton::connection, proton::sender etc.) are
/// reference-counted wrappers for C structs. They are not safe for concurrent use,
/// not even to copy or assign.
///
/// A pointer to thread_safe<> can be used from any thread to get the
/// proton::event_loop for the object's connection. The object will not be
/// destroyed until the thread_safe<> is deleted. You can use std::shared_ptr,
/// std::unique_ptr or any other memory management technique to manage the
/// thread_safe<>.
///
/// Use make_thread_safe(), make_shared_thread_safe(), make_unique_thread_safe() to
/// create a thread_safe<>
///
/// @see @ref mt_page
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:
/// @cond INTERNAL
static void operator delete(void*) {}
/// @endcond
~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());
}
}
}
/// Get the event loop for this object.
class event_loop* event_loop() { return event_loop::get(ptr()); }
/// Get the thread-unsafe proton object wrapped by this thread_safe<T>
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&);
/// @cond INTERNAL
friend class returned<T>;
/// @endcond
};
// 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:
/// Take ownership
explicit returned(thread_safe<T>* p) : ptr_(p) {}
/// Create an owned thread_safe<T>
explicit returned(const T& obj) : ptr_(thread_safe<T>::create(obj)) {}
/// Transfer ownership.
/// Use the same "cheat" as std::auto_ptr, calls x.release() even though x is const.
returned(const returned& x) : ptr_(const_cast<returned&>(x).release()) {}
/// Delete if still owned.
~returned() { if (ptr_) delete ptr_; }
/// Release ownership.
thread_safe<T>* release() const { thread_safe<T>* p = ptr_; ptr_ = 0; return p; }
/// Get the raw pointer, caller must not delete.
thread_safe<T>* get() const { return ptr_; }
/// Implicit conversion to target, usable only in a safe context.
operator T() { return ptr_->unsafe(); }
#if PN_CPP_HAS_CPP11
/// Release to a std::shared_ptr
operator std::shared_ptr<thread_safe<T> >() {
return std::shared_ptr<thread_safe<T> >(release());
}
/// Release to a std::unique_ptr
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_;
};
/// Make a thread-safe wrapper for `obj`.
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
|