Unverified Commit 3d7851f8 authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #1029

Add scaffold for new type_id API
parents 13fc58a2 3640a0d9
...@@ -32,8 +32,8 @@ IndentWidth: 2 ...@@ -32,8 +32,8 @@ IndentWidth: 2
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp Language: Cpp
MacroBlockBegin: "^BEGIN_STATE$" MacroBlockBegin: "^BEGIN_STATE$|CAF_BEGIN_TYPE_ID_BLOCK"
MacroBlockEnd: "^END_STATE$" MacroBlockEnd: "^END_STATE$|CAF_END_TYPE_ID_BLOCK"
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
NamespaceIndentation: None NamespaceIndentation: None
PenaltyBreakAssignment: 25 PenaltyBreakAssignment: 25
......
...@@ -69,6 +69,7 @@ set(CAF_CORE_SOURCES ...@@ -69,6 +69,7 @@ set(CAF_CORE_SOURCES
src/detail/ini_consumer.cpp src/detail/ini_consumer.cpp
src/detail/invoke_result_visitor.cpp src/detail/invoke_result_visitor.cpp
src/detail/message_data.cpp src/detail/message_data.cpp
src/detail/meta_object.cpp
src/detail/parse.cpp src/detail/parse.cpp
src/detail/parser/chars.cpp src/detail/parser/chars.cpp
src/detail/pretty_type_name.cpp src/detail/pretty_type_name.cpp
...@@ -154,6 +155,7 @@ set(CAF_CORE_SOURCES ...@@ -154,6 +155,7 @@ set(CAF_CORE_SOURCES
src/tracing_data_factory.cpp src/tracing_data_factory.cpp
src/type_erased_tuple.cpp src/type_erased_tuple.cpp
src/type_erased_value.cpp src/type_erased_value.cpp
src/type_id_list.cpp
src/uniform_type_info_map.cpp src/uniform_type_info_map.cpp
src/uri.cpp src/uri.cpp
src/uri_builder.cpp src/uri_builder.cpp
...@@ -193,6 +195,7 @@ set(CAF_CORE_TEST_SOURCES ...@@ -193,6 +195,7 @@ set(CAF_CORE_TEST_SOURCES
test/detail/bounds_checker.cpp test/detail/bounds_checker.cpp
test/detail/ini_consumer.cpp test/detail/ini_consumer.cpp
test/detail/limited_vector.cpp test/detail/limited_vector.cpp
test/detail/meta_object.cpp
test/detail/parse.cpp test/detail/parse.cpp
test/detail/parser/read_bool.cpp test/detail/parser/read_bool.cpp
test/detail/parser/read_floating_point.cpp test/detail/parser/read_floating_point.cpp
...@@ -268,6 +271,7 @@ set(CAF_CORE_TEST_SOURCES ...@@ -268,6 +271,7 @@ set(CAF_CORE_TEST_SOURCES
test/to_string.cpp test/to_string.cpp
test/tracing_data.cpp test/tracing_data.cpp
test/type_erased_tuple.cpp test/type_erased_tuple.cpp
test/type_id_list.cpp
test/typed_response_promise.cpp test/typed_response_promise.cpp
test/typed_spawn.cpp test/typed_spawn.cpp
test/unit.cpp test/unit.cpp
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 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. *
******************************************************************************/
#pragma once
#include <algorithm>
#include <cstddef>
#include "caf/binary_deserializer.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/byte.hpp"
#include "caf/deserializer.hpp"
#include "caf/detail/meta_object.hpp"
#include "caf/error.hpp"
#include "caf/serializer.hpp"
namespace caf::detail {
template <class T>
meta_object make_meta_object(const char* type_name) {
return {
type_name,
[](void* ptr) noexcept { reinterpret_cast<T*>(ptr)->~T(); },
[](void* ptr) { new (ptr) T(); },
[](caf::binary_serializer& sink, const void* ptr) {
return sink(*reinterpret_cast<const T*>(ptr));
},
[](caf::binary_deserializer& source, void* ptr) {
return source(*reinterpret_cast<T*>(ptr));
},
[](caf::serializer& sink, const void* ptr) {
return sink(*reinterpret_cast<const T*>(ptr));
},
[](caf::deserializer& source, void* ptr) {
return source(*reinterpret_cast<T*>(ptr));
},
};
}
template <class... Ts>
void register_meta_objects(size_t first_id) {
auto xs = resize_global_meta_objects(first_id + sizeof...(Ts));
meta_object src[] = {make_meta_object<Ts>()...};
std::copy(src, src + sizeof...(Ts), xs.begin() + first_id);
}
} // namespace caf::detail
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 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. *
******************************************************************************/
#pragma once
#include <cstddef>
#include <cstdint>
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
namespace caf::detail {
/// Enables destroying, construcing and serializing objects through type-erased
/// pointers.
struct meta_object {
/// Stores a human-readable representation of the type's name.
const char* type_name = nullptr;
/// Calls the destructor for given object.
void (*destroy)(void*) noexcept;
/// Creates a new object at given memory location by calling the default
/// constructor.
void (*default_construct)(void*);
/// Applies an object to a binary serializer.
error_code<sec> (*save_binary)(caf::binary_serializer&, const void*);
/// Applies an object to a binary deserializer.
error_code<sec> (*load_binary)(caf::binary_deserializer&, void*);
/// Applies an object to a generic serializer.
caf::error (*save)(caf::serializer&, const void*);
/// Applies an object to a generic deserializer.
caf::error (*load)(caf::deserializer&, void*);
};
/// Returns the global storage for all meta objects. The ::type_id of an object
/// is the index for accessing the corresonding meta object.
CAF_CORE_EXPORT span<const meta_object> global_meta_objects();
/// Returns the global meta object for given type ID.
CAF_CORE_EXPORT meta_object& global_meta_object(type_id_t id);
/// Clears the array for storing global meta objects.
/// @warning intended for unit testing only!
CAF_CORE_EXPORT void clear_global_meta_objects();
/// Resizes and returns the global storage for all meta objects. Existing
/// entries are copied to the new memory region. The new size *must* grow the
/// array.
/// @warning calling this after constructing any ::actor_system is unsafe and
/// causes undefined behavior.
CAF_CORE_EXPORT span<meta_object> resize_global_meta_objects(size_t size);
/// Sets the meta objects in range `[first_id, first_id + xs.size)` to `xs`.
/// Resizes the global meta object if needed. Aborts the program if the range
/// already contains meta objects.
/// @warning calling this after constructing any ::actor_system is unsafe and
/// causes undefined behavior.
CAF_CORE_EXPORT void set_global_meta_objects(type_id_t first_id,
span<const meta_object> xs);
} // namespace caf::detail
...@@ -40,13 +40,17 @@ template <class> class intrusive_ptr; ...@@ -40,13 +40,17 @@ template <class> class intrusive_ptr;
template <class> class optional; template <class> class optional;
template <class> class param; template <class> class param;
template <class> class span; template <class> class span;
template <class> class stream; template <class> class stream;;
template <class> class stream_sink; template <class> class stream_sink;
template <class> class stream_source; template <class> class stream_source;
template <class> class trivial_match_case; template <class> class trivial_match_case;
template <class> class weak_intrusive_ptr; template <class> class weak_intrusive_ptr;
template <class> struct timeout_definition; template <class> struct timeout_definition;
template <class> struct type_id;
template <uint16_t> struct type_by_id;
template <uint16_t> struct type_name_by_id;
// -- 2 param templates -------------------------------------------------------- // -- 2 param templates --------------------------------------------------------
...@@ -187,6 +191,7 @@ using ip_endpoint = ipv6_endpoint; ...@@ -187,6 +191,7 @@ using ip_endpoint = ipv6_endpoint;
using ip_subnet = ipv6_subnet; using ip_subnet = ipv6_subnet;
using settings = dictionary<config_value>; using settings = dictionary<config_value>;
using stream_slot = uint16_t; using stream_slot = uint16_t;
using type_id_t = uint16_t;
// -- functions ---------------------------------------------------------------- // -- functions ----------------------------------------------------------------
...@@ -272,6 +277,8 @@ class message_data; ...@@ -272,6 +277,8 @@ class message_data;
class private_thread; class private_thread;
class uri_impl; class uri_impl;
struct meta_object;
// enable intrusive_ptr<uri_impl> with forward declaration only // enable intrusive_ptr<uri_impl> with forward declaration only
CAF_CORE_EXPORT void intrusive_ptr_add_ref(const uri_impl*); CAF_CORE_EXPORT void intrusive_ptr_add_ref(const uri_impl*);
CAF_CORE_EXPORT void intrusive_ptr_release(const uri_impl*); CAF_CORE_EXPORT void intrusive_ptr_release(const uri_impl*);
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 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. *
******************************************************************************/
#pragma once
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <utility>
#include "caf/detail/make_meta_object.hpp"
#include "caf/detail/meta_object.hpp"
#include "caf/span.hpp"
#include "caf/type_id.hpp"
namespace caf::detail {
template <uint16_t First, uint16_t Second>
struct type_id_pair {};
template <class Range, uint16_t... Is>
struct type_id_sequence_helper;
template <uint16_t End, uint16_t... Is>
struct type_id_sequence_helper<type_id_pair<End, End>, Is...> {
using type = std::integer_sequence<uint16_t, Is...>;
};
template <uint16_t Begin, uint16_t End, uint16_t... Is>
struct type_id_sequence_helper<type_id_pair<Begin, End>, Is...> {
using type = typename type_id_sequence_helper<type_id_pair<Begin + 1, End>,
Is..., Begin>::type;
};
template <uint16_t Begin, uint16_t End>
using make_type_id_sequence =
typename type_id_sequence_helper<type_id_pair<Begin, End>>::type;
} // namespace caf::detail
namespace caf {
/// @warning calling this after constructing any ::actor_system is unsafe and
/// causes undefined behavior.
template <uint16_t... Is>
void init_global_meta_objects_impl(std::integer_sequence<uint16_t, Is...>,
uint16_t first_id) {
detail::meta_object src[] = {
detail::make_meta_object<type_by_id_t<Is>>(type_name_by_id_v<Is>)...,
};
detail::set_global_meta_objects(first_id, make_span(src));
}
/// Initializes the global meta object table with all types in `ProjectIds`.
/// @warning calling this after constructing any ::actor_system is unsafe and
/// causes undefined behavior.
template <class ProjectIds>
void init_global_meta_objects() {
static constexpr uint16_t begin = ProjectIds::first;
static constexpr uint16_t end = ProjectIds::last + 1;
init_global_meta_objects_impl(detail::make_type_id_sequence<begin, end>{},
begin);
}
} // namespace caf
This diff is collapsed.
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 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. *
******************************************************************************/
#pragma once
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include "caf/detail/comparable.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/type_id.hpp"
namespace caf {
/// A list of type IDs, stored in a size-prefix, contiguous memory block.
class type_id_list : detail::comparable<type_id_list> {
public:
using pointer = const type_id_t*;
constexpr explicit type_id_list(pointer data) noexcept : data_(data) {
// nop
}
constexpr type_id_list(const type_id_list&) noexcept = default;
type_id_list& operator=(const type_id_list&) noexcept = default;
/// Queries whether this type list contains data, i.e, `data() != nullptr`.
constexpr operator bool() const noexcept {
return data_ != nullptr;
}
/// Returns the raw pointer to the size-prefixed list.
constexpr pointer data() const noexcept {
return data_;
}
/// Returns the number of elements in the list.
/// @pre `data() != nullptr`
constexpr size_t size() const noexcept {
return data_[0];
}
/// Returns the type ID at `index`.
/// @pre `data() != nullptr`
constexpr type_id_t operator[](size_t index) const noexcept {
return data_[index + 1];
}
/// Compares this list to `other`.
int compare(type_id_list other) const noexcept {
return memcmp(data_, other.data_, size() * sizeof(type_id_t));
}
private:
pointer data_;
};
/// @private
template <class... Ts>
struct make_type_id_list_helper {
static constexpr inline type_id_t data[]
= {static_cast<type_id_t>(sizeof...(Ts)), type_id_v<Ts>...};
};
/// Constructs a ::type_id_list from the template parameter pack `Ts`.
/// @relates type_id_list
template <class... Ts>
constexpr type_id_list make_type_id_list() {
return type_id_list{make_type_id_list_helper<Ts...>::data};
}
/// @relates type_id_list
CAF_CORE_EXPORT std::string to_string(type_id_list xs);
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 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. *
******************************************************************************/
#include "caf/detail/meta_object.hpp"
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "caf/config.hpp"
#include "caf/span.hpp"
namespace caf::detail {
#define fatal(str) \
do { \
fprintf(stderr, "FATAL: " str "\n"); \
abort(); \
} while (false)
namespace {
// Stores global type information.
meta_object* meta_objects;
// Stores the size of `meta_objects`.
size_t meta_objects_size;
// Make sure to clean up all meta objects on program exit.
struct meta_objects_cleanup {
~meta_objects_cleanup() {
delete[] meta_objects;
}
} cleanup_helper;
} // namespace
span<const meta_object> global_meta_objects() {
return {meta_objects, meta_objects_size};
}
meta_object& global_meta_object(type_id_t id) {
CAF_ASSERT(id < meta_objects_size);
return meta_objects[id];
}
void clear_global_meta_objects() {
if (meta_objects != nullptr) {
delete[] meta_objects;
meta_objects = nullptr;
meta_objects_size = 0;
}
}
span<meta_object> resize_global_meta_objects(size_t size) {
if (size <= meta_objects_size)
fatal("resize_global_meta_objects called with a new size that does not "
"grow the array");
auto new_storage = new meta_object[size];
std::copy(meta_objects, meta_objects + meta_objects_size, new_storage);
delete[] meta_objects;
meta_objects = new_storage;
meta_objects_size = size;
return {new_storage, size};
}
void set_global_meta_objects(type_id_t first_id, span<const meta_object> xs) {
auto new_size = first_id + xs.size();
if (first_id < meta_objects_size) {
if (new_size > meta_objects_size)
fatal("set_global_meta_objects called with "
"'first_id < meta_objects_size' and "
"'new_size > meta_objects_size'");
auto out = meta_objects + first_id;
for (const auto& x : xs) {
if (out->type_name == nullptr) {
// We support calling set_global_meta_objects for building the global
// table chunk-by-chunk.
*out = x;
} else if (strcmp(out->type_name, x.type_name) == 0) {
// nop: set_global_meta_objects implements idempotency.
} else {
fprintf(stderr,
"FATAL: type ID %d already assigned to %s (tried to override "
"with %s)\n",
static_cast<int>(std::distance(meta_objects, out)),
out->type_name, x.type_name);
abort();
}
++out;
}
return;
}
auto dst = resize_global_meta_objects(first_id + xs.size());
std::copy(xs.begin(), xs.end(), dst.begin() + first_id);
}
} // namespace caf::detail
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 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. *
******************************************************************************/
#include "caf/type_id_list.hpp"
#include "caf/detail/meta_object.hpp"
namespace caf {
std::string to_string(type_id_list xs) {
if (!xs || xs.size() == 0)
return "[]";
std::string result;
result += '[';
result += detail::global_meta_object(xs[0]).type_name;
for (size_t index = 1; index < xs.size(); ++index) {
result += ", ";
result += detail::global_meta_object(xs[index]).type_name;
}
result += ']';
return result;
}
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 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 detail.meta_object
#include "caf/detail/meta_object.hpp"
#include "caf/test/dsl.hpp"
#include <tuple>
#include <type_traits>
#include "caf/binary_deserializer.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/detail/make_meta_object.hpp"
#include "caf/init_global_meta_objects.hpp"
using namespace std::string_literals;
using namespace caf;
using namespace caf::detail;
namespace {
struct i32_wrapper {
static size_t instances;
int32_t value;
i32_wrapper() : value(0) {
++instances;
}
~i32_wrapper() {
--instances;
}
};
template <class Inspector>
auto inspect(Inspector& f, i32_wrapper& x) {
return f(x.value);
}
size_t i32_wrapper::instances = 0;
struct i64_wrapper {
static size_t instances;
int64_t value;
i64_wrapper() : value(0) {
++instances;
}
~i64_wrapper() {
--instances;
}
};
template <class Inspector>
auto inspect(Inspector& f, i64_wrapper& x) {
return f(x.value);
}
size_t i64_wrapper::instances = 0;
} // namespace
CAF_BEGIN_TYPE_ID_BLOCK(meta_object_suite, caf::first_custom_type_id)
CAF_ADD_TYPE_ID(meta_object_suite, i32_wrapper)
CAF_ADD_TYPE_ID(meta_object_suite, i64_wrapper)
CAF_END_TYPE_ID_BLOCK(meta_object_suite)
namespace caf {
static_assert(meta_object_suite_first_type_id == first_custom_type_id);
static_assert(meta_object_suite_last_type_id == first_custom_type_id + 1);
static_assert(type_id<i32_wrapper>::value == first_custom_type_id);
static_assert(type_id<i64_wrapper>::value == first_custom_type_id + 1);
static_assert(type_id<i32_wrapper>::value == meta_object_suite_first_type_id);
static_assert(type_id<i64_wrapper>::value == meta_object_suite_last_type_id);
} // namespace caf
namespace {
struct fixture {
fixture() {
CAF_ASSERT(i32_wrapper::instances == 0);
clear_global_meta_objects();
}
};
} // namespace
CAF_TEST_FIXTURE_SCOPE(meta_object_suite, fixture)
CAF_TEST(meta objects allow construction and destruction of objects) {
auto meta_i32_wrapper = make_meta_object<i32_wrapper>("i32_wrapper");
std::aligned_storage_t<sizeof(i32_wrapper), alignof(i32_wrapper)> storage;
meta_i32_wrapper.default_construct(&storage);
CAF_CHECK_EQUAL(i32_wrapper::instances, 1u);
meta_i32_wrapper.destroy(&storage);
CAF_CHECK_EQUAL(i32_wrapper::instances, 0u);
}
CAF_TEST(meta objects allow serialization of objects) {
byte_buffer buf;
auto meta_i32_wrapper = make_meta_object<i32_wrapper>("i32_wrapper");
std::aligned_storage_t<sizeof(i32_wrapper), alignof(i32_wrapper)> storage;
binary_serializer sink{nullptr, buf};
meta_i32_wrapper.default_construct(&storage);
CAF_CHECK_EQUAL(i32_wrapper::instances, 1u);
meta_i32_wrapper.save_binary(sink, &storage);
i32_wrapper copy;
CAF_CHECK_EQUAL(i32_wrapper::instances, 2u);
copy.value = 42;
binary_deserializer source{nullptr, buf};
meta_i32_wrapper.load_binary(source, &copy);
CAF_CHECK_EQUAL(copy.value, 0);
meta_i32_wrapper.destroy(&storage);
CAF_CHECK_EQUAL(i32_wrapper::instances, 1u);
}
CAF_TEST(resizing the global meta objects keeps entries) {
auto eq = [](const meta_object& x, const meta_object& y) {
return std::tie(x.destroy, x.default_construct, x.save_binary,
x.load_binary, x.save, x.load)
== std::tie(y.destroy, y.default_construct, y.save_binary,
y.load_binary, y.save, y.load);
};
auto meta_i32 = make_meta_object<int32_t>("int32_t");
auto xs1 = resize_global_meta_objects(1);
CAF_CHECK_EQUAL(xs1.size(), 1u);
xs1[0] = meta_i32;
CAF_CHECK(eq(xs1[0], meta_i32));
auto xs2 = resize_global_meta_objects(2);
CAF_CHECK_EQUAL(xs2.size(), 2u);
CAF_CHECK(eq(xs2[0], meta_i32));
resize_global_meta_objects(3);
CAF_CHECK(eq(global_meta_object(0), meta_i32));
}
CAF_TEST(init_global_meta_objects takes care of creating a meta object table) {
init_global_meta_objects<meta_object_suite_type_ids>();
auto xs = global_meta_objects();
CAF_REQUIRE_EQUAL(xs.size(), meta_object_suite_last_type_id + 1u);
CAF_CHECK_EQUAL(type_name_by_id_v<type_id_v<i32_wrapper>>, "i32_wrapper"s);
CAF_CHECK_EQUAL(type_name_by_id_v<type_id_v<i64_wrapper>>, "i64_wrapper"s);
CAF_CHECK_EQUAL(xs[type_id_v<i32_wrapper>].type_name, "i32_wrapper"s);
CAF_CHECK_EQUAL(xs[type_id_v<i64_wrapper>].type_name, "i64_wrapper"s);
CAF_MESSAGE("calling init_global_meta_objects again is a no-op");
init_global_meta_objects<meta_object_suite_type_ids>();
auto ys = global_meta_objects();
auto same = [](const auto& x, const auto& y) {
return x.type_name == y.type_name;
};
CAF_CHECK(std::equal(xs.begin(), xs.end(), ys.begin(), ys.end(), same));
CAF_MESSAGE("init_global_meta_objects can initialize allocated chunks");
CAF_CHECK_EQUAL(global_meta_object(type_id_v<float>).type_name, nullptr);
init_global_meta_objects<builtin_type_ids>();
CAF_MESSAGE("again, calling init_global_meta_objects again is a no-op");
init_global_meta_objects<builtin_type_ids>();
CAF_CHECK_EQUAL(global_meta_object(type_id_v<float>).type_name, "float"s);
}
CAF_TEST_FIXTURE_SCOPE_END()
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 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 type_id_list
#include "caf/type_id_list.hpp"
#include "caf/test/dsl.hpp"
#include "caf/init_global_meta_objects.hpp"
using namespace caf;
CAF_TEST(lists store the size at index 0) {
type_id_t data[] = {3, 1, 2, 4};
type_id_list xs{data};
CAF_CHECK_EQUAL(xs.size(), 3u);
CAF_CHECK_EQUAL(xs[0], 1u);
CAF_CHECK_EQUAL(xs[1], 2u);
CAF_CHECK_EQUAL(xs[2], 4u);
}
CAF_TEST(lists are comparable) {
type_id_t data[] = {3, 1, 2, 4};
type_id_list xs{data};
type_id_t data_copy[] = {3, 1, 2, 4};
type_id_list ys{data_copy};
CAF_CHECK_EQUAL(xs, ys);
data_copy[1] = 10;
CAF_CHECK_NOT_EQUAL(xs, ys);
CAF_CHECK_LESS(xs, ys);
}
CAF_TEST(make_type_id_list constructs a list from types) {
auto xs = make_type_id_list<uint8_t, bool, float>();
CAF_CHECK_EQUAL(xs.size(), 3u);
CAF_CHECK_EQUAL(xs[0], type_id_v<uint8_t>);
CAF_CHECK_EQUAL(xs[1], type_id_v<bool>);
CAF_CHECK_EQUAL(xs[2], type_id_v<float>);
}
CAF_TEST(type ID lists are convertible to strings) {
detail::clear_global_meta_objects();
init_global_meta_objects<builtin_type_ids>();
auto xs = make_type_id_list<uint8_t, bool, float>();
CAF_CHECK_EQUAL(to_string(xs), "[uint8_t, bool, float]");
}
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