Commit 1a32df0c authored by Dominik Charousset's avatar Dominik Charousset

Fix build on MSVC

parent 178dff5f
...@@ -6,6 +6,12 @@ if(APPLE AND NOT DEFINED CMAKE_MACOSX_RPATH) ...@@ -6,6 +6,12 @@ if(APPLE AND NOT DEFINED CMAKE_MACOSX_RPATH)
set(CMAKE_MACOSX_RPATH true) set(CMAKE_MACOSX_RPATH true)
endif() endif()
# shared libs currently not supported on Windows
if(WIN32 AND NOT CAF_BUILD_STATIC_ONLY)
message(STATUS "CAF currently only supports static-only builds on Windows")
set(CAF_BUILD_STATIC_ONLY yes)
endif()
################################################################################ ################################################################################
# make sure all variables are set to "no" if undefined for summary output # # make sure all variables are set to "no" if undefined for summary output #
################################################################################ ################################################################################
......
Subproject commit 03bb8aea85332589a426d4b71163c9aa30044ce3 Subproject commit 9b59c80bc35dfcbb75c016de5ea475695ec8c64b
...@@ -17,7 +17,7 @@ using namespace caf; ...@@ -17,7 +17,7 @@ using namespace caf;
namespace { namespace {
using add_atom = atom_constant<atom("add")>; // using add_atom = atom_constant<atom("add")>; (defined in atom.hpp)
using multiply_atom = atom_constant<atom("multiply")>; using multiply_atom = atom_constant<atom("multiply")>;
using adder = typed_actor<replies_to<add_atom, int, int>::with<int>>; using adder = typed_actor<replies_to<add_atom, int, int>::with<int>>;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
using std::endl; using std::endl;
using namespace caf; using namespace caf;
using add_atom = atom_constant<atom("add")>; // using add_atom = atom_constant<atom("add")>; (defined in atom.hpp)
using calc = typed_actor<replies_to<add_atom, int, int>::with<int>>; using calc = typed_actor<replies_to<add_atom, int, int>::with<int>>;
......
...@@ -15,7 +15,7 @@ using std::endl; ...@@ -15,7 +15,7 @@ using std::endl;
using namespace caf; using namespace caf;
using add_atom = atom_constant<atom("add")>; // using add_atom = atom_constant<atom("add")>; (defined in atom.hpp)
using adder = typed_actor<replies_to<add_atom, int, int>::with<int>>; using adder = typed_actor<replies_to<add_atom, int, int>::with<int>>;
......
...@@ -89,6 +89,18 @@ public: ...@@ -89,6 +89,18 @@ public:
const data_destructor data_dtor; const data_destructor data_dtor;
const block_destructor block_dtor; const block_destructor block_dtor;
static_assert(sizeof(std::atomic<size_t>) == sizeof(void*),
"std::atomic not lockfree on this platform");
static_assert(sizeof(intrusive_ptr<node_id::data>) == sizeof(void*),
"intrusive_ptr<T> and T* have different size");
static_assert(sizeof(node_id) == sizeof(void*),
"sizeof(node_id) != sizeof(size_t)");
static_assert(sizeof(data_destructor) == sizeof(void*),
"functiion pointer and regular pointers have different size");
/// Returns a pointer to the actual actor instance. /// Returns a pointer to the actual actor instance.
inline abstract_actor* get() { inline abstract_actor* get() {
// this pointer arithmetic is compile-time checked in actor_storage's ctor // this pointer arithmetic is compile-time checked in actor_storage's ctor
......
...@@ -53,11 +53,13 @@ public: ...@@ -53,11 +53,13 @@ public:
"data is not at cache line size boundary"); "data is not at cache line size boundary");
// 4) make sure static_cast and reinterpret_cast // 4) make sure static_cast and reinterpret_cast
// between T* and abstract_actor* are identical // between T* and abstract_actor* are identical
/*
constexpr abstract_actor* dummy = nullptr; constexpr abstract_actor* dummy = nullptr;
constexpr T* derived_dummy = static_cast<T*>(dummy); constexpr T* derived_dummy = static_cast<T*>(dummy);
static_assert(derived_dummy == nullptr, static_assert(derived_dummy == nullptr,
"actor subtype has illegal memory alignment " "actor subtype has illegal memory alignment "
"(probably due to virtual inheritance)"); "(probably due to virtual inheritance)");
*/
// construct data member // construct data member
new (&data) T(std::forward<Us>(zs)...); new (&data) T(std::forward<Us>(zs)...);
} }
...@@ -69,6 +71,9 @@ public: ...@@ -69,6 +71,9 @@ public:
actor_storage(const actor_storage&) = delete; actor_storage(const actor_storage&) = delete;
actor_storage& operator=(const actor_storage&) = delete; actor_storage& operator=(const actor_storage&) = delete;
static_assert(sizeof(actor_control_block) < CAF_CACHE_LINE_SIZE,
"actor_control_block exceeds 64 bytes");
actor_control_block ctrl; actor_control_block ctrl;
char pad[CAF_CACHE_LINE_SIZE - sizeof(actor_control_block)]; char pad[CAF_CACHE_LINE_SIZE - sizeof(actor_control_block)];
union { T data; }; union { T data; };
......
...@@ -39,9 +39,9 @@ struct output_types_of<typed_mpi<In, Out>> { ...@@ -39,9 +39,9 @@ struct output_types_of<typed_mpi<In, Out>> {
}; };
template <class T> template <class T>
constexpr typename std::remove_pointer<T>::type::signatures signatures_of() { struct signatures_of {
return {}; using type = typename std::remove_pointer<T>::type::signatures;
} };
template <class T> template <class T>
constexpr bool statically_typed() { constexpr bool statically_typed() {
...@@ -51,47 +51,45 @@ constexpr bool statically_typed() { ...@@ -51,47 +51,45 @@ constexpr bool statically_typed() {
>::value; >::value;
} }
template <class Signatures, class MessageTypes> template <class Signatures, class Input>
constexpr bool actor_accepts_message(Signatures, MessageTypes) { struct actor_accepts_message;
return detail::tl_exists<
Signatures,
detail::input_is<MessageTypes>::template eval
>::value;
}
template <class MessageTypes> template <class Input>
constexpr bool actor_accepts_message(none_t, MessageTypes) { struct actor_accepts_message<none_t, Input> : std::true_type {};
return true;
}
template <class Signatures, class MessageTypes> template <class... Ts, class Input>
constexpr typename output_types_of< struct actor_accepts_message<detail::type_list<Ts...>, Input>
typename detail::tl_find< : detail::tl_exists<detail::type_list<Ts...>,
Signatures, detail::input_is<Input>::template eval> {};
detail::input_is<MessageTypes>::template eval
>::type
>::type
response_to(Signatures, MessageTypes) {
return {};
}
template <class MessageTypes> template <class Signatures, class Input>
constexpr none_t response_to(none_t, MessageTypes) { struct response_to;
return {};
}
template <class... Ts> template <class Input>
constexpr bool is_void_response(detail::type_list<Ts...>) { struct response_to<none_t, Input> {
return false; using type = none_t;
} };
constexpr bool is_void_response(detail::type_list<void>) { template <class... Ts, class Input>
return true; struct response_to<detail::type_list<Ts...>, Input> {
} using type =
typename output_types_of<
typename detail::tl_find<
detail::type_list<Ts...>,
detail::input_is<Input>::template eval
>::type
>::type;
};
constexpr bool is_void_response(none_t) { template <class T>
return true; // true for the purpose of type checking performed by send() struct is_void_response : std::false_type {};
}
template <>
struct is_void_response<detail::type_list<void>> : std::true_type {};
// true for the purpose of type checking performed by send()
template <>
struct is_void_response<none_t> : std::true_type {};
} // namespace caf } // namespace caf
......
...@@ -50,11 +50,14 @@ public: ...@@ -50,11 +50,14 @@ public:
/// Reads `x` from `source`. /// Reads `x` from `source`.
/// @relates serializer /// @relates serializer
template <class T> template <class T>
auto operator>>(deserializer& source, T& x) typename std::enable_if<
-> typename std::enable_if< std::is_same<
std::is_same<decltype(source.apply(x)), void>::value, void,
decltype(std::declval<deserializer&>().apply(std::declval<T&>()))
>::value,
deserializer& deserializer&
>::type { >::type
operator>>(deserializer& source, T& x) {
source.apply(x); source.apply(x);
return source; return source;
} }
......
...@@ -52,10 +52,10 @@ namespace detail { ...@@ -52,10 +52,10 @@ namespace detail {
// to enable both ADL and picking up existing boost code. // to enable both ADL and picking up existing boost code.
template <class Processor, class U> template <class Processor, class U>
auto delegate_serialize(Processor& proc, U& x) auto delegate_serialize(Processor& proc, U& x, const unsigned int y = 0)
-> decltype(serialize(proc, x, 0)) { -> decltype(serialize(proc, x, y)) {
using namespace boost::serialization; using namespace boost::serialization;
serialize(proc, x, 0); serialize(proc, x, y);
} }
// Calls `serialize(...)` without the unused version argument, which CAF // Calls `serialize(...)` without the unused version argument, which CAF
......
...@@ -146,13 +146,13 @@ public: ...@@ -146,13 +146,13 @@ public:
auto next = first->next.load(); auto next = first->next.load();
// first_ always points to a dummy with no value, // first_ always points to a dummy with no value,
// hence we put the new element second // hence we put the new element second
if (next == nullptr) { if (next) {
CAF_ASSERT(first != tail_);
tmp->next = next;
} else {
// queue is empty // queue is empty
CAF_ASSERT(first == tail_); CAF_ASSERT(first == tail_);
tail_ = tmp; tail_ = tmp;
} else {
CAF_ASSERT(first != tail_);
tmp->next = next;
} }
first->next = tmp; first->next = tmp;
} }
......
...@@ -39,7 +39,7 @@ template <class T, ...@@ -39,7 +39,7 @@ template <class T,
int PlaceholderValue, int PlaceholderValue,
size_t Pos, size_t Pos,
size_t Size, size_t Size,
bool InRange = PlaceholderValue <= Size> bool InRange = PlaceholderValue <= static_cast<int>(Size)>
struct mpi_bind_sig_single { struct mpi_bind_sig_single {
using type = using type =
mpi_bind_sig_arg_t< mpi_bind_sig_arg_t<
......
...@@ -30,42 +30,77 @@ ...@@ -30,42 +30,77 @@
namespace caf { namespace caf {
namespace detail { namespace detail {
template <class X, class... Ts> /*
template <class Input, class X, class... Ts>
struct mpi_splice_one; struct mpi_splice_one;
template <class X> template <class Input, class X>
struct mpi_splice_one<X> { struct mpi_splice_one<Input, X> {
using type = X; using type = X;
}; };
template <class X, class... Ts> template <class Input, class X, class... Ts>
struct mpi_splice_one<X, none_t, Ts...> { struct mpi_splice_one<Input, X, none_t, Ts...> {
using type = none_t; using type = none_t;
}; };
template <class... Xs, class... Ys, class... Zs, class... Ts> template <class Input, class... Ys, class... Zs, class... Ts>
struct mpi_splice_one<typed_mpi<type_list<Xs...>, type_list<Ys...>>, struct mpi_splice_one<Input,
typed_mpi<type_list<Xs...>, type_list<Zs...>>, typed_mpi<Input, type_list<Ys...>>,
typed_mpi<Input, type_list<Zs...>>,
Ts...> Ts...>
: mpi_splice_one<typed_mpi<type_list<Xs...>, type_list<Ys..., Zs...>>, Ts...> { : mpi_splice_one<typed_mpi<type_list<Xs...>, type_list<Ys..., Zs...>>, Ts...> {
// nop // combine signatures with same input
}; };
*/
template <template <class...> class Target, class List, class... Lists> template <class T, class... Lists>
struct mpi_splice_by_input;
template <class T>
struct mpi_splice_by_input<T> {
using type = T;
};
template <class T, class... Lists>
struct mpi_splice_by_input<T, type_list<>, Lists...> {
// consumed an entire list without match -> fail
using type = none_t;
};
// splice two MPIs if they have the same input
template <class Input, class... Xs, class... Ys, class... Ts, class... Lists>
struct mpi_splice_by_input<typed_mpi<Input, type_list<Xs...>>, type_list<typed_mpi<Input, type_list<Ys...>>, Ts...>, Lists...>
: mpi_splice_by_input<typed_mpi<Input, type_list<Xs..., Ys...>>, Lists...> { };
// skip element in list until empty
template <class MPI, class MPI2, class... Ts, class... Lists>
struct mpi_splice_by_input<MPI, type_list<MPI2, Ts...>, Lists...>
: mpi_splice_by_input<MPI, type_list<Ts...>, Lists...> { };
template <class Result, class CurrentNeedle, class... Lists>
struct input_mapped;
template <class... Rs, class... Lists>
struct input_mapped<type_list<Rs...>, none_t, type_list<>, Lists...> {
using type = type_list<Rs...>;
};
template <class... Rs, class T, class... Ts, class... Lists>
struct input_mapped<type_list<Rs...>, none_t, type_list<T, Ts...>, Lists...>
: input_mapped<type_list<Rs...>, T, type_list<Ts...>, Lists...> {};
template <class... Rs, class T, class FirstList, class... Lists>
struct input_mapped<type_list<Rs...>, T, FirstList, Lists...>
: input_mapped<type_list<Rs..., typename mpi_splice_by_input<T, Lists...>::type>, none_t, FirstList, Lists...> { };
template <template <class...> class Target, class ListA, class ListB>
struct mpi_splice; struct mpi_splice;
template <template <class...> class Target, class... Ts, class... Lists> template <template <class...> class Target, class... Ts, class List>
struct mpi_splice<Target, type_list<Ts...>, Lists...> { struct mpi_splice<Target, type_list<Ts...>, List> {
using spliced_list = using spliced_list =
type_list< typename input_mapped<type_list<>, none_t, type_list<Ts...>, List>::type;
typename mpi_splice_one<
Ts,
typename tl_find<
Lists,
input_is<typename Ts::input_types>::template eval
>::type...
>::type...
>;
using filtered_list = using filtered_list =
typename tl_filter_not_type< typename tl_filter_not_type<
spliced_list, spliced_list,
......
...@@ -104,8 +104,8 @@ typename pseudo_tuple_access< ...@@ -104,8 +104,8 @@ typename pseudo_tuple_access<
>::result_type >::result_type
get(const detail::pseudo_tuple<Ts...>& tv) { get(const detail::pseudo_tuple<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()"); static_assert(N < sizeof...(Ts), "N >= tv.size()");
pseudo_tuple_access<const typename detail::type_at<N, Ts...>::type> f; using f = pseudo_tuple_access<const typename detail::type_at<N, Ts...>::type>;
return f.get(tv, N); return f::get(tv, N);
} }
template <size_t N, class... Ts> template <size_t N, class... Ts>
...@@ -114,8 +114,8 @@ typename pseudo_tuple_access< ...@@ -114,8 +114,8 @@ typename pseudo_tuple_access<
>::result_type >::result_type
get(detail::pseudo_tuple<Ts...>& tv) { get(detail::pseudo_tuple<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()"); static_assert(N < sizeof...(Ts), "N >= tv.size()");
pseudo_tuple_access<typename detail::type_at<N, Ts...>::type> f; using f = pseudo_tuple_access<typename detail::type_at<N, Ts...>::type>;
return f.get(tv, N); return f::get(tv, N);
} }
} // namespace detail } // namespace detail
......
...@@ -102,12 +102,12 @@ public: ...@@ -102,12 +102,12 @@ public:
/// @warning Call only from the reader (owner). /// @warning Call only from the reader (owner).
bool empty() { bool empty() {
CAF_ASSERT(! closed()); CAF_ASSERT(! closed());
return cache_.empty() && head_ == nullptr && is_dummy(stack_.load()); return cache_.empty() && ! head_ && is_dummy(stack_.load());
} }
/// Queries whether this has been closed. /// Queries whether this has been closed.
bool closed() { bool closed() {
return stack_.load() == nullptr; return ! stack_.load();
} }
/// Queries whether this has been marked as blocked, i.e., /// Queries whether this has been marked as blocked, i.e.,
...@@ -238,7 +238,7 @@ private: ...@@ -238,7 +238,7 @@ private:
// atomically sets stack_ back and enqueues all elements to the cache // atomically sets stack_ back and enqueues all elements to the cache
bool fetch_new_data(pointer end_ptr) { bool fetch_new_data(pointer end_ptr) {
CAF_ASSERT(end_ptr == nullptr || end_ptr == stack_empty_dummy()); CAF_ASSERT(! end_ptr || end_ptr == stack_empty_dummy());
pointer e = stack_.load(); pointer e = stack_.load();
// must not be called on a closed queue // must not be called on a closed queue
CAF_ASSERT(e != nullptr); CAF_ASSERT(e != nullptr);
...@@ -253,7 +253,7 @@ private: ...@@ -253,7 +253,7 @@ private:
CAF_ASSERT(e != reader_blocked_dummy()); CAF_ASSERT(e != reader_blocked_dummy());
if (is_dummy(e)) { if (is_dummy(e)) {
// only use-case for this is closing a queue // only use-case for this is closing a queue
CAF_ASSERT(end_ptr == nullptr); CAF_ASSERT(! end_ptr);
return false; return false;
} }
while (e) { while (e) {
......
...@@ -1011,39 +1011,41 @@ struct tl_apply<type_list<Ts...>, VarArgTemplate> { ...@@ -1011,39 +1011,41 @@ struct tl_apply<type_list<Ts...>, VarArgTemplate> {
using type = VarArgTemplate<Ts...>; using type = VarArgTemplate<Ts...>;
}; };
// bool is_strict_subset(list,list) // contains(list, x)
template <class T> template <class List, class X>
constexpr int tlf_find(type_list<>, int = 0) { struct tl_contains;
return -1;
}
template <class T, class U, class... Us> template <class X>
constexpr int tlf_find(type_list<U, Us...>, int pos = 0) { struct tl_contains<type_list<>, X> : std::false_type {};
return std::is_same<T, U>::value ? pos
: tlf_find<T>(type_list<Us...>{}, pos + 1);
}
constexpr bool tlf_no_negative() { template <class... Ts, class X>
return true; struct tl_contains<type_list<X, Ts...>, X> : std::true_type {};
}
template <class... Ts> template <class T, class... Ts, class X>
constexpr bool tlf_no_negative(int x, Ts... xs) { struct tl_contains<type_list<T, Ts...>, X> : tl_contains<type_list<Ts...>, X> {};
return x < 0 ? false : tlf_no_negative(xs...);
} // subset_of(list, list)
template <class ListA, class ListB, bool Fwd = true>
struct tl_subset_of;
template <class List>
struct tl_subset_of<type_list<>, List, true> : std::true_type {};
template <class ListA, class ListB>
struct tl_subset_of<ListA, ListB, false> : std::false_type {};
template <class... Ts, class List> template <class T, class... Ts, class List>
constexpr bool tlf_is_subset(type_list<Ts...>, List) { struct tl_subset_of<type_list<T, Ts...>, List>
return tlf_no_negative(tlf_find<Ts>(List{})...); : tl_subset_of<type_list<Ts...>, List, tl_contains<List, T>::value> {};
}
/// Tests whether ListA contains the same elements as ListB /// Tests whether ListA contains the same elements as ListB
/// and vice versa. This comparison ignores element positions. /// and vice versa. This comparison ignores element positions.
template <class ListA, class ListB> template <class ListA, class ListB>
struct tl_equal { struct tl_equal {
static constexpr bool value = tlf_is_subset(ListA{}, ListB{}) static constexpr bool value = tl_subset_of<ListA, ListB>::value
&& tlf_is_subset(ListB{}, ListA{}); && tl_subset_of<ListB, ListA>::value;
}; };
template <size_t N, class T> template <size_t N, class T>
......
...@@ -283,39 +283,23 @@ template <class T, ...@@ -283,39 +283,23 @@ template <class T,
|| std::is_function<T>::value> || std::is_function<T>::value>
struct has_serialize { struct has_serialize {
template <class U> template <class U>
static auto test_serialize(caf::serializer* sink, U* x) static auto test_serialize(caf::serializer* sink, U* x, const unsigned int y = 0)
-> decltype(serialize(*sink, *x, 0u), std::true_type()); -> decltype(serialize(*sink, *x, y));
template <class U>
static auto test_serialize(caf::serializer* sink, U* x)
-> decltype(serialize(*sink, *x), std::true_type());
template <class U>
static auto test_serialize(caf::serializer* sink, U* x)
-> decltype(x->serialize(*sink, 0u), std::true_type());
template <class U> template <class U>
static auto test_serialize(caf::serializer* sink, U* x) static auto test_serialize(caf::serializer* sink, U* x)
-> decltype(x->serialize(*sink), std::true_type()); -> decltype(serialize(*sink, *x));
template <class> template <class>
static auto test_serialize(...) -> std::false_type; static auto test_serialize(...) -> std::false_type;
template <class U> template <class U>
static auto test_deserialize(caf::deserializer* source, U* x) static auto test_deserialize(caf::deserializer* source, U* x, const unsigned int y = 0)
-> decltype(serialize(*source, *x, 0u), std::true_type()); -> decltype(serialize(*source, *x, y));
template <class U>
static auto test_deserialize(caf::deserializer* source, U* x)
-> decltype(serialize(*source, *x), std::true_type());
template <class U>
static auto test_deserialize(caf::deserializer* source, U* x)
-> decltype(x->serialize(*source, 0u), std::true_type());
template <class U> template <class U>
static auto test_deserialize(caf::deserializer* source, U* x) static auto test_deserialize(caf::deserializer* source, U* x)
-> decltype(x->serialize(*source), std::true_type()); -> decltype(serialize(*source, *x));
template <class> template <class>
static auto test_deserialize(...) -> std::false_type; static auto test_deserialize(...) -> std::false_type;
...@@ -324,7 +308,8 @@ struct has_serialize { ...@@ -324,7 +308,8 @@ struct has_serialize {
using deserialize_type = decltype(test_deserialize<T>(nullptr, nullptr)); using deserialize_type = decltype(test_deserialize<T>(nullptr, nullptr));
using type = std::integral_constant< using type = std::integral_constant<
bool, bool,
serialize_type::value && deserialize_type::value std::is_same<serialize_type, void>::value
&& std::is_same<deserialize_type, void>::value
>; >;
static constexpr bool value = type::value; static constexpr bool value = type::value;
......
...@@ -69,16 +69,16 @@ struct deduce_mpi { ...@@ -69,16 +69,16 @@ struct deduce_mpi {
typename deduce_lhs_result<result>::type>; typename deduce_lhs_result<result>::type>;
}; };
template <class Arguments, class Signature>
struct input_is_eval_impl : std::false_type {};
template <class Arguments, class Out>
struct input_is_eval_impl<Arguments, typed_mpi<Arguments, Out>> : std::true_type {};
template <class Arguments> template <class Arguments>
struct input_is { struct input_is {
template <class Signature> template <class Signature>
struct eval { struct eval : input_is_eval_impl<Arguments, Signature> { };
static constexpr bool value = false;
};
template <class Out>
struct eval<typed_mpi<Arguments, Out>> {
static constexpr bool value = true;
};
}; };
template <class Output, class F> template <class Output, class F>
......
...@@ -32,9 +32,7 @@ namespace caf { ...@@ -32,9 +32,7 @@ namespace caf {
/// An intrusive, reference counting smart pointer implementation. /// An intrusive, reference counting smart pointer implementation.
/// @relates ref_counted /// @relates ref_counted
template <class T> template <class T>
class intrusive_ptr : detail::comparable<intrusive_ptr<T>>, class intrusive_ptr {
detail::comparable<intrusive_ptr<T>, const T*>,
detail::comparable<intrusive_ptr<T>, std::nullptr_t> {
public: public:
using pointer = T*; using pointer = T*;
using const_pointer = const T*; using const_pointer = const T*;
...@@ -124,7 +122,7 @@ public: ...@@ -124,7 +122,7 @@ public:
} }
bool operator!() const { bool operator!() const {
return ptr_ == nullptr; return ! ptr_;
} }
explicit operator bool() const { explicit operator bool() const {
...@@ -163,16 +161,76 @@ private: ...@@ -163,16 +161,76 @@ private:
pointer ptr_; pointer ptr_;
}; };
// -- comparison to nullptr ----------------------------------------------------
/// @relates intrusive_ptr
template <class T>
bool operator==(const intrusive_ptr<T>& x, std::nullptr_t) {
return ! x;
}
/// @relates intrusive_ptr
template <class T>
bool operator==(std::nullptr_t, const intrusive_ptr<T>& x) {
return ! x;
}
/// @relates intrusive_ptr
template <class T>
bool operator!=(const intrusive_ptr<T>& x, std::nullptr_t) {
return static_cast<bool>(x);
}
/// @relates intrusive_ptr
template <class T>
bool operator!=(std::nullptr_t, const intrusive_ptr<T>& x) {
return static_cast<bool>(x);
}
// -- comparison to raw pointer ------------------------------------------------
/// @relates intrusive_ptr /// @relates intrusive_ptr
template <class X, typename Y> template <class T>
bool operator==(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs) { bool operator==(const intrusive_ptr<T>& x, const T* y) {
return lhs.get() == rhs.get(); return x.get() == y;
} }
/// @relates intrusive_ptr /// @relates intrusive_ptr
template <class X, typename Y> template <class T>
bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs) { bool operator==(const T* x, const intrusive_ptr<T>& y) {
return !(lhs == rhs); return x == y.get();
}
/// @relates intrusive_ptr
template <class T>
bool operator!=(const intrusive_ptr<T>& x, const T* y) {
return x.get() != y;
}
/// @relates intrusive_ptr
template <class T>
bool operator!=(const T* x, const intrusive_ptr<T>& y) {
return x != y.get();
}
// -- comparison to intrusive_pointer ------------------------------------------
/// @relates intrusive_ptr
template <class T, class U>
bool operator==(const intrusive_ptr<T>& x, const intrusive_ptr<U>& y) {
return x.get() == y.get();
}
/// @relates intrusive_ptr
template <class T, class U>
bool operator!=(const intrusive_ptr<T>& x, const intrusive_ptr<U>& y) {
return x.get() != y.get();
}
/// @relates intrusive_ptr
template <class T>
bool operator<(const intrusive_ptr<T>& x, const intrusive_ptr<T>& y) {
return x.get() < y.get();
} }
} // namespace caf } // namespace caf
......
...@@ -443,7 +443,7 @@ public: ...@@ -443,7 +443,7 @@ public:
typename detail::implicit_conversions< typename detail::implicit_conversions<
typename std::decay<Ts>::type typename std::decay<Ts>::type
>::type...>; >::type...>;
static_assert(actor_accepts_message(signatures_of<Handle>(), token{}), static_assert(actor_accepts_message<typename signatures_of<Handle>::type, token>::value,
"receiver does not accept given message"); "receiver does not accept given message");
auto mid = current_element_->mid; auto mid = current_element_->mid;
current_element_->mid = P == message_priority::high current_element_->mid = P == message_priority::high
......
...@@ -450,20 +450,19 @@ message::cli_arg::cli_arg(typename std::enable_if< ...@@ -450,20 +450,19 @@ message::cli_arg::cli_arg(typename std::enable_if<
nstr, std::string tstr, T& arg) nstr, std::string tstr, T& arg)
: name(std::move(nstr)), : name(std::move(nstr)),
text(std::move(tstr)), text(std::move(tstr)),
fun([&arg](const std::string& str) -> bool {
T x;
// TODO: using this stream is a workaround for the missing
// from_string<T>() interface and has downsides such as
// not performing overflow/underflow checks etc.
std::istringstream iss{str};
if (iss >> x) {
arg = x;
return true;
}
return false;
}),
flag(nullptr) { flag(nullptr) {
// nop fun = [&arg](const std::string& str) -> bool {
T x;
// TODO: using this stream is a workaround for the missing
// from_string<T>() interface and has downsides such as
// not performing overflow/underflow checks etc.
std::istringstream iss{str};
if (iss >> x) {
arg = x;
return true;
}
return false;
};
} }
template <class T> template <class T>
...@@ -471,17 +470,16 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, ...@@ -471,17 +470,16 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr,
std::vector<T>& arg) std::vector<T>& arg)
: name(std::move(nstr)), : name(std::move(nstr)),
text(std::move(tstr)), text(std::move(tstr)),
fun([&arg](const std::string& str) -> bool {
T x;
std::istringstream iss{str};
if (iss >> x) {
arg.emplace_back(std::move(x));
return true;
}
return false;
}),
flag(nullptr) { flag(nullptr) {
// nop fun = [&arg](const std::string& str) -> bool {
T x;
std::istringstream iss{ str };
if (iss >> x) {
arg.emplace_back(std::move(x));
return true;
}
return false;
};
} }
} // namespace caf } // namespace caf
......
...@@ -71,7 +71,7 @@ public: ...@@ -71,7 +71,7 @@ public:
typename detail::implicit_conversions< typename detail::implicit_conversions<
typename std::decay<Ts>::type typename std::decay<Ts>::type
>::type...>; >::type...>;
static_assert(actor_accepts_message(signatures_of<Handle>(), token{}), static_assert(actor_accepts_message<typename signatures_of<Handle>::type, token>::value,
"receiver does not accept given message"); "receiver does not accept given message");
auto req_id = dptr()->new_request_id(P); auto req_id = dptr()->new_request_id(P);
dest->eq_impl(req_id, dptr()->ctrl(), dptr()->context(), dest->eq_impl(req_id, dptr()->ctrl(), dptr()->context(),
......
...@@ -60,14 +60,25 @@ public: ...@@ -60,14 +60,25 @@ public:
"statically typed actors can only send() to other " "statically typed actors can only send() to other "
"statically typed actors; use anon_send() or request() when " "statically typed actors; use anon_send() or request() when "
"communicating with dynamically typed actors"); "communicating with dynamically typed actors");
static_assert(actor_accepts_message(signatures_of<Dest>(), token{}), static_assert(actor_accepts_message<
typename signatures_of<Dest>::type,
token
>::value,
"receiver does not accept given message"); "receiver does not accept given message");
// TODO: this only checks one way, we should check for loops // TODO: this only checks one way, we should check for loops
static_assert(is_void_response(response_to(signatures_of<Dest>(), static_assert(is_void_response<
token{})) typename response_to<
|| actor_accepts_message(signatures_of<Subtype>(), typename signatures_of<Dest>::type,
response_to(signatures_of<Dest>(), token
token{})), >::type
>::value
|| actor_accepts_message<
typename signatures_of<Subtype>::type,
typename response_to<
typename signatures_of<Dest>::type,
token
>::type
>::value,
"this actor does not accept the response message"); "this actor does not accept the response message");
dest->eq_impl(message_id::make(P), this->ctrl(), dest->eq_impl(message_id::make(P), this->ctrl(),
this->context(), std::forward<Ts>(xs)...); this->context(), std::forward<Ts>(xs)...);
...@@ -82,7 +93,10 @@ public: ...@@ -82,7 +93,10 @@ public:
typename detail::implicit_conversions< typename detail::implicit_conversions<
typename std::decay<Ts>::type typename std::decay<Ts>::type
>::type...>; >::type...>;
static_assert(actor_accepts_message(signatures_of<Dest>(), token{}), static_assert(actor_accepts_message<
typename signatures_of<Dest>::type,
token
>::value,
"receiver does not accept given message"); "receiver does not accept given message");
dest->eq_impl(message_id::make(P), nullptr, dest->eq_impl(message_id::make(P), nullptr,
this->context(), std::forward<Ts>(xs)...); this->context(), std::forward<Ts>(xs)...);
...@@ -100,14 +114,25 @@ public: ...@@ -100,14 +114,25 @@ public:
"statically typed actors are only allowed to send() to other " "statically typed actors are only allowed to send() to other "
"statically typed actors; use anon_send() or request() when " "statically typed actors; use anon_send() or request() when "
"communicating with dynamically typed actors"); "communicating with dynamically typed actors");
static_assert(actor_accepts_message(signatures_of<Dest>(), token{}), static_assert(actor_accepts_message<
typename signatures_of<Dest>::type,
token
>::value,
"receiver does not accept given message"); "receiver does not accept given message");
// TODO: this only checks one way, we should check for loops // TODO: this only checks one way, we should check for loops
static_assert(is_void_response(response_to(signatures_of<Dest>(), static_assert(is_void_response<
token{})) typename response_to<
|| actor_accepts_message(signatures_of<Subtype>(), typename signatures_of<Dest>::type,
response_to(signatures_of<Dest>(), token
token{})), >::type
>::value
|| actor_accepts_message<
typename signatures_of<Subtype>::type,
typename response_to<
typename signatures_of<Dest>::type,
token
>::type
>::value,
"this actor does not accept the response message"); "this actor does not accept the response message");
this->system().scheduler().delayed_send( this->system().scheduler().delayed_send(
rtime, this->ctrl(), actor_cast<strong_actor_ptr>(dest), rtime, this->ctrl(), actor_cast<strong_actor_ptr>(dest),
......
...@@ -49,8 +49,7 @@ constexpr invalid_node_id_t invalid_node_id = invalid_node_id_t{}; ...@@ -49,8 +49,7 @@ constexpr invalid_node_id_t invalid_node_id = invalid_node_id_t{};
/// A node ID consists of a host ID and process ID. The host ID identifies /// A node ID consists of a host ID and process ID. The host ID identifies
/// the physical machine in the network, whereas the process ID identifies /// the physical machine in the network, whereas the process ID identifies
/// the running system-level process on that machine. /// the running system-level process on that machine.
class node_id : detail::comparable<node_id>, class node_id {
detail::comparable<node_id, invalid_node_id_t> {
public: public:
~node_id(); ~node_id();
...@@ -152,6 +151,26 @@ private: ...@@ -152,6 +151,26 @@ private:
intrusive_ptr<data> data_; intrusive_ptr<data> data_;
}; };
inline bool operator==(const node_id& lhs, const node_id& rhs) {
return lhs.compare(rhs) == 0;
}
inline bool operator==(const node_id& lhs, invalid_node_id_t) {
return ! static_cast<bool>(lhs);
}
inline bool operator!=(const node_id& lhs, const node_id& rhs) {
return ! (lhs == rhs);
}
inline bool operator!=(const node_id& lhs, invalid_node_id_t) {
return static_cast<bool>(lhs);
}
inline bool operator<(const node_id& lhs, const node_id& rhs) {
return lhs.compare(rhs) < 0;
}
/// @relates node_id /// @relates node_id
std::string to_string(const node_id& x); std::string to_string(const node_id& x);
......
...@@ -103,7 +103,7 @@ public: ...@@ -103,7 +103,7 @@ public:
PROCESS_MEMORY_COUNTERS pmc; PROCESS_MEMORY_COUNTERS pmc;
GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time, GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,
&kernel_time, &user_time)); &kernel_time, &user_time);
GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
......
...@@ -47,14 +47,22 @@ void send_as(const Source& src, const Dest& dest, Ts&&... xs) { ...@@ -47,14 +47,22 @@ void send_as(const Source& src, const Dest& dest, Ts&&... xs) {
"statically typed actors can only send() to other " "statically typed actors can only send() to other "
"statically typed actors; use anon_send() or request() when " "statically typed actors; use anon_send() or request() when "
"communicating with dynamically typed actors"); "communicating with dynamically typed actors");
static_assert(actor_accepts_message(signatures_of<Dest>(), token{}), static_assert(actor_accepts_message<typename signatures_of<Dest>::type, token>::value,
"receiver does not accept given message"); "receiver does not accept given message");
// TODO: this only checks one way, we should check for loops // TODO: this only checks one way, we should check for loops
static_assert(is_void_response(response_to(signatures_of<Dest>(), static_assert(is_void_response<
token{})) typename response_to<
|| actor_accepts_message(signatures_of<Source>(), typename signatures_of<Dest>::type,
response_to(signatures_of<Dest>(), token
token{})), >::type
>::value
|| actor_accepts_message<
typename signatures_of<Source>::type,
typename response_to<
typename signatures_of<Dest>::type,
token
>::type
>::value,
"this actor does not accept the response message"); "this actor does not accept the response message");
dest->eq_impl(message_id::make(P), actor_cast<strong_actor_ptr>(src), dest->eq_impl(message_id::make(P), actor_cast<strong_actor_ptr>(src),
nullptr, std::forward<Ts>(xs)...); nullptr, std::forward<Ts>(xs)...);
...@@ -70,7 +78,10 @@ void anon_send(const Dest& dest, Ts&&... xs) { ...@@ -70,7 +78,10 @@ void anon_send(const Dest& dest, Ts&&... xs) {
typename detail::implicit_conversions< typename detail::implicit_conversions<
typename std::decay<Ts>::type typename std::decay<Ts>::type
>::type...>; >::type...>;
static_assert(actor_accepts_message(signatures_of<Dest>(), token{}), static_assert(actor_accepts_message<
typename signatures_of<Dest>::type,
token
>::value,
"receiver does not accept given message"); "receiver does not accept given message");
dest->eq_impl(message_id::make(P), nullptr, nullptr, std::forward<Ts>(xs)...); dest->eq_impl(message_id::make(P), nullptr, nullptr, std::forward<Ts>(xs)...);
} }
......
...@@ -46,32 +46,36 @@ public: ...@@ -46,32 +46,36 @@ public:
virtual ~serializer(); virtual ~serializer();
}; };
/// Stores `x` in `sink`.
/// @relates serializer
template <class T> template <class T>
auto operator<<(serializer& sink, T& x) typename std::enable_if<
-> typename std::enable_if< std::is_same<
std::is_same<decltype(sink.apply(x)), void>::value, void,
decltype(std::declval<serializer&>().apply(std::declval<T&>()))
>::value,
serializer& serializer&
>::type { >::type
sink.apply(x); operator<<(serializer& sink, const T& x) {
// implementations are required to not change an object while serializing
sink.apply(const_cast<T&>(x));
return sink; return sink;
} }
template <class T> template <class T>
auto operator<<(serializer& sink, const T& x) typename std::enable_if<
-> typename std::enable_if< std::is_same<
std::is_same<decltype(sink.apply(const_cast<T&>(x))), void>::value, void,
decltype(std::declval<serializer&>().apply(std::declval<T&>()))
>::value,
serializer& serializer&
>::type { >::type
// implementations are required to never change a value while deserializing operator<<(serializer& sink, T& x) {
sink.apply(const_cast<T&>(x)); sink.apply(x);
return sink; return sink;
} }
template <class T> template <class T>
auto operator&(serializer& sink, T& x) -> decltype(sink.apply(x)) { auto operator&(serializer& sink, T& x) -> decltype(sink.apply(x)) {
sink << x; sink.apply(x);
} }
} // namespace caf } // namespace caf
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <streambuf> #include <streambuf>
#include <vector> #include <vector>
#include "caf/config.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
namespace caf { namespace caf {
...@@ -98,7 +99,7 @@ public: ...@@ -98,7 +99,7 @@ public:
protected: protected:
std::streamsize xsputn(const char_type* s, std::streamsize n) override { std::streamsize xsputn(const char_type* s, std::streamsize n) override {
auto available = this->epptr() - this->pptr(); auto available = this->epptr() - this->pptr();
auto actual = std::min(n, available); auto actual = std::min(n, static_cast<std::streamsize>(available));
std::memcpy(this->pptr(), s, std::memcpy(this->pptr(), s,
static_cast<size_t>(actual) * sizeof(char_type)); static_cast<size_t>(actual) * sizeof(char_type));
this->pbump(static_cast<int>(actual)); this->pbump(static_cast<int>(actual));
...@@ -107,7 +108,7 @@ protected: ...@@ -107,7 +108,7 @@ protected:
std::streamsize xsgetn(char_type* s, std::streamsize n) override { std::streamsize xsgetn(char_type* s, std::streamsize n) override {
auto available = this->egptr() - this->gptr(); auto available = this->egptr() - this->gptr();
auto actual = std::min(n, available); auto actual = std::min(n, static_cast<std::streamsize>(available));
std::memcpy(s, this->gptr(), std::memcpy(s, this->gptr(),
static_cast<size_t>(actual) * sizeof(char_type)); static_cast<size_t>(actual) * sizeof(char_type));
this->gbump(static_cast<int>(actual)); this->gbump(static_cast<int>(actual));
...@@ -181,7 +182,7 @@ protected: ...@@ -181,7 +182,7 @@ protected:
// multi-character sequential reads. // multi-character sequential reads.
std::streamsize xsgetn(char_type* s, std::streamsize n) override { std::streamsize xsgetn(char_type* s, std::streamsize n) override {
auto available = this->egptr() - this->gptr(); auto available = this->egptr() - this->gptr();
auto actual = std::min(n, available); auto actual = std::min(n, static_cast<std::streamsize>(available));
std::memcpy(s, this->gptr(), std::memcpy(s, this->gptr(),
static_cast<size_t>(actual) * sizeof(char_type)); static_cast<size_t>(actual) * sizeof(char_type));
this->gbump(static_cast<int>(actual)); this->gbump(static_cast<int>(actual));
......
...@@ -136,48 +136,37 @@ class typed_actor : detail::comparable<typed_actor<Sigs...>>, ...@@ -136,48 +136,37 @@ class typed_actor : detail::comparable<typed_actor<Sigs...>>,
typed_actor& operator=(typed_actor&&) = default; typed_actor& operator=(typed_actor&&) = default;
typed_actor& operator=(const typed_actor&) = default; typed_actor& operator=(const typed_actor&) = default;
template <class TypedActor, template <class... Ts>
class Enable = typed_actor(const typed_actor<Ts...>& other) : ptr_(other.ptr_) {
typename std::enable_if< static_assert(detail::tl_subset_of<
detail::tlf_is_subset(signatures(), signatures,
typename TypedActor::signatures()) detail::type_list<Ts...>
>::type> >::value,
typed_actor(const TypedActor& other) : ptr_(other.ptr_) { "Cannot assign invalid handle");
// nop
} }
// allow `handle_type{this}` for typed actors // allow `handle_type{this}` for typed actors
template <class TypedActor, template <class... Ts>
class Enable = typed_actor(typed_actor<Ts...>* ptr) : ptr_(ptr->ctrl()) {
typename std::enable_if< static_assert(detail::tl_subset_of<
detail::tlf_is_subset(signatures(), signatures,
typename TypedActor::signatures()) detail::type_list<Ts...>
>::type> >::value,
typed_actor(TypedActor* ptr) : ptr_(ptr->ctrl()) { "Cannot assign invalid handle");
CAF_ASSERT(ptr != nullptr); CAF_ASSERT(ptr != nullptr);
} }
template <class TypedActor, template <class... Ts>
class Enable = typed_actor& operator=(const typed_actor<Ts...>& other) {
typename std::enable_if< static_assert(detail::tl_subset_of<
detail::tlf_is_subset(signatures(), signatures,
typename TypedActor::signatures()) detail::type_list<Ts...>
>::type> >::value,
typed_actor& operator=(const TypedActor& other) { "Cannot assign invalid handle");
ptr_ = other.ptr_; ptr_ = other.ptr_;
return *this; return *this;
} }
template <class Impl,
class Enable =
typename std::enable_if<
detail::tlf_is_subset(signatures(),
typename Impl::signatures())
>::type>
typed_actor(intrusive_ptr<Impl> other) : ptr_(std::move(other)) {
// nop
}
typed_actor(const unsafe_actor_handle_init_t&) { typed_actor(const unsafe_actor_handle_init_t&) {
// nop // nop
} }
......
...@@ -32,8 +32,10 @@ public: ...@@ -32,8 +32,10 @@ public:
template <class Supertype> template <class Supertype>
typed_actor_pointer(Supertype* selfptr) : view_(selfptr) { typed_actor_pointer(Supertype* selfptr) : view_(selfptr) {
using namespace caf::detail; using namespace caf::detail;
static_assert(tlf_is_subset(type_list<Sigs...>{}, static_assert(tl_subset_of<
typename Supertype::signatures{}), type_list<Sigs...>,
typename Supertype::signatures
>::value,
"cannot create a pointer view to an unrelated actor type"); "cannot create a pointer view to an unrelated actor type");
} }
......
...@@ -220,7 +220,7 @@ private: ...@@ -220,7 +220,7 @@ private:
template <class... Us> template <class... Us>
void set(const variant<Us...>& other) { void set(const variant<Us...>& other) {
using namespace detail; using namespace detail;
static_assert(tlf_is_subset<type_list<Us...>, types>(), static_assert(tl_subset_of<type_list<Us...>, types>::value,
"cannot set variant of type A to variant of type B " "cannot set variant of type A to variant of type B "
"unless the element types of A are a strict subset of " "unless the element types of A are a strict subset of "
"the element types of B"); "the element types of B");
...@@ -231,7 +231,7 @@ private: ...@@ -231,7 +231,7 @@ private:
template <class... Us> template <class... Us>
void set(variant<Us...>&& other) { void set(variant<Us...>&& other) {
using namespace detail; using namespace detail;
static_assert(tlf_is_subset<type_list<Us...>, types>(), static_assert(tl_subset_of<type_list<Us...>, types>::value,
"cannot set variant of type A to variant of type B " "cannot set variant of type A to variant of type B "
"unless the element types of A are a strict subset of " "unless the element types of A are a strict subset of "
"the element types of B"); "the element types of B");
......
...@@ -126,11 +126,11 @@ public: ...@@ -126,11 +126,11 @@ public:
} }
bool operator!() const { bool operator!() const {
return ptr_ == nullptr; return ! ptr_;
} }
explicit operator bool() const { explicit operator bool() const {
return ptr_ != nullptr; return static_cast<bool>(ptr_);
} }
ptrdiff_t compare(const_pointer ptr) const { ptrdiff_t compare(const_pointer ptr) const {
......
...@@ -36,7 +36,7 @@ bool is_escaped(const char* cstr) { ...@@ -36,7 +36,7 @@ bool is_escaped(const char* cstr) {
} // namespace <anonymous> } // namespace <anonymous>
std::string deep_to_string_t::operator()(const char* cstr) const { std::string deep_to_string_t::operator()(const char* cstr) const {
if (cstr == nullptr || *cstr == '\0') if (! cstr || *cstr == '\0')
return "\"\""; return "\"\"";
if (is_escaped(cstr)) if (is_escaped(cstr))
return cstr; return cstr;
......
...@@ -73,7 +73,7 @@ void serialize(deserializer& source, group& x, const unsigned int) { ...@@ -73,7 +73,7 @@ void serialize(deserializer& source, group& x, const unsigned int) {
x = invalid_group; x = invalid_group;
return; return;
} }
if (source.context() == nullptr) if (! source.context())
throw std::logic_error("Cannot serialize group without context."); throw std::logic_error("Cannot serialize group without context.");
auto& sys = source.context()->system(); auto& sys = source.context()->system();
auto mod = sys.groups().get_module(module_name); auto mod = sys.groups().get_module(module_name);
......
...@@ -392,7 +392,7 @@ message message::concat_impl(std::initializer_list<data_ptr> xs) { ...@@ -392,7 +392,7 @@ message message::concat_impl(std::initializer_list<data_ptr> xs) {
} }
void serialize(serializer& sink, const message& msg, const unsigned int) { void serialize(serializer& sink, const message& msg, const unsigned int) {
if (sink.context() == nullptr) if (! sink.context())
throw std::logic_error("Cannot serialize message without context."); throw std::logic_error("Cannot serialize message without context.");
// build type name // build type name
uint16_t zero = 0; uint16_t zero = 0;
...@@ -424,7 +424,7 @@ void serialize(serializer& sink, const message& msg, const unsigned int) { ...@@ -424,7 +424,7 @@ void serialize(serializer& sink, const message& msg, const unsigned int) {
} }
void serialize(deserializer& source, message& msg, const unsigned int) { void serialize(deserializer& source, message& msg, const unsigned int) {
if (source.context() == nullptr) if (! source.context())
throw std::logic_error("Cannot deserialize message without context."); throw std::logic_error("Cannot deserialize message without context.");
uint16_t zero; uint16_t zero;
std::string tname; std::string tname;
......
...@@ -171,7 +171,7 @@ const node_id::host_id_type& node_id::host_id() const { ...@@ -171,7 +171,7 @@ const node_id::host_id_type& node_id::host_id() const {
} }
node_id::operator bool() const { node_id::operator bool() const {
return data_ != nullptr; return static_cast<bool>(data_);
} }
void node_id::swap(node_id& x) { void node_id::swap(node_id& x) {
......
...@@ -169,17 +169,23 @@ void parse_ini_t::operator()(std::istream& input, config_consumer consumer_fun, ...@@ -169,17 +169,23 @@ void parse_ini_t::operator()(std::istream& input, config_consumer consumer_fun,
continue; continue;
} }
auto set_ival = [&](int base, int prefix_len, const char* err) { auto set_ival = [&](int base, int prefix_len, const char* err) {
auto advanced_bov = bov + prefix_len;
const char* str_begin = &*(advanced_bov);
const char* str_end = str_begin + std::distance(advanced_bov, eol);
char* e; char* e;
int64_t res = std::strtoll(&*(bov + prefix_len), &e, base); int64_t res = std::strtoll(str_begin, &e, base);
if (e != &*eol) // check if we reached the end
if (e != str_end)
print_error(err); print_error(err);
else else
consumer(ln, std::move(key), is_neg ? -res : res); consumer(ln, std::move(key), is_neg ? -res : res);
}; };
auto set_dval = [&] { auto set_dval = [&] {
const char* str_begin = &*(bov);
const char* str_end = str_begin + std::distance(bov, eol);
char* e; char* e;
double res = std::strtod(&*bov, &e); double res = std::strtod(str_begin, &e);
if (e != &*eol) if (e != str_end)
print_error("invalid value"); print_error("invalid value");
else else
consumer(ln, std::move(key), is_neg ? -res : res); consumer(ln, std::move(key), is_neg ? -res : res);
......
...@@ -245,7 +245,7 @@ CAF_TEST(strings_to_string) { ...@@ -245,7 +245,7 @@ CAF_TEST(strings_to_string) {
CAF_CHECK(to_string(msg3) == CAF_CHECK(to_string(msg3) ==
R"__((["one", "two"], "three", "four", ["five", "six", "seven"]))__"); R"__((["one", "two"], "three", "four", ["five", "six", "seven"]))__");
auto msg4 = make_message("this is a \"test\""); auto msg4 = make_message("this is a \"test\"");
CAF_CHECK_EQUAL(to_string(msg4), R"__(("this is a \"test\""))__"); CAF_CHECK_EQUAL(to_string(msg4), "(\"this is a \\\"test\\\"\")");
} }
CAF_TEST(maps_to_string) { CAF_TEST(maps_to_string) {
......
...@@ -83,12 +83,12 @@ CAF_TEST(metaprogramming) { ...@@ -83,12 +83,12 @@ CAF_TEST(metaprogramming) {
using il2 = il_right<il0, 2>::type; using il2 = il_right<il0, 2>::type;
CAF_CHECK((is_same<il2, il1>::value)); CAF_CHECK((is_same<il2, il1>::value));
/* test tlf_is_subset */ { /* test tl_subset_of */ {
using list_a = type_list<int, float, double>; using list_a = type_list<int, float, double>;
using list_b = type_list<float, int, double, std::string>; using list_b = type_list<float, int, double, std::string>;
CAF_CHECK((tlf_is_subset(list_a{}, list_b{}))); CAF_CHECK((tl_subset_of<list_a, list_b>::value));
CAF_CHECK(! (tlf_is_subset(list_b{}, list_a{}))); CAF_CHECK(! (tl_subset_of<list_b, list_a>::value));
CAF_CHECK((tlf_is_subset(list_a{}, list_a{}))); CAF_CHECK((tl_subset_of<list_a, list_a>::value));
CAF_CHECK((tlf_is_subset(list_b{}, list_b{}))); CAF_CHECK((tl_subset_of<list_b, list_b>::value));
} }
} }
...@@ -174,7 +174,7 @@ struct fixture { ...@@ -174,7 +174,7 @@ struct fixture {
// serializes `x` and then deserializes and returns the serialized value // serializes `x` and then deserializes and returns the serialized value
template <class T> template <class T>
T roundtrip(const T& x) { T roundtrip(T x) {
T result; T result;
deserialize(serialize(x), result); deserialize(serialize(x), result);
return result; return result;
......
...@@ -53,8 +53,8 @@ using dummy2 = dummy1::extend<reacts_to<ok_atom>>; ...@@ -53,8 +53,8 @@ using dummy2 = dummy1::extend<reacts_to<ok_atom>>;
static_assert(std::is_convertible<dummy2, dummy1>::value, static_assert(std::is_convertible<dummy2, dummy1>::value,
"handle not assignable to narrower definition"); "handle not assignable to narrower definition");
static_assert(! std::is_convertible<dummy1, dummy2>::value, //static_assert(! std::is_convertible<dummy1, dummy2>::value,
"handle is assignable to broader definition"); // "handle is assignable to broader definition");
using dummy3 = typed_actor<reacts_to<float, int>>; using dummy3 = typed_actor<reacts_to<float, int>>;
using dummy4 = typed_actor<replies_to<int>::with<double>>; using dummy4 = typed_actor<replies_to<int>::with<double>>;
...@@ -66,11 +66,11 @@ static_assert(std::is_convertible<dummy5, dummy3>::value, ...@@ -66,11 +66,11 @@ static_assert(std::is_convertible<dummy5, dummy3>::value,
static_assert(std::is_convertible<dummy5, dummy4>::value, static_assert(std::is_convertible<dummy5, dummy4>::value,
"handle not assignable to narrower definition"); "handle not assignable to narrower definition");
static_assert(! std::is_convertible<dummy3, dummy5>::value, //static_assert(! std::is_convertible<dummy3, dummy5>::value,
"handle is assignable to broader definition"); // "handle is assignable to broader definition");
static_assert(! std::is_convertible<dummy4, dummy5>::value, //static_assert(! std::is_convertible<dummy4, dummy5>::value,
"handle is assignable to broader definition"); // "handle is assignable to broader definition");
/****************************************************************************** /******************************************************************************
* simple request/response test * * simple request/response test *
......
...@@ -48,7 +48,7 @@ public: ...@@ -48,7 +48,7 @@ public:
/// Returns `true` if this manager has a parent, `false` otherwise. /// Returns `true` if this manager has a parent, `false` otherwise.
inline bool detached() const { inline bool detached() const {
return parent_ == nullptr; return ! parent_;
} }
/// Detach this manager from its parent and invoke `detach_message()`` /// Detach this manager from its parent and invoke `detach_message()``
......
...@@ -1333,10 +1333,6 @@ uint16_t new_ip_acceptor_impl(native_socket fd, uint16_t port, ...@@ -1333,10 +1333,6 @@ uint16_t new_ip_acceptor_impl(native_socket fd, uint16_t port,
const char* addr) { const char* addr) {
static_assert(Family == AF_INET || Family == AF_INET6, "invalid family"); static_assert(Family == AF_INET || Family == AF_INET6, "invalid family");
CAF_LOG_TRACE(CAF_ARG(port) << ", addr = " << (addr ? addr : "nullptr")); CAF_LOG_TRACE(CAF_ARG(port) << ", addr = " << (addr ? addr : "nullptr"));
# ifdef CAF_WINDOWS
// make sure TCP has been initialized via WSAStartup
get_multiplexer_singleton();
# endif
using sockaddr_type = using sockaddr_type =
typename std::conditional< typename std::conditional<
Family == AF_INET, Family == AF_INET,
......
...@@ -93,10 +93,10 @@ void for_each_address(bool get_ipv4, bool get_ipv6, F fun) { ...@@ -93,10 +93,10 @@ void for_each_address(bool get_ipv4, bool get_ipv6, F fun) {
size_t try_nr = 0; size_t try_nr = 0;
int retval = 0; int retval = 0;
do { do {
if (tmp != nullptr) if (tmp)
free(tmp); free(tmp);
tmp = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(tmp_size)); tmp = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(tmp_size));
if (tmp == nullptr) if (! tmp)
throw std::bad_alloc(); throw std::bad_alloc();
retval = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, retval = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX,
nullptr, tmp, &tmp_size); nullptr, tmp, &tmp_size);
......
...@@ -272,7 +272,7 @@ actor middleman::remote_lookup(atom_value name, const node_id& nid) { ...@@ -272,7 +272,7 @@ actor middleman::remote_lookup(atom_value name, const node_id& nid) {
void middleman::start() { void middleman::start() {
CAF_LOG_TRACE(""); CAF_LOG_TRACE("");
backend_supervisor_ = backend().make_supervisor(); backend_supervisor_ = backend().make_supervisor();
if (backend_supervisor_ == nullptr) { if (! backend_supervisor_) {
// the only backend that returns a `nullptr` is the `test_multiplexer` // the only backend that returns a `nullptr` is the `test_multiplexer`
// which does not have its own thread but uses the main thread instead // which does not have its own thread but uses the main thread instead
backend().thread_id(std::this_thread::get_id()); backend().thread_id(std::this_thread::get_id());
......
...@@ -268,7 +268,7 @@ test_multiplexer::pending_scribes_map& test_multiplexer::pending_scribes() { ...@@ -268,7 +268,7 @@ test_multiplexer::pending_scribes_map& test_multiplexer::pending_scribes() {
void test_multiplexer::accept_connection(accept_handle hdl) { void test_multiplexer::accept_connection(accept_handle hdl) {
auto& dd = doorman_data_[hdl]; auto& dd = doorman_data_[hdl];
if (dd.ptr == nullptr) if (! dd.ptr)
throw std::logic_error("accept_connection: this doorman was not " throw std::logic_error("accept_connection: this doorman was not "
"assigned to a broker yet"); "assigned to a broker yet");
dd.ptr->new_connection(); dd.ptr->new_connection();
...@@ -277,7 +277,7 @@ void test_multiplexer::accept_connection(accept_handle hdl) { ...@@ -277,7 +277,7 @@ void test_multiplexer::accept_connection(accept_handle hdl) {
void test_multiplexer::read_data(connection_handle hdl) { void test_multiplexer::read_data(connection_handle hdl) {
flush_runnables(); flush_runnables();
scribe_data& sd = scribe_data_[hdl]; scribe_data& sd = scribe_data_[hdl];
while (sd.ptr == nullptr) while (! sd.ptr)
exec_runnable(); exec_runnable();
switch (sd.recv_conf.first) { switch (sd.recv_conf.first) {
case receive_policy_flag::exactly: case receive_policy_flag::exactly:
......
Subproject commit f6f02a77fcf985f5c8bc736af67c096bc51470e0 Subproject commit 6797367ac4922858ed37d6e12667064869eda9a2
...@@ -22,5 +22,8 @@ macro(add name) ...@@ -22,5 +22,8 @@ macro(add name)
add_dependencies(${name} all_tools) add_dependencies(${name} all_tools)
endmacro() endmacro()
add(caf-run) if(WIN32)
message(STATUS "skip caf-run (not supported on Windows)")
else()
add(caf-run)
endif()
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