Skip to content

Commit

Permalink
Merge pull request STEllAR-GROUP#1736 from gentryx/master
Browse files Browse the repository at this point in the history
added convenience c-tor and begin()/end() to serialize_buffer
  • Loading branch information
hkaiser committed Aug 27, 2015
2 parents 8641841 + d178d06 commit 01a8ff0
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 201 deletions.
200 changes: 18 additions & 182 deletions hpx/runtime/serialization/serialize_buffer.hpp
@@ -1,4 +1,5 @@
// Copyright (c) 2013-2014 Hartmut Kaiser
// Copyright (c) 2015 Andreas Schaefer
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -20,13 +21,8 @@

namespace hpx { namespace serialization
{
namespace detail
{
struct serialize_buffer_no_allocator {};
}

///////////////////////////////////////////////////////////////////////////
template <typename T, typename Allocator = detail::serialize_buffer_no_allocator>
template <typename T, typename Allocator = std::allocator<T> >
class serialize_buffer
{
private:
Expand Down Expand Up @@ -57,6 +53,18 @@ namespace hpx { namespace serialization
, alloc_(alloc)
{}

explicit serialize_buffer(std::size_t size,
allocator_type const& alloc = allocator_type())
: data_()
, size_(size)
, alloc_(alloc)
{
using util::placeholders::_1;
data_.reset(alloc_.allocate(size),
util::bind(&serialize_buffer::deleter<allocator_type>,
_1, alloc_, size_));
}

// The default mode is 'copy' which is consistent with the constructor
// taking a T const * below.
serialize_buffer (T* data, std::size_t size, init_mode mode = copy,
Expand Down Expand Up @@ -193,6 +201,7 @@ namespace hpx { namespace serialization
, alloc_(alloc)
{
if (mode == copy) {
using util::placeholders::_1;
data_.reset(alloc_.allocate(size),
util::bind(&serialize_buffer::deleter<allocator_type>,
_1, alloc_, size_));
Expand All @@ -216,6 +225,9 @@ namespace hpx { namespace serialization
T* data() { return data_.get(); }
T const* data() const { return data_.get(); }

T* begin() { return data(); }
T* end() { return data() + size_; }

T& operator[](std::size_t idx) { return data_[idx]; }
T operator[](std::size_t idx) const { return data_[idx]; }

Expand Down Expand Up @@ -270,182 +282,6 @@ namespace hpx { namespace serialization
std::size_t size_;
Allocator alloc_;
};

///////////////////////////////////////////////////////////////////////////
template <typename T>
class serialize_buffer<T, detail::serialize_buffer_no_allocator>
{
private:
static void no_deleter(T*) {}

static void array_delete(T * x)
{
delete [] x;
}

public:
enum init_mode
{
copy = 0, // constructor copies data
reference = 1, // constructor does not copy data and does not
// manage the lifetime of it
take = 2 // constructor does not copy data but does take
// ownership and manages the lifetime of it
};

typedef T value_type;

serialize_buffer()
: size_(0)
{}

// The default mode is 'copy' which is consistent with the constructor
// taking a T const * below.
serialize_buffer (T* data, std::size_t size, init_mode mode = copy)
: data_(), size_(size)
{
if (mode == copy) {
data_ = boost::shared_array<T>(data,
&serialize_buffer::array_delete);
if (size != 0)
std::copy(data, data + size, data_.get());
}
else if (mode == reference) {
data_ = boost::shared_array<T>(data,
&serialize_buffer::no_deleter);
}
else {
// take ownership
data_ = boost::shared_array<T>(data,
&serialize_buffer::array_delete);
}
}

template <typename Deleter>
serialize_buffer (T* data, std::size_t size, init_mode mode,
Deleter const& deleter)
: data_(), size_(size)
{
if (mode == copy) {
data_.reset(new T[size], deleter);
if (size != 0)
std::copy(data, data + size, data_.get());
}
else {
// reference or take ownership, behavior is defined by deleter
data_ = boost::shared_array<T>(data, deleter);
}
}

template <typename Deleter>
serialize_buffer (T const* data, std::size_t size, init_mode mode,
Deleter const& deleter)
: data_(), size_(size)
{
if (mode == copy) {
data_.reset(new T[size], deleter);
if (size != 0)
std::copy(data, data + size, data_.get());
}
else if (mode == reference) {
data_ = boost::shared_array<T>(const_cast<T*>(data), deleter);
}
else {
// can't take ownership of const buffer
HPX_THROW_EXCEPTION(bad_parameter,
"serialize_buffer::serialize_buffer",
"can't take ownership of const data");
}
}

// same set of constructors, but taking const data
serialize_buffer (T const* data, std::size_t size,
init_mode mode = copy)
: data_(), size_(size)
{
if (mode == copy) {
data_ = boost::shared_array<T>(new T[size],
&serialize_buffer::array_delete);
if (size != 0)
std::copy(data, data + size, data_.get());
}
else if (mode == reference) {
data_ = boost::shared_array<T>(
const_cast<T*>(data),
&serialize_buffer::no_deleter);
}
else {
// can't take ownership of const buffer
HPX_THROW_EXCEPTION(bad_parameter,
"serialize_buffer::serialize_buffer",
"can't take ownership of const data");
}
}

template <typename Deleter>
serialize_buffer (T const* data, std::size_t size,
Deleter const& deleter)
: data_(), size_(size)
{
// create from const data implies 'copy' mode
data_.reset(new T[size], deleter);
if (size != 0)
std::copy(data, data + size, data_.get());
}

// accessors enabling data access
T* data() { return data_.get(); }
T const* data() const { return data_.get(); }

T& operator[](std::size_t idx) { return data_[idx]; }
T operator[](std::size_t idx) const { return data_[idx]; }

boost::shared_array<T> data_array() const { return data_; }

std::size_t size() const { return size_; }

private:
// serialization support
friend class hpx::serialization::access;

///////////////////////////////////////////////////////////////////////
template <typename Archive>
void save(Archive& ar, const unsigned int version) const
{
ar << size_; //-V128

if (size_ != 0)
{
ar << hpx::serialization::make_array(data_.get(), size_);
}
}

///////////////////////////////////////////////////////////////////////
template <typename Archive>
void load(Archive& ar, const unsigned int version)
{
ar >> size_; //-V128
data_.reset(new T[size_]);

if (size_ != 0)
{
ar >> hpx::serialization::make_array(data_.get(), size_);
}
}

HPX_SERIALIZATION_SPLIT_MEMBER()

// this is needed for util::any
friend bool
operator==(serialize_buffer const& rhs, serialize_buffer const& lhs)
{
return rhs.data_.get() == lhs.data_.get() && rhs.size_ == lhs.size_;
}

private:
boost::shared_array<T> data_;
std::size_t size_;
};
}}

namespace hpx { namespace traits
Expand Down
75 changes: 56 additions & 19 deletions tests/unit/serialization/serialize_buffer.cpp
@@ -1,4 +1,5 @@
// Copyright (c) 2014 Hartmut Kaiser
// Copyright (c) 2015 Andreas Schaefer
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -24,21 +25,6 @@ HPX_REGISTER_BASE_LCO_WITH_VALUE_DECLARATION(
HPX_REGISTER_BASE_LCO_WITH_VALUE(
buffer_plain_type, serialization_buffer_char);

///////////////////////////////////////////////////////////////////////////////
typedef hpx::serialization::serialize_buffer<char, std::allocator<char> >
buffer_allocator_type;

buffer_allocator_type bounce_allocator(buffer_allocator_type const& receive_buffer)
{
return receive_buffer;
}
HPX_PLAIN_ACTION(bounce_allocator);

HPX_REGISTER_BASE_LCO_WITH_VALUE_DECLARATION(
buffer_allocator_type, serialization_buffer_char_allocator);
HPX_REGISTER_BASE_LCO_WITH_VALUE(
buffer_allocator_type, serialization_buffer_char_allocator);

///////////////////////////////////////////////////////////////////////////////
template <typename Buffer, typename Action>
void test(hpx::id_type dest, char* send_buffer, std::size_t size)
Expand Down Expand Up @@ -69,13 +55,13 @@ template <typename Allocator>
void test_stateful_allocator(hpx::id_type dest, char* send_buffer,
std::size_t size, Allocator const& alloc)
{
typedef buffer_allocator_type buffer_type;
typedef buffer_plain_type buffer_type;
buffer_type recv_buffer;

std::vector<hpx::future<buffer_type> > recv_buffers;
recv_buffers.reserve(10);

bounce_allocator_action act;
bounce_plain_action act;
for(std::size_t j = 0; j != 10; ++j)
{
recv_buffers.push_back(hpx::async(act, dest,
Expand All @@ -91,6 +77,51 @@ void test_stateful_allocator(hpx::id_type dest, char* send_buffer,
}
}

template <typename T>
void test_fixed_size_initialization_for_persistent_buffers(std::size_t max_size)
{
for (std::size_t size = 1; size <= max_size; size *= 2)
{
std::vector<T> send_vec;
std::vector<T> recv_vec;
send_vec.reserve(size);
for (std::size_t i = 0; i < size; ++i) {
send_vec.push_back(size - i);
}

hpx::serialization::serialize_buffer<T> send_buffer(size);
hpx::serialization::serialize_buffer<T> recv_buffer;
std::copy(send_vec.begin(), send_vec.end(), send_buffer.begin());
recv_buffer = send_buffer;

std::copy(recv_buffer.begin(), recv_buffer.end(), std::back_inserter(recv_vec));
HPX_TEST(send_vec == recv_vec);
}
}

template <typename T>
void test_initialization_from_vector(std::size_t max_size)
{
for (std::size_t size = 1; size <= max_size; size *= 2)
{
std::vector<T> send_vec;
std::vector<T> recv_vec;
send_vec.reserve(size);
for (std::size_t i = 0; i < size; ++i) {
send_vec.push_back(size - i);
}

// default init mode is "copy"
hpx::serialization::serialize_buffer<T> send_buffer(send_vec[0], send_vec.size());
hpx::serialization::serialize_buffer<T> recv_buffer;
std::copy(send_vec.begin(), send_vec.end(), send_buffer.begin());
recv_buffer = send_buffer;

std::copy(recv_buffer.begin(), recv_buffer.end(), std::back_inserter(recv_vec));
HPX_TEST(send_vec == recv_vec);
}
}

///////////////////////////////////////////////////////////////////////////////
int hpx_main(int argc, char* argv[])
{
Expand All @@ -103,13 +134,19 @@ int hpx_main(int argc, char* argv[])
{
test<buffer_plain_type, bounce_plain_action>(
loc, send_buffer.get(), size);
test<buffer_allocator_type, bounce_allocator_action>(
loc, send_buffer.get(), size);
test_stateful_allocator(
loc, send_buffer.get(), size, std::allocator<char>());
}
}

for (std::size_t size = 1; size <= max_size; size *= 2)
{
test_fixed_size_initialization_for_persistent_buffers<int>(size);
test_fixed_size_initialization_for_persistent_buffers<char>(size);
test_fixed_size_initialization_for_persistent_buffers<float>(size);
test_fixed_size_initialization_for_persistent_buffers<double>(size);
}

return hpx::finalize();
}

Expand Down

0 comments on commit 01a8ff0

Please sign in to comment.