Commit 3d4450f7 authored by Dominik Charousset's avatar Dominik Charousset

Re-implement the message builder

parent be0e4f12
...@@ -234,6 +234,7 @@ set(CAF_CORE_TEST_SOURCES ...@@ -234,6 +234,7 @@ set(CAF_CORE_TEST_SOURCES
test/mailbox_element.cpp test/mailbox_element.cpp
test/make_config_value_field.cpp test/make_config_value_field.cpp
test/message.cpp test/message.cpp
test/message_builder.cpp
test/message_id.cpp test/message_id.cpp
test/message_lifetime.cpp test/message_lifetime.cpp
test/metaprogramming.cpp test/metaprogramming.cpp
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "caf/detail/core_export.hpp" #include "caf/detail/core_export.hpp"
#include "caf/detail/implicit_conversions.hpp" #include "caf/detail/implicit_conversions.hpp"
#include "caf/detail/message_builder_element.hpp" #include "caf/detail/message_builder_element.hpp"
#include "caf/detail/padded_size.hpp"
#include "caf/detail/type_id_list_builder.hpp" #include "caf/detail/type_id_list_builder.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/message.hpp" #include "caf/message.hpp"
...@@ -61,6 +62,7 @@ public: ...@@ -61,6 +62,7 @@ public:
using namespace detail; using namespace detail;
using value_type = strip_and_convert_t<T>; using value_type = strip_and_convert_t<T>;
static_assert(sendable<value_type>); static_assert(sendable<value_type>);
storage_size_ += padded_size_v<strip_and_convert_t<value_type>>;
types_.push_back(type_id_v<value_type>); types_.push_back(type_id_v<value_type>);
elements_.emplace_back(make_message_builder_element(std::forward<T>(x))); elements_.emplace_back(make_message_builder_element(std::forward<T>(x)));
return *this; return *this;
...@@ -91,7 +93,7 @@ public: ...@@ -91,7 +93,7 @@ public:
/// Converts the buffer to an actual message object and transfers /// Converts the buffer to an actual message object and transfers
/// ownership of the data to it, leaving this object in an invalid state. /// ownership of the data to it, leaving this object in an invalid state.
/// @warning Calling *any* member function on this object afterwards /// @warning Calling *any* member function on this object afterwards
/// is undefined behavior (dereferencing a `nullptr`) /// is undefined behavior.
message move_to_message(); message move_to_message();
/// Removes all elements from the buffer. /// Removes all elements from the buffer.
...@@ -108,6 +110,7 @@ public: ...@@ -108,6 +110,7 @@ public:
} }
private: private:
size_t storage_size_ = 0;
detail::type_id_list_builder types_; detail::type_id_list_builder types_;
std::vector<detail::message_builder_element_ptr> elements_; std::vector<detail::message_builder_element_ptr> elements_;
}; };
......
...@@ -21,18 +21,39 @@ ...@@ -21,18 +21,39 @@
namespace caf { namespace caf {
void message_builder::clear() noexcept { void message_builder::clear() noexcept {
storage_size_ = 0;
types_.clear(); types_.clear();
elements_.clear(); elements_.clear();
} }
message message_builder::to_message() const { message message_builder::to_message() const {
// TODO: implement me if (empty())
return {}; return message{};
using namespace detail;
auto vptr = malloc(sizeof(message_data) + storage_size_);
if (vptr == nullptr)
throw std::bad_alloc();
auto raw_ptr = new (vptr) message_data(types_.copy_to_list());
intrusive_cow_ptr<message_data> ptr{raw_ptr, false};
auto storage = raw_ptr->storage();
for (auto& element : elements_)
storage = element->copy_init(storage);
return message{std::move(ptr)};
} }
message message_builder::move_to_message() { message message_builder::move_to_message() {
// TODO: implement me if (empty())
return {}; return message{};
using namespace detail;
auto vptr = malloc(sizeof(message_data) + storage_size_);
if (vptr == nullptr)
throw std::bad_alloc();
auto raw_ptr = new (vptr) message_data(types_.move_to_list());
intrusive_cow_ptr<message_data> ptr{raw_ptr, false};
auto storage = raw_ptr->storage();
for (auto& element : elements_)
storage = element->move_init(storage);
return message{std::move(ptr)};
} }
} // namespace caf } // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE message_builder
#include "caf/message_builder.hpp"
#include "core-test.hpp"
#include <map>
#include <numeric>
#include <string>
#include <vector>
#include "caf/message.hpp"
#include "caf/type_id_list.hpp"
using namespace caf;
#define STEP(message) \
CAF_MESSAGE(message); \
if (true)
CAF_TEST(message builder can build messages incrermenetally) {
message_builder builder;
CAF_CHECK(builder.empty());
CAF_CHECK(builder.to_message().empty());
CAF_CHECK_EQUAL(builder.size(), 0u);
STEP("after adding 1, the message is (1)") {
builder.append(int32_t{1});
auto msg = builder.to_message();
CAF_CHECK_EQUAL(builder.size(), 1u);
CAF_CHECK_EQUAL(msg.types(), make_type_id_list<int32_t>());
CAF_CHECK_EQUAL(to_string(msg), "(1)");
}
STEP("after adding [2, 3], the message is (1, 2, 3)") {
std::vector<int32_t> xs{2, 3};
builder.append(xs.begin(), xs.end());
CAF_CHECK_EQUAL(builder.size(), 3u);
auto msg = builder.to_message();
CAF_CHECK_EQUAL(msg.types(),
(make_type_id_list<int32_t, int32_t, int32_t>()));
CAF_CHECK_EQUAL(to_string(msg), "(1, 2, 3)");
}
STEP("moving the content to a message produces the same message again") {
auto msg = builder.move_to_message();
CAF_CHECK_EQUAL(msg.types(),
(make_type_id_list<int32_t, int32_t, int32_t>()));
CAF_CHECK_EQUAL(to_string(msg), "(1, 2, 3)");
}
}
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