Commit bdd75627 authored by Dominik Charousset's avatar Dominik Charousset

Fix reference count of tuple decorators

parent a71505bb
......@@ -32,16 +32,16 @@ class concatenated_tuple : public message_data {
public:
concatenated_tuple& operator=(const concatenated_tuple&) = delete;
using pointer = message_data::ptr;
using vector_type = std::vector<pointer>;
using message_data::cow_ptr;
using vector_type = std::vector<cow_ptr>;
static pointer make(std::initializer_list<pointer> xs);
static cow_ptr make(std::initializer_list<cow_ptr> xs);
void* mutable_at(size_t pos) override;
size_t size() const override;
concatenated_tuple* copy() const override;
cow_ptr copy() const override;
const void* at(size_t pos) const override;
......
......@@ -41,16 +41,16 @@ class decorated_tuple : public message_data {
using vector_type = std::vector<size_t>;
using pointer = message_data::ptr;
using message_data::cow_ptr;
// creates a typed subtuple from `d` with mapping `v`
static pointer make(pointer d, vector_type v);
static cow_ptr make(cow_ptr d, vector_type v);
void* mutable_at(size_t pos) override;
size_t size() const override;
decorated_tuple* copy() const override;
cow_ptr copy() const override;
const void* at(size_t pos) const override;
......@@ -63,7 +63,7 @@ class decorated_tuple : public message_data {
uint16_t type_nr_at(size_t pos) const override;
inline const pointer& decorated() const {
inline const cow_ptr& decorated() const {
return m_decorated;
}
......@@ -72,10 +72,10 @@ class decorated_tuple : public message_data {
}
private:
decorated_tuple(pointer&&, vector_type&&);
decorated_tuple(cow_ptr&&, vector_type&&);
decorated_tuple(const decorated_tuple&) = default;
pointer m_decorated;
cow_ptr m_decorated;
vector_type m_mapping;
uint32_t m_type_token;
};
......
......@@ -162,6 +162,7 @@ class basic_memory_cache : public memory_cache {
// allocate cache on-the-fly
if (!m_cache) {
m_cache.reset(new storage, false); // starts with ref count of 1
CAF_REQUIRE(m_cache->unique());
}
auto res = m_cache->next();
if (m_cache->has_next()) {
......@@ -170,7 +171,7 @@ class basic_memory_cache : public memory_cache {
// we got the last element out of the cache; pass the reference to the
// client to avoid pointless increase/decrease ops on the reference count
embedded_storage result;
result.first = std::move(m_cache);
result.first.reset(m_cache.release(), false);
result.second = res;
return result;
}
......
......@@ -59,8 +59,6 @@ class message_data : public ref_counted {
virtual size_t size() const = 0;
virtual message_data* copy() const = 0;
virtual const void* at(size_t pos) const = 0;
// Tries to match element at position `pos` to given RTTI.
......@@ -77,15 +75,19 @@ class message_data : public ref_counted {
* nested types *
****************************************************************************/
class ptr {
class cow_ptr {
public:
ptr() = default;
ptr(ptr&&) = default;
ptr(const ptr&) = default;
ptr& operator=(ptr&&) = default;
ptr& operator=(const ptr&) = default;
cow_ptr() = default;
cow_ptr(cow_ptr&&) = default;
cow_ptr(const cow_ptr&) = default;
cow_ptr& operator=(cow_ptr&&) = default;
cow_ptr& operator=(const cow_ptr&) = default;
inline ptr(intrusive_ptr<message_data> p) : m_ptr(std::move(p)) {
inline cow_ptr(intrusive_ptr<message_data> p) : m_ptr(std::move(p)) {
// nop
}
inline cow_ptr(message_data* ptr, bool add_ref) : m_ptr(ptr, add_ref) {
// nop
}
......@@ -93,7 +95,7 @@ class message_data : public ref_counted {
* modifiers *
**************************************************************************/
inline void swap(ptr& other) {
inline void swap(cow_ptr& other) {
m_ptr.swap(other.m_ptr);
}
......@@ -140,6 +142,8 @@ class message_data : public ref_counted {
message_data* get_detached();
intrusive_ptr<message_data> m_ptr;
};
virtual cow_ptr copy() const = 0;
};
} // namespace detail
......
......@@ -98,8 +98,8 @@ class tuple_vals : public message_data {
return sizeof...(Ts);
}
tuple_vals* copy() const override {
return new tuple_vals(*this);
message_data::cow_ptr copy() const override {
return message_data::cow_ptr(new tuple_vals(*this), false);
}
const void* at(size_t pos) const override {
......
......@@ -309,7 +309,7 @@ class message {
using raw_ptr = detail::message_data*;
using data_ptr = detail::message_data::ptr;
using data_ptr = detail::message_data::cow_ptr;
explicit message(raw_ptr);
......@@ -462,7 +462,7 @@ make_message(V&& v, Vs&&... vs) {
typename detail::strip_and_convert<Vs>::type
>::type...>;
auto ptr = make_counted<storage>(std::forward<V>(v), std::forward<Vs>(vs)...);
return message{detail::message_data::ptr{std::move(ptr)}};
return message{detail::message_data::cow_ptr{std::move(ptr)}};
}
/**
......
......@@ -34,6 +34,7 @@
#include <QEvent>
#include <QApplication>
#include "caf/make_counted.hpp"
#include "caf/actor_companion.hpp"
#include "caf/message_handler.hpp"
......@@ -55,7 +56,7 @@ class actor_widget : public Base {
template <typename... Ts>
actor_widget(Ts&&... args) : Base(std::forward<Ts>(args)...) {
m_companion.reset(detail::memory::create<actor_companion>());
m_companion = make_counted<actor_companion>();
m_companion->on_enqueue([=](message_pointer ptr) {
qApp->postEvent(this, new event_type(std::move(ptr)));
});
......
......@@ -39,8 +39,7 @@ void actor_companion::on_enqueue(enqueue_handler handler) {
void actor_companion::enqueue(const actor_addr& sender, message_id mid,
message content, execution_unit*) {
using detail::memory;
message_pointer ptr{memory::create<mailbox_element>(sender, mid,
std::move(content))};
auto ptr = mailbox_element::make(sender, mid, std::move(content));
shared_lock<lock_type> guard(m_lock);
if (m_on_enqueue) {
m_on_enqueue(std::move(ptr));
......
......@@ -27,7 +27,7 @@
namespace caf {
namespace detail {
auto concatenated_tuple::make(std::initializer_list<pointer> xs) -> pointer {
auto concatenated_tuple::make(std::initializer_list<cow_ptr> xs) -> cow_ptr {
auto result = make_counted<concatenated_tuple>();
for (auto& x : xs) {
if (x) {
......@@ -41,7 +41,7 @@ auto concatenated_tuple::make(std::initializer_list<pointer> xs) -> pointer {
}
}
result->init();
return pointer{std::move(result)};
return cow_ptr{std::move(result)};
}
void* concatenated_tuple::mutable_at(size_t pos) {
......@@ -54,8 +54,8 @@ size_t concatenated_tuple::size() const {
return m_size;
}
concatenated_tuple* concatenated_tuple::copy() const {
return new concatenated_tuple(*this);
message_data::cow_ptr concatenated_tuple::copy() const {
return cow_ptr(new concatenated_tuple(*this), false);
}
const void* concatenated_tuple::at(size_t pos) const {
......@@ -106,7 +106,7 @@ void concatenated_tuple::init() {
m_type_token = add_to_type_token(m_type_token, m->type_nr_at(i));
}
}
auto acc_size = [](size_t tmp, const pointer& val) {
auto acc_size = [](size_t tmp, const cow_ptr& val) {
return tmp + val->size();
};
m_size = std::accumulate(m_data.begin(), m_data.end(), size_t{0}, acc_size);
......
......@@ -22,7 +22,7 @@
namespace caf {
namespace detail {
decorated_tuple::pointer decorated_tuple::make(pointer d, vector_type v) {
decorated_tuple::cow_ptr decorated_tuple::make(cow_ptr d, vector_type v) {
auto ptr = dynamic_cast<const decorated_tuple*>(d.get());
if (ptr) {
d = ptr->decorated();
......@@ -31,7 +31,7 @@ decorated_tuple::pointer decorated_tuple::make(pointer d, vector_type v) {
v[i] = pmap[v[i]];
}
}
return pointer{new decorated_tuple(std::move(d), std::move(v))};
return cow_ptr{new decorated_tuple(std::move(d), std::move(v))};
}
void* decorated_tuple::mutable_at(size_t pos) {
......@@ -43,8 +43,8 @@ size_t decorated_tuple::size() const {
return m_mapping.size();
}
decorated_tuple* decorated_tuple::copy() const {
return new decorated_tuple(*this);
message_data::cow_ptr decorated_tuple::copy() const {
return cow_ptr(new decorated_tuple(*this), false);
}
const void* decorated_tuple::at(size_t pos) const {
......@@ -69,13 +69,13 @@ uint16_t decorated_tuple::type_nr_at(size_t pos) const {
return m_decorated->type_nr_at(m_mapping[pos]);
}
decorated_tuple::decorated_tuple(pointer&& d, vector_type&& v)
decorated_tuple::decorated_tuple(cow_ptr&& d, vector_type&& v)
: m_decorated(std::move(d)),
m_mapping(std::move(v)),
m_type_token(0xFFFFFFFF) {
CAF_REQUIRE(m_mapping.empty()
|| *(std::max_element(m_mapping.begin(), m_mapping.end()))
< static_cast<const pointer&>(m_decorated)->size());
< static_cast<const cow_ptr&>(m_decorated)->size());
// calculate type token
for (size_t i = 0; i < m_mapping.size(); ++i) {
m_type_token <<= 6;
......
......@@ -66,8 +66,8 @@ class message_builder::dynamic_msg_data : public detail::message_data {
return m_elements.size();
}
dynamic_msg_data* copy() const override {
return new dynamic_msg_data(*this);
cow_ptr copy() const override {
return cow_ptr(new dynamic_msg_data(*this), false);
}
bool match_element(size_t pos, uint16_t typenr,
......@@ -174,8 +174,8 @@ message_builder::dynamic_msg_data* message_builder::data() {
// operations on m_data can cause race conditions if
// someone else holds a reference to m_data
if (!m_data->unique()) {
intrusive_ptr<ref_counted> tmp{std::move(m_data)};
m_data.reset(static_cast<dynamic_msg_data*>(tmp.get())->copy());
auto tmp = static_cast<dynamic_msg_data*>(m_data.get())->copy();
m_data.reset(tmp.release(), false);
}
return static_cast<dynamic_msg_data*>(m_data.get());
}
......
......@@ -65,13 +65,12 @@ std::string message_data::tuple_type_names() const {
return result;
}
message_data* message_data::ptr::get_detached() {
message_data* message_data::cow_ptr::get_detached() {
auto p = m_ptr.get();
if (!p->unique()) {
auto np = p->copy();
CAF_REQUIRE(np->unique());
m_ptr.reset(np, false);
return np;
auto cptr = p->copy();
m_ptr.swap(cptr.m_ptr);
return m_ptr.get();
}
return p;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment