Commit 8c32441b authored by Dominik Charousset's avatar Dominik Charousset

less intrusive memory management

this patch adds the class `memory_cached_mixin` which adds all
member functions and member variables needed by the memory management
subsystem
parent eb2b833a
......@@ -35,8 +35,10 @@
#include <vector>
#include <utility>
#include <typeinfo>
#include <iostream>
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/config.hpp"
#include "cppa/ref_counted.hpp"
namespace cppa { namespace detail {
......@@ -79,6 +81,45 @@ class memory_cache {
};
class memory;
memory_cache* get_cache_map_entry(const std::type_info* tinf);
template<typename T>
class basic_memory_cache;
template<typename Base>
class memory_cached_mixin : public Base {
friend class memory;
template<typename T>
friend class basic_memory_cache;
protected:
template<typename... Args>
memory_cached_mixin(Args&&... args)
: Base(std::forward<Args>(args)...), outer_memory(nullptr) { }
virtual void request_deletion() {
memory_cache* mc = get_cache_map_entry(&typeid(*this));
if (!mc) {
auto om = outer_memory;
if (om) {
om->destroy();
om->deallocate();
}
else delete this;
}
else mc->release_instance(mc->downcast(this));
}
private:
instance_wrapper* outer_memory;
};
template<typename T>
class basic_memory_cache : public memory_cache {
......@@ -178,39 +219,8 @@ class memory {
return result;
}
/*
* @brief Calls the destructor of @p ptr and allows the memory manager
* to reuse this address.
*/
template<typename T>
static inline void dispose(T* ptr) {
auto mc = get_or_set_cache_map_entry<T>();
mc->release_instance(ptr);
}
/*
* @brief Calls the destructor of @p ptr and allows the memory manager
* to reuse this address. This function must be used when disposing
* through a base pointer.
*/
template<typename T>
static inline void dispose_base(T* ptr) {
auto mc = get_cache_map_entry(&typeid(*ptr));
if (mc) mc->release_instance(mc->downcast(ptr));
else {
auto wptr = ptr->outer_memory;
if (wptr) {
wptr->destroy();
wptr->deallocate();
}
else delete ptr;
}
}
private:
static memory_cache* get_cache_map_entry(const std::type_info* tinf);
static void add_cache_map_entry(const std::type_info* tinf, memory_cache* instance);
template<typename T>
......@@ -226,9 +236,8 @@ class memory {
};
struct disposer {
template<typename T>
void operator()(T* ptr) {
memory::dispose(ptr);
inline void operator()(memory_managed* ptr) const {
ptr->request_deletion();
}
};
......
......@@ -37,19 +37,14 @@
#include "cppa/any_tuple.hpp"
#include "cppa/message_id.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/detail/memory.hpp"
// needs access to constructor + destructor to initialize m_dummy_node
namespace cppa { class local_actor; }
namespace cppa { namespace detail {
class memory;
class instance_wrapper;
class recursive_queue_node : public memory_managed {
template<typename>
friend class basic_memory_cache;
class recursive_queue_node : public memory_cached_mixin<memory_managed> {
friend class memory;
friend class ::cppa::local_actor;
......@@ -75,11 +70,6 @@ class recursive_queue_node : public memory_managed {
recursive_queue_node(actor_ptr sptr, any_tuple data, message_id_t id = message_id_t());
~recursive_queue_node();
// a pointer to the outer memory region this instance belongs to
instance_wrapper* outer_memory;
};
} } // namespace cppa::detail
......
......@@ -37,12 +37,13 @@
#include "cppa/actor.hpp"
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message_id.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/response_handle.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/message_id.hpp"
#include "cppa/detail/memory.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
namespace cppa {
......@@ -52,12 +53,6 @@ class scheduler;
class message_future;
class local_scheduler;
namespace detail {
class memory;
class instance_wrapper;
template<typename> class basic_memory_cache;
} // namespace detail
template<bool DiscardOld>
struct behavior_policy { static const bool discard_old = DiscardOld; };
......@@ -115,7 +110,7 @@ class message_future;
/**
* @brief Base class for local running Actors.
*/
class local_actor : public actor {
class local_actor : public detail::memory_cached_mixin<actor> {
typedef actor super;
......@@ -458,12 +453,6 @@ class local_actor : public actor {
do_become(std::move(copy), discard_old);
}
void request_deletion();
private:
detail::instance_wrapper* outer_memory;
};
/**
......
......@@ -33,8 +33,17 @@
namespace cppa {
namespace detail { struct disposer; }
/**
* @brief This base enables derived classes to enforce a different
* allocation strategy than new/delete by providing a virtual
* protected @p request_deletion() function and non-public destructor.
*/
class memory_managed {
friend struct detail::disposer;
protected:
virtual ~memory_managed();
......
......@@ -48,30 +48,22 @@ class basic_memory_cache;
namespace cppa { namespace network {
class sync_request_info : public memory_managed {
public:
template<typename>
friend class detail::basic_memory_cache;
class sync_request_info : public detail::memory_cached_mixin<memory_managed> {
friend class detail::memory;
public:
typedef sync_request_info* pointer;
pointer next; // intrusive next pointer
pointer next; // intrusive next pointer
actor_ptr sender; // points to the sender of the message
message_id_t mid;
message_id_t mid; // sync message ID
private:
sync_request_info(actor_ptr sptr, message_id_t id);
~sync_request_info();
// intrusive outer memory pointer
detail::instance_wrapper* outer_memory;
};
class default_actor_proxy : public detail::abstract_actor<actor_proxy> {
......
......@@ -69,10 +69,6 @@ class ref_counted : public memory_managed {
inline size_t get_reference_count() const { return m_rc; }
protected:
virtual ~ref_counted();
private:
std::atomic<size_t> m_rc;
......
......@@ -48,8 +48,6 @@ inline sync_request_info* new_req_info(actor_ptr sptr, message_id_t id) {
sync_request_info::sync_request_info(actor_ptr sptr, message_id_t id)
: next(nullptr), sender(std::move(sptr)), mid(id) { }
sync_request_info::~sync_request_info() { }
default_actor_proxy::default_actor_proxy(actor_id mid,
const process_information_ptr& pinfo,
const default_protocol_ptr& parent)
......
......@@ -70,8 +70,7 @@ class down_observer : public attachable {
local_actor::local_actor(bool sflag)
: m_chaining(sflag), m_trap_exit(false)
, m_is_scheduled(sflag), m_dummy_node(), m_current_node(&m_dummy_node)
, outer_memory(nullptr) { }
, m_is_scheduled(sflag), m_dummy_node(), m_current_node(&m_dummy_node) { }
void local_actor::monitor(actor_ptr whom) {
if (whom) whom->attach(new down_observer(this, whom));
......@@ -158,9 +157,4 @@ response_handle local_actor::make_response_handle() {
return std::move(result);
}
void local_actor::request_deletion() {
if (outer_memory) detail::memory::dispose_base(this);
else super::request_deletion();
}
} // namespace cppa
......@@ -70,7 +70,7 @@ cache_map& get_cache_map() {
return *cache;
}
memory_cache* memory::get_cache_map_entry(const type_info* tinf) {
memory_cache* get_cache_map_entry(const type_info* tinf) {
auto& cache = get_cache_map();
auto i = cache.find(tinf);
if (i != cache.end()) return i->second.get();
......
......@@ -38,8 +38,6 @@ recursive_queue_node::recursive_queue_node(actor_ptr sptr,
any_tuple data,
message_id_t id)
: next(nullptr), marked(false), sender(move(sptr))
, msg(move(data)), mid(id), outer_memory(nullptr) { }
recursive_queue_node::~recursive_queue_node() { }
, msg(move(data)), mid(id) { }
} } // namespace cppa::detail
......@@ -35,6 +35,4 @@ namespace cppa {
ref_counted::ref_counted() : m_rc(0) { }
ref_counted::~ref_counted() { }
} // namespace cppa
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