eina-cxx: Added malloc_clone_allocator to use with POD's when wrapping Eina C structures

Summary:
Added efl::eina::malloc_clone_allocator to be used with ptr_* data
structures for wrapping structures allocated by EFL in C.

This allows for example:

  void foo(Eina_List* l)
  {
    efl::eina::ptr_list<int, efl::eina::malloc_clone_allocator> list(l);
  }

If the standard efl::eina::heap_no_clone_allocator is used, the
deallocation code uses C++ delete operator, which causes undefined
behavior because the allocation was originally done with malloc.

Reviewers: cedric

CC: savio, cedric

Differential Revision: https://phab.enlightenment.org/D614
This commit is contained in:
Felipe Magno de Almeida 2014-03-10 12:25:42 +09:00 committed by Cedric BAIL
parent 416376e03c
commit 2ab6aac74d
2 changed files with 36 additions and 0 deletions

View File

@ -2,6 +2,9 @@
#define EINA_CLONE_ALLOCATORS_HH_
#include <memory>
#include <cstring>
#include <cstdlib>
#include <type_traits>
namespace efl { namespace eina {
@ -64,6 +67,25 @@ struct heap_no_copy_allocator
}
};
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, "malloc_clone_allocator can only be used with POD types");
std::free(const_cast<T*>(p));
}
};
} }
#endif

View File

@ -128,6 +128,19 @@ START_TEST(eina_cxx_ptrlist_insert)
}
END_TEST
START_TEST(eina_cxx_ptrlist_malloc_clone_allocator)
{
efl::eina::eina_init eina_init;
efl::eina::ptr_list<int, efl::eina::malloc_clone_allocator> list1;
list1.push_back(5);
list1.push_back(10);
efl::eina::ptr_list<int, efl::eina::malloc_clone_allocator> list2 = list1;
}
END_TEST
START_TEST(eina_cxx_ptrlist_constructors)
{
efl::eina::eina_init eina_init;
@ -240,4 +253,5 @@ eina_test_ptrlist(TCase* tc)
tcase_add_test(tc, eina_cxx_ptrlist_constructors);
tcase_add_test(tc, eina_cxx_ptrlist_erase);
tcase_add_test(tc, eina_cxx_ptrlist_range);
tcase_add_test(tc, eina_cxx_ptrlist_malloc_clone_allocator);
}