forked from enlightenment/efl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
4.4 KiB
200 lines
4.4 KiB
#ifndef EINA_CLONE_ALLOCATORS_HH_ |
|
#define EINA_CLONE_ALLOCATORS_HH_ |
|
|
|
#include <eina_workarounds.hh> |
|
|
|
#include <Eo.h> |
|
|
|
#include <memory> |
|
#include <cstring> |
|
#include <cstdlib> |
|
#include <type_traits> |
|
|
|
/** |
|
* @addtogroup Eina_Cxx_Containers_Group |
|
* |
|
* @{ |
|
*/ |
|
|
|
namespace efl { namespace eina { |
|
|
|
/** |
|
* @defgroup Eina_Cxx_Clone_Allocators_Group Clone Allocators |
|
* @ingroup Eina_Cxx_Containers_Group |
|
* |
|
* Clone allocators is a formalized way to pointer containers control |
|
* the memory of the stored objects, allowing users to apply custom |
|
* allocators/deallocators for the cloned objects. |
|
* |
|
* @{ |
|
*/ |
|
|
|
/* |
|
* @internal |
|
*/ |
|
struct default_clone_allocator_placeholder; |
|
|
|
/** |
|
* This allocator creates copies of objects on the heap, calling their |
|
* copy constructor to make then equivalent to the given reference. |
|
* |
|
* The created objects are released with the default delete. |
|
*/ |
|
struct heap_copy_allocator |
|
{ |
|
template <typename T> |
|
static T* allocate_clone(T const& v) |
|
{ |
|
return new T(v); |
|
} |
|
|
|
template <typename T> |
|
static void deallocate_clone(T* p) |
|
{ |
|
#ifdef EFL_EINA_CXX11 |
|
std::default_delete<T>()(p); |
|
#else |
|
delete p; |
|
#endif |
|
} |
|
}; |
|
|
|
/** |
|
* This allocator creates copies of Eo classes through eo_ref |
|
* |
|
* The created objects are released using eo_unref |
|
*/ |
|
struct eo_clone_allocator |
|
{ |
|
static Eo* allocate_clone(Eo const& v) |
|
{ |
|
return ::efl_ref(&v); |
|
} |
|
|
|
static void deallocate_clone(Eo const* p) |
|
{ |
|
::efl_unref(const_cast<Eo*>(p)); |
|
} |
|
}; |
|
|
|
/** |
|
* This allocator allows users to create custom allocation schemes by |
|
* overloading the <tt>new_clone(T const& v)</tt> and |
|
* <tt>delete_clone(T* p)</tt> functions. |
|
*/ |
|
struct heap_clone_allocator |
|
{ |
|
template <typename T> |
|
static T* allocate_clone(T const& v) |
|
{ |
|
return new_clone(v); |
|
} |
|
template <typename T> |
|
static void deallocate_clone(T* p) |
|
{ |
|
delete_clone(p); |
|
} |
|
}; |
|
|
|
/** |
|
* This allocator does not allocate or deallocate anything. It simple |
|
* gets non-const-qualified pointers for objects, which allow |
|
* containers to hold elements without having ownership on them. |
|
* |
|
* It is commonly used to create a pointer container that is a view into |
|
* another existing container. |
|
*/ |
|
struct view_clone_allocator |
|
{ |
|
template <typename T> |
|
static T* allocate_clone(T const& v) |
|
{ |
|
return const_cast<T*>(&v); |
|
} |
|
template <typename T> |
|
static void deallocate_clone(T*) |
|
{ |
|
} |
|
}; |
|
|
|
/** |
|
* This allocator does not define an @c allocate_clone member function, |
|
* so it should be used to disable operations that require elements to |
|
* be cloned. |
|
*/ |
|
struct heap_no_copy_allocator |
|
{ |
|
static void deallocate_clone(_Elm_Calendar_Mark const volatile*) {} |
|
static void deallocate_clone(_Elm_Calendar_Mark volatile*) {} |
|
static void deallocate_clone(_Elm_Calendar_Mark const*) {} |
|
static void deallocate_clone(_Elm_Calendar_Mark*) {} |
|
static void deallocate_clone(Elm_Gen_Item const volatile*) {} |
|
static void deallocate_clone(Elm_Gen_Item volatile*) {} |
|
static void deallocate_clone(Elm_Gen_Item const*) {} |
|
static void deallocate_clone(Elm_Gen_Item*) {} |
|
static void deallocate_clone(_Elm_Map_Overlay const volatile*) {} |
|
static void deallocate_clone(_Elm_Map_Overlay volatile*) {} |
|
static void deallocate_clone(_Elm_Map_Overlay const*) {} |
|
static void deallocate_clone(_Elm_Map_Overlay*) {} |
|
template <typename T> |
|
static void deallocate_clone(T* p) |
|
{ |
|
#ifdef EFL_EINA_CXX11 |
|
std::default_delete<T>()(p); |
|
#else |
|
delete p; |
|
#endif |
|
} |
|
}; |
|
|
|
/** |
|
* Manages allocation and deallocation of memory using the function |
|
* @c malloc and @c free. This allocator does not calls constructors, |
|
* the content of the newly allocated objects are assigned using |
|
* @c memcpy, so it has to be used with types that have |
|
* <em>standard-layout</em>. |
|
*/ |
|
struct malloc_clone_allocator |
|
{ |
|
template <typename T> |
|
static T* allocate_clone(T const& v) |
|
{ |
|
static_assert(std::is_pod<T>::value, "malloc_clone_allocator can only be used with POD types"); |
|
T* p = static_cast<T*>(std::malloc(sizeof(T))); |
|
std::memcpy(p, &v, sizeof(T)); |
|
return p; |
|
} |
|
|
|
template <typename T> |
|
static void deallocate_clone(T const* p) |
|
{ |
|
static_assert(std::is_pod<T>::value || std::is_void<T>::value |
|
, "malloc_clone_allocator can only be used with POD types"); |
|
std::free(const_cast<T*>(p)); |
|
} |
|
}; |
|
|
|
/** |
|
* @internal |
|
*/ |
|
template <typename A> |
|
struct clone_allocator_deleter |
|
{ |
|
template <typename T> |
|
void operator()(T* object) const |
|
{ |
|
A::deallocate_clone(object); |
|
} |
|
}; |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
} } |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
#endif
|
|
|