Commit 5e7b99b9 authored by Dominik Charousset's avatar Dominik Charousset

Make use of noexcept, relates #253

parent 3d3abfa9
This document specifies how to contribute code to this repository.
This document specifies how to contribute code to CAF.
Git Workflow
============
CAF's git workflow encompasses the following key aspects. (For general git
Our git workflow encompasses the following key aspects. (For general git
style guidelines, see <https://github.com/agis-/git-style-guide>.)
- The `master` branch always reflects a *production-ready* state, i.e.,
......@@ -87,7 +87,7 @@ public:
// suppress redundant @return if you start the brief description with "Returns"
/// Returns the name of this instance.
inline const std::string& name() const {
inline const std::string& name() const noexcept {
return name_;
}
......@@ -100,10 +100,10 @@ public:
void print_name() const;
/// Does something (maybe).
void do_something();
void do_something() noexcept;
/// Does something else.
void do_something_else();
/// Does something else but is guaranteed to never throw.
void do_something_else() noexcept;
private:
std::string name_;
......@@ -156,7 +156,7 @@ void my_class::do_something() {
}
}
void my_class::do_something_else() {
void my_class::do_something_else() noexcept {
switch (default_name[0]) {
case 'a':
// handle a
......@@ -273,6 +273,9 @@ General
- Protect single-argument constructors with `explicit` to avoid implicit conversions.
- Use noexcept whenever it makes sense, in particular for move construction and assignment,
as long as it does not limit future design space.
Naming
------
......
......@@ -58,13 +58,13 @@ public:
// -- overridden observers of type_erased_tuple ------------------------------
size_t size() const override;
size_t size() const noexcept override;
uint32_t type_token() const override;
uint32_t type_token() const noexcept override;
rtti_pair type(size_t pos) const override;
rtti_pair type(size_t pos) const noexcept override;
const void* get(size_t pos) const override;
const void* get(size_t pos) const noexcept override;
std::string stringify(size_t pos) const override;
......
......@@ -62,13 +62,13 @@ public:
// -- overridden observers of type_erased_tuple ------------------------------
size_t size() const override;
size_t size() const noexcept override;
uint32_t type_token() const override;
uint32_t type_token() const noexcept override;
rtti_pair type(size_t pos) const override;
rtti_pair type(size_t pos) const noexcept override;
const void* get(size_t pos) const override;
const void* get(size_t pos) const noexcept override;
std::string stringify(size_t pos) const override;
......
......@@ -57,13 +57,13 @@ public:
// -- overridden observers of type_erased_tuple ------------------------------
size_t size() const override;
size_t size() const noexcept override;
uint32_t type_token() const override;
uint32_t type_token() const noexcept override;
rtti_pair type(size_t pos) const override;
rtti_pair type(size_t pos) const noexcept override;
const void* get(size_t pos) const override;
const void* get(size_t pos) const noexcept override;
std::string stringify(size_t pos) const override;
......
......@@ -58,13 +58,13 @@ public:
// -- overridden observers of type_erased_tuple ------------------------------
size_t size() const override;
size_t size() const noexcept override;
uint32_t type_token() const override;
uint32_t type_token() const noexcept override;
rtti_pair type(size_t pos) const override;
rtti_pair type(size_t pos) const noexcept override;
const void* get(size_t pos) const override;
const void* get(size_t pos) const noexcept override;
std::string stringify(size_t pos) const override;
......
......@@ -38,84 +38,95 @@ namespace detail {
class message_data : public ref_counted, public type_erased_tuple {
public:
// -- nested types -----------------------------------------------------------
class cow_ptr;
// -- constructors, destructors, and assignment operators --------------------
message_data() = default;
message_data(const message_data&) = default;
~message_data();
bool shared() const override;
// -- pure virtual observers -------------------------------------------------
// nested types
virtual cow_ptr copy() const = 0;
class cow_ptr {
public:
cow_ptr() = default;
cow_ptr(cow_ptr&&) = default;
cow_ptr(const cow_ptr&) = default;
cow_ptr& operator=(cow_ptr&&) = default;
cow_ptr& operator=(const cow_ptr&) = default;
// -- observers --------------------------------------------------------------
template <class T>
cow_ptr(intrusive_ptr<T> p) : ptr_(std::move(p)) {
// nop
}
using type_erased_tuple::copy;
inline cow_ptr(message_data* ptr, bool add_ref) : ptr_(ptr, add_ref) {
// nop
}
bool shared() const noexcept override;
};
// modifiers
class message_data::cow_ptr {
public:
// -- constructors, destructors, and assignment operators ------------------
inline void swap(cow_ptr& other) {
ptr_.swap(other.ptr_);
}
cow_ptr() noexcept = default;
cow_ptr(cow_ptr&&) noexcept = default;
cow_ptr(const cow_ptr&) noexcept = default;
cow_ptr& operator=(cow_ptr&&) noexcept = default;
cow_ptr& operator=(const cow_ptr&) noexcept = default;
inline void reset(message_data* p = nullptr, bool add_ref = true) {
ptr_.reset(p, add_ref);
}
template <class T>
cow_ptr(intrusive_ptr<T> p) noexcept : ptr_(std::move(p)) {
// nop
}
inline message_data* release() {
return ptr_.detach();
}
inline cow_ptr(message_data* ptr, bool add_ref) noexcept
: ptr_(ptr, add_ref) {
// nop
}
inline void unshare() {
static_cast<void>(get_unshared());
}
// -- modifiers ------------------------------------------------------------
inline message_data* operator->() {
return get_unshared();
}
inline void swap(cow_ptr& other) noexcept {
ptr_.swap(other.ptr_);
}
inline message_data& operator*() {
return *get_unshared();
}
inline void reset(message_data* p = nullptr, bool add_ref = true) noexcept {
ptr_.reset(p, add_ref);
}
// observers
inline message_data* release() noexcept {
return ptr_.detach();
}
inline const message_data* operator->() const {
return ptr_.get();
}
inline void unshare() {
static_cast<void>(get_unshared());
}
inline const message_data& operator*() const {
return *ptr_.get();
}
inline message_data* operator->() {
return get_unshared();
}
inline explicit operator bool() const {
return static_cast<bool>(ptr_);
}
inline message_data& operator*() {
return *get_unshared();
}
inline message_data* get() const {
return ptr_.get();
}
// -- observers ------------------------------------------------------------
private:
message_data* get_unshared();
intrusive_ptr<message_data> ptr_;
};
inline const message_data* operator->() const noexcept {
return ptr_.get();
}
using type_erased_tuple::copy;
inline const message_data& operator*() const noexcept {
return *ptr_.get();
}
virtual cow_ptr copy() const = 0;
inline explicit operator bool() const noexcept {
return static_cast<bool>(ptr_);
}
inline message_data* get() const noexcept {
return ptr_.get();
}
private:
message_data* get_unshared();
intrusive_ptr<message_data> ptr_;
};
} // namespace detail
......
......@@ -157,7 +157,7 @@ public:
return data_;
}
size_t size() const override {
size_t size() const noexcept override {
return sizeof...(Ts);
}
......@@ -165,7 +165,7 @@ public:
return message_data::cow_ptr(new tuple_vals(*this), false);
}
const void* get(size_t pos) const override {
const void* get(size_t pos) const noexcept override {
CAF_ASSERT(pos < size());
return tup_ptr_access<0, sizeof...(Ts)>::get(pos, data_);
}
......@@ -187,11 +187,11 @@ public:
return tup_ptr_access<0, sizeof...(Ts)>::serialize(pos, data_, source);
}
uint32_t type_token() const override {
uint32_t type_token() const noexcept override {
return make_type_token<Ts...>();
}
rtti_pair type(size_t pos) const override {
rtti_pair type(size_t pos) const noexcept override {
return types_[pos];
}
......
......@@ -62,12 +62,14 @@ namespace caf {
/// rendering error messages via `actor_system::render(const error&)`.
class error : detail::comparable<error> {
public:
error();
error(error&&) = default;
error(const error&) = default;
error& operator=(error&&) = default;
error& operator=(const error&) = default;
error(uint8_t code, atom_value category, message context = message{});
error() noexcept;
error(error&&) noexcept = default;
error(const error&) noexcept = default;
error& operator=(error&&) noexcept = default;
error& operator=(const error&) noexcept = default;
error(uint8_t code, atom_value category) noexcept;
error(uint8_t code, atom_value category, message msg) noexcept;
template <class E,
class = typename std::enable_if<
......@@ -81,16 +83,24 @@ public:
}
/// Returns the category-specific error code, whereas `0` means "no error".
uint8_t code() const;
inline uint8_t code() const noexcept {
return code_;
}
/// Returns the category of this error.
atom_value category() const;
inline atom_value category() const noexcept {
return category_;
}
/// Returns optional context information to this error.
message& context();
inline message& context() noexcept {
return context_;
}
/// Returns optional context information to this error.
const message& context() const;
inline const message& context() const noexcept {
return context_;
}
/// Returns `code() != 0`.
inline explicit operator bool() const noexcept {
......@@ -103,18 +113,18 @@ public:
}
/// Sets the error code to 0.
void clear();
/// Creates a flag storing the context size and the error code.
uint32_t compress_code_and_size() const;
inline void clear() noexcept {
code_ = 0;
context_.reset();
}
friend void serialize(serializer& sink, error& x, const unsigned int);
friend void serialize(deserializer& source, error& x, const unsigned int);
int compare(uint8_t code, atom_value category) const;
int compare(const error&) const noexcept;
int compare(const error&) const;
int compare(uint8_t code, atom_value category) const noexcept;
private:
uint8_t code_;
......
......@@ -46,24 +46,24 @@ public:
// tell actor_cast this pointer can be null
static constexpr bool has_non_null_guarantee = false;
constexpr intrusive_ptr() : ptr_(nullptr) {
constexpr intrusive_ptr() noexcept : ptr_(nullptr) {
// nop
}
intrusive_ptr(pointer raw_ptr, bool add_ref = true) {
intrusive_ptr(pointer raw_ptr, bool add_ref = true) noexcept {
set_ptr(raw_ptr, add_ref);
}
intrusive_ptr(intrusive_ptr&& other) : ptr_(other.detach()) {
intrusive_ptr(intrusive_ptr&& other) noexcept : ptr_(other.detach()) {
// nop
}
intrusive_ptr(const intrusive_ptr& other) {
intrusive_ptr(const intrusive_ptr& other) noexcept {
set_ptr(other.get(), true);
}
template <class Y>
intrusive_ptr(intrusive_ptr<Y> other) : ptr_(other.detach()) {
intrusive_ptr(intrusive_ptr<Y> other) noexcept : ptr_(other.detach()) {
static_assert(std::is_convertible<Y*, T*>::value,
"Y* is not assignable to T*");
}
......@@ -92,67 +92,67 @@ public:
return detach();
}
void reset(pointer new_value = nullptr, bool add_ref = true) {
void reset(pointer new_value = nullptr, bool add_ref = true) noexcept {
auto old = ptr_;
set_ptr(new_value, add_ref);
if (old)
intrusive_ptr_release(old);
}
intrusive_ptr& operator=(pointer ptr) {
intrusive_ptr& operator=(pointer ptr) noexcept {
reset(ptr);
return *this;
}
intrusive_ptr& operator=(intrusive_ptr other) {
intrusive_ptr& operator=(intrusive_ptr other) noexcept {
swap(other);
return *this;
}
pointer get() const {
pointer get() const noexcept {
return ptr_;
}
pointer operator->() const {
pointer operator->() const noexcept {
return ptr_;
}
reference operator*() const {
reference operator*() const noexcept {
return *ptr_;
}
bool operator!() const {
bool operator!() const noexcept {
return ! ptr_;
}
explicit operator bool() const {
explicit operator bool() const noexcept {
return ptr_ != nullptr;
}
ptrdiff_t compare(const_pointer ptr) const {
ptrdiff_t compare(const_pointer ptr) const noexcept {
return static_cast<ptrdiff_t>(get() - ptr);
}
ptrdiff_t compare(const intrusive_ptr& other) const {
ptrdiff_t compare(const intrusive_ptr& other) const noexcept {
return compare(other.get());
}
ptrdiff_t compare(std::nullptr_t) const {
ptrdiff_t compare(std::nullptr_t) const noexcept {
return reinterpret_cast<ptrdiff_t>(get());
}
template <class C>
intrusive_ptr<C> downcast() const {
intrusive_ptr<C> downcast() const noexcept {
return (ptr_) ? dynamic_cast<C*>(get()) : nullptr;
}
template <class C>
intrusive_ptr<C> upcast() const {
intrusive_ptr<C> upcast() const noexcept {
return (ptr_) ? static_cast<C*>(get()) : nullptr;
}
private:
void set_ptr(pointer raw_ptr, bool add_ref) {
void set_ptr(pointer raw_ptr, bool add_ref) noexcept {
ptr_ = raw_ptr;
if (raw_ptr && add_ref)
intrusive_ptr_add_ref(raw_ptr);
......
......@@ -48,68 +48,56 @@ class message_handler;
/// tuple with elements of any type.
class message {
public:
/// Creates an empty message.
message() = default;
// -- nested types -----------------------------------------------------------
/// Move constructor.
message(message&&);
struct cli_arg;
/// Copy constructor.
message(const message&) = default;
struct cli_res;
/// Move assignment.
message& operator=(message&&);
// -- member types -----------------------------------------------------------
/// Copy assignment.
message& operator=(const message&) = default;
/// Raw pointer to content.
using raw_ptr = detail::message_data*;
/// Returns the size of this message.
inline size_t size() const {
return vals_ ? vals_->size() : 0;
}
/// Copy-on-write pointer to content.
using data_ptr = detail::message_data::cow_ptr;
/// Creates a new message with all but the first n values.
message drop(size_t n) const;
/// Function object for generating CLI argument help text.
using help_factory = std::function<std::string (const std::vector<cli_arg>&)>;
/// Creates a new message with all but the last n values.
message drop_right(size_t n) const;
// -- constructors, destructors, and assignment operators --------------------
/// Creates a new message from the first n values.
inline message take(size_t n) const {
return n >= size() ? *this : drop_right(size() - n);
}
message() noexcept = default;
message(const message&) noexcept = default;
message& operator=(const message&) noexcept = default;
/// Creates a new message from the last n values.
inline message take_right(size_t n) const {
return n >= size() ? *this : drop(size() - n);
}
message(message&&) noexcept;
message& operator=(message&&) noexcept;
explicit message(const data_ptr& vals) noexcept;
/// Creates a new message of size `n` starting at the element at position `p`.
message slice(size_t p, size_t n) const;
~message();
// -- factories --------------------------------------------------------------
/// Concatinate messages
/// Creates a new message by concatenating `xs...`.
template <class... Ts>
static message concat(const Ts&... xs) {
return concat_impl({xs.vals()...});
}
/// Returns a mutable pointer to the element at position `p`.
void* get_mutable(size_t p);
/// Creates a new message from a type-erased tuple.
static message from(const type_erased_tuple* ptr);
/// Returns a const pointer to the element at position `p`.
const void* at(size_t p) const;
/// Creates a new message by copying all elements in a type-erased tuple.
static message copy_from(const type_erased_tuple* ptr);
/// Returns true if `size() == 0, otherwise false.
inline bool empty() const {
return size() == 0;
}
// -- modifiers --------------------------------------------------------------
/// Returns the value at position `p` as const reference of type `T`.
template <class T>
const T& get_as(size_t p) const {
CAF_ASSERT(match_element(p, type_nr<T>::value, &typeid(T)));
return *reinterpret_cast<const T*>(at(p));
}
/// Concatenates `*this` and `x`.
message& operator+=(const message& x);
/// Returns a mutable pointer to the element at position `p`.
void* get_mutable(size_t p);
/// Returns the value at position `p` as mutable reference of type `T`.
template <class T>
......@@ -121,6 +109,35 @@ public:
/// Returns `handler(*this)`.
optional<message> apply(message_handler handler);
/// Forces the message to copy its content if there are more than
/// one references to the content.
inline void force_unshare() {
vals_.unshare();
}
/// Returns a mutable reference to the content. Causes the message
/// to unshare its content if necessary.
inline data_ptr& vals() {
return vals_;
}
/// Exchanges content of `this` and `other`.
void swap(message& other) noexcept;
/// Assigns new content.
void reset(raw_ptr new_ptr = nullptr, bool add_ref = true) noexcept;
// -- observers --------------------------------------------------------------
/// Creates a new message with all but the first n values.
message drop(size_t n) const;
/// Creates a new message with all but the last n values.
message drop_right(size_t n) const;
/// Creates a new message of size `n` starting at the element at position `p`.
message slice(size_t p, size_t n) const;
/// Filters this message by applying slices of it to `handler` and returns
/// the remaining elements of this operation. Slices are generated in the
/// sequence `[0, size)`, `[0, size-1)`, `...` , `[1, size-1)`, `...`,
......@@ -153,65 +170,6 @@ public:
/// iterates a message only once, from left to right.
message extract(message_handler handler) const;
/// Stores the name of a command line option ("<long name>[,<short name>]")
/// along with a description and a callback.
struct cli_arg {
/// Returns `true` on a match, `false` otherwise.
using consumer = std::function<bool (const std::string&)>;
/// Full name of this CLI argument using format "<long name>[,<short name>]"
std::string name;
/// Desciption of this CLI argument for the auto-generated help text.
std::string text;
/// Auto-generated helptext for this item.
std::string helptext;
/// Evaluates option arguments.
consumer fun;
/// Set to true for zero-argument options.
bool* flag;
/// Creates a CLI argument without data.
cli_arg(std::string name, std::string text);
/// Creates a CLI flag option. The `flag` is set to `true` if the option
/// was set, otherwise it is `false`.
cli_arg(std::string name, std::string text, bool& flag);
/// Creates a CLI argument storing its matched argument in `dest`.
cli_arg(std::string name, std::string text, atom_value& dest);
/// Creates a CLI argument storing its matched argument in `dest`.
cli_arg(std::string name, std::string text, std::string& dest);
/// Creates a CLI argument appending matched arguments to `dest`.
cli_arg(std::string name, std::string text, std::vector<std::string>& dest);
/// Creates a CLI argument using the function object `f`.
cli_arg(std::string name, std::string text, consumer f);
/// Creates a CLI argument for converting from strings,
/// storing its matched argument in `dest`.
template <class T>
cli_arg(typename std::enable_if<
type_nr<T>::value != 0,
std::string
>::type name,
std::string text, T& dest);
/// Creates a CLI argument for converting from strings,
/// appending matched arguments to `dest`.
template <class T>
cli_arg(std::string name, std::string text, std::vector<T>& dest);
};
struct cli_res;
using help_factory = std::function<std::string (const std::vector<cli_arg>&)>;
/// A simplistic interface for using `extract` to parse command line options.
/// Usage example:
///
......@@ -254,90 +212,107 @@ public:
help_factory help_generator = nullptr,
bool suppress_help = false) const;
/// Queries whether the element at position `p` is of type `T`.
template <class T>
bool match_element(size_t p) const {
const std::type_info* rtti = nullptr;
if (type_nr<T>::value == 0) {
rtti = &typeid(T);
}
return match_element(p, type_nr<T>::value, rtti);
}
// -- inline observers -------------------------------------------------------
/// Queries whether the types of this message are `Ts...`.
template <class... Ts>
bool match_elements() const {
std::integral_constant<size_t, 0> p0;
detail::type_list<Ts...> tlist;
return size() == sizeof...(Ts) && match_elements_impl(p0, tlist);
/// Returns a const pointer to the element at position `p`.
inline const void* at(size_t p) const noexcept {
CAF_ASSERT(vals_);
return vals_->get(p);
}
inline std::pair<uint16_t, const std::type_info*> type(size_t pos) const {
return vals_->type(pos);
/// Returns a reference to the content.
inline const data_ptr& vals() const noexcept {
return vals_;
}
message& operator+=(const message& x);
/// Creates a message object from `ptr`.
static message from(const type_erased_tuple* ptr);
static message copy_from(const type_erased_tuple* ptr);
/// @cond PRIVATE
using raw_ptr = detail::message_data*;
/// Returns a reference to the content.
inline const data_ptr& cvals() const noexcept {
return vals_;
}
using data_ptr = detail::message_data::cow_ptr;
/// Returns a type hint for the pattern matching engine.
inline uint32_t type_token() const noexcept {
return vals_ ? vals_->type_token() : 0xFFFFFFFF;
}
explicit message(const data_ptr& vals);
/// Returns whether there are more than one references to the content.
inline bool shared() const noexcept {
return vals_ ? vals_->shared() : false;
}
inline data_ptr& vals() {
return vals_;
/// Returns the size of this message.
inline size_t size() const noexcept {
return vals_ ? vals_->size() : 0;
}
inline const data_ptr& vals() const {
return vals_;
/// Creates a new message from the first n values.
inline message take(size_t n) const {
return n >= size() ? *this : drop_right(size() - n);
}
inline const data_ptr& cvals() const {
return vals_;
/// Creates a new message from the last n values.
inline message take_right(size_t n) const {
return n >= size() ? *this : drop(size() - n);
}
inline uint32_t type_token() const {
return vals_ ? vals_->type_token() : 0xFFFFFFFF;
/// Returns true if `size() == 0, otherwise false.
inline bool empty() const {
return size() == 0;
}
inline void force_unshare() {
vals_.unshare();
/// Returns the value at position `p` as const reference of type `T`.
template <class T>
const T& get_as(size_t p) const {
CAF_ASSERT(match_element(p, type_nr<T>::value, &typeid(T)));
return *reinterpret_cast<const T*>(at(p));
}
inline bool shared() const {
return vals_ ? vals_->shared() : false;
/// Queries whether the element at position `p` is of type `T`.
template <class T>
bool match_element(size_t p) const noexcept {
auto rtti = type_nr<T>::value == 0 ? &typeid(T) : nullptr;
return match_element(p, type_nr<T>::value, rtti);
}
void reset(raw_ptr new_ptr = nullptr, bool add_ref = true);
/// Queries whether the types of this message are `Ts...`.
template <class... Ts>
bool match_elements() const noexcept {
std::integral_constant<size_t, 0> p0;
detail::type_list<Ts...> tlist;
return size() == sizeof...(Ts) && match_elements_impl(p0, tlist);
}
void swap(message& other);
/// Queries the run-time type information for the element at position `pos`.
inline std::pair<uint16_t, const std::type_info*>
type(size_t pos) const noexcept {
CAF_ASSERT(vals_ && vals_->size() > pos);
return vals_->type(pos);
}
bool match_element(size_t p, uint16_t tnr, const std::type_info* rtti) const;
/// Checks whether the type of the stored value at position `pos`
/// matches type number `n` and run-time type information `p`.
bool match_element(size_t pos, uint16_t n,
const std::type_info* p) const noexcept {
CAF_ASSERT(vals_);
return vals_->matches(pos, n, p);
}
template <class T, class... Ts>
bool match_elements(detail::type_list<T, Ts...> list) const {
bool match_elements(detail::type_list<T, Ts...> list) const noexcept {
std::integral_constant<size_t, 0> p0;
return size() == (sizeof...(Ts) + 1) && match_elements_impl(p0, list);
}
/// @endcond
private:
template <size_t P>
static bool match_elements_impl(std::integral_constant<size_t, P>,
detail::type_list<>) {
detail::type_list<>) noexcept {
return true; // end of recursion
}
template <size_t P, class T, class... Ts>
bool match_elements_impl(std::integral_constant<size_t, P>,
detail::type_list<T, Ts...>) const {
detail::type_list<T, Ts...>) const noexcept {
std::integral_constant<size_t, P + 1> next_p;
detail::type_list<Ts...> next_list;
return match_element<T>(P) && match_elements_impl(next_p, next_list);
......@@ -359,6 +334,90 @@ void serialize(deserializer& sink, message& msg, const unsigned int);
/// @relates message
std::string to_string(const message& msg);
/// Stores the name of a command line option ("<long name>[,<short name>]")
/// along with a description and a callback.
struct message::cli_arg {
/// Returns `true` on a match, `false` otherwise.
using consumer = std::function<bool (const std::string&)>;
/// Full name of this CLI argument using format "<long name>[,<short name>]"
std::string name;
/// Desciption of this CLI argument for the auto-generated help text.
std::string text;
/// Auto-generated helptext for this item.
std::string helptext;
/// Evaluates option arguments.
consumer fun;
/// Set to true for zero-argument options.
bool* flag;
/// Creates a CLI argument without data.
cli_arg(std::string name, std::string text);
/// Creates a CLI flag option. The `flag` is set to `true` if the option
/// was set, otherwise it is `false`.
cli_arg(std::string name, std::string text, bool& flag);
/// Creates a CLI argument storing its matched argument in `dest`.
cli_arg(std::string name, std::string text, atom_value& dest);
/// Creates a CLI argument storing its matched argument in `dest`.
cli_arg(std::string name, std::string text, std::string& dest);
/// Creates a CLI argument appending matched arguments to `dest`.
cli_arg(std::string name, std::string text, std::vector<std::string>& dest);
/// Creates a CLI argument using the function object `f`.
cli_arg(std::string name, std::string text, consumer f);
/// Creates a CLI argument for converting from strings,
/// storing its matched argument in `dest`.
template <class T>
cli_arg(typename std::enable_if<
type_nr<T>::value != 0,
std::string
>::type nstr,
std::string tstr, T& arg)
: name(std::move(nstr)),
text(std::move(tstr)),
flag(nullptr) {
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;
};
}
/// Creates a CLI argument for converting from strings,
/// appending matched arguments to `dest`.
template <class T>
cli_arg(std::string nstr, std::string tstr, std::vector<T>& arg)
: name(std::move(nstr)),
text(std::move(tstr)),
flag(nullptr) {
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;
};
}
};
/// Stores the result of `message::extract_opts`.
struct message::cli_res {
/// Stores the remaining (unmatched) arguments.
......@@ -443,50 +502,6 @@ inline message make_message() {
return message{};
}
/******************************************************************************
* template member function implementations *
******************************************************************************/
template <class T>
message::cli_arg::cli_arg(typename std::enable_if<
type_nr<T>::value != 0,
std::string
>::type
nstr, std::string tstr, T& arg)
: name(std::move(nstr)),
text(std::move(tstr)),
flag(nullptr) {
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>
message::cli_arg::cli_arg(std::string nstr, std::string tstr,
std::vector<T>& arg)
: name(std::move(nstr)),
text(std::move(tstr)),
flag(nullptr) {
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
#endif // CAF_MESSAGE_HPP
......@@ -61,20 +61,20 @@ public:
// -- pure virtual observers -------------------------------------------------
/// Returns the size of this tuple.
virtual size_t size() const = 0;
virtual size_t size() const noexcept = 0;
/// Returns whether multiple references to this tuple exist.
virtual bool shared() const = 0;
virtual bool shared() const noexcept = 0;
/// Returns a type hint for the element types.
virtual uint32_t type_token() const = 0;
virtual uint32_t type_token() const noexcept = 0;
/// Returns the type number and `std::type_info` object for
/// the element at position `pos`.
virtual rtti_pair type(size_t pos) const = 0;
virtual rtti_pair type(size_t pos) const noexcept = 0;
/// Returns the element at position `pos`.
virtual const void* get(size_t pos) const = 0;
virtual const void* get(size_t pos) const noexcept = 0;
/// Returns a string representation of the element at position `pos`.
virtual std::string stringify(size_t pos) const = 0;
......@@ -95,19 +95,19 @@ public:
/// Saves the content of the tuple to `sink`.
void save(serializer& sink) const;
/// Checks whether the type of the stored value matches
/// the type nr and type info object.
bool matches(size_t pos, uint16_t tnr, const std::type_info* tinf) const;
/// Checks whether the type of the stored value at position `pos`
/// matches type number `n` and run-time type information `p`.
bool matches(size_t pos, uint16_t n, const std::type_info* p) const noexcept;
// -- inline observers -------------------------------------------------------
/// Returns the type number for the element at position `pos`.
inline uint16_t type_nr(size_t pos) const {
inline uint16_t type_nr(size_t pos) const noexcept {
return type(pos).first;
}
/// Checks whether the type of the stored value matches `rtti`.
inline bool matches(size_t pos, const rtti_pair& rtti) const {
inline bool matches(size_t pos, const rtti_pair& rtti) const noexcept {
return matches(pos, rtti.first, rtti.second);
}
};
......@@ -162,23 +162,23 @@ public:
// -- overridden observers ---------------------------------------------------
size_t size() const override {
size_t size() const noexcept override {
return sizeof...(Ts);
}
bool shared() const override {
bool shared() const noexcept override {
return false;
}
uint32_t type_token() const override {
uint32_t type_token() const noexcept override {
return make_type_token<Ts...>();
}
rtti_pair type(size_t pos) const override {
rtti_pair type(size_t pos) const noexcept override {
return ptrs_[pos]->type();
}
const void* get(size_t pos) const override {
const void* get(size_t pos) const noexcept override {
return ptrs_[pos]->get();
}
......
......@@ -50,24 +50,26 @@ public:
// tell actor_cast this pointer can be null
static constexpr bool has_non_null_guarantee = false;
constexpr weak_intrusive_ptr() : ptr_(nullptr) {
constexpr weak_intrusive_ptr() noexcept : ptr_(nullptr) {
// nop
}
weak_intrusive_ptr(pointer raw_ptr, bool add_ref = true) {
weak_intrusive_ptr(pointer raw_ptr, bool add_ref = true) noexcept {
set_ptr(raw_ptr, add_ref);
}
weak_intrusive_ptr(weak_intrusive_ptr&& other) : ptr_(other.detach()) {
weak_intrusive_ptr(weak_intrusive_ptr&& other) noexcept
: ptr_(other.detach()) {
// nop
}
weak_intrusive_ptr(const weak_intrusive_ptr& other) {
weak_intrusive_ptr(const weak_intrusive_ptr& other) noexcept {
set_ptr(other.get(), true);
}
template <class Y>
weak_intrusive_ptr(weak_intrusive_ptr<Y> other) : ptr_(other.detach()) {
weak_intrusive_ptr(weak_intrusive_ptr<Y> other) noexcept
: ptr_(other.detach()) {
static_assert(std::is_convertible<Y*, T*>::value,
"Y* is not assignable to T*");
}
......@@ -103,50 +105,50 @@ public:
intrusive_ptr_release_weak(old);
}
weak_intrusive_ptr& operator=(pointer ptr) {
weak_intrusive_ptr& operator=(pointer ptr) noexcept {
reset(ptr);
return *this;
}
weak_intrusive_ptr& operator=(weak_intrusive_ptr other) {
weak_intrusive_ptr& operator=(weak_intrusive_ptr other) noexcept {
swap(other);
return *this;
}
pointer get() const {
pointer get() const noexcept {
return ptr_;
}
pointer operator->() const {
pointer operator->() const noexcept {
return ptr_;
}
reference operator*() const {
reference operator*() const noexcept {
return *ptr_;
}
bool operator!() const {
bool operator!() const noexcept {
return ! ptr_;
}
explicit operator bool() const {
explicit operator bool() const noexcept {
return static_cast<bool>(ptr_);
}
ptrdiff_t compare(const_pointer ptr) const {
ptrdiff_t compare(const_pointer ptr) const noexcept {
return static_cast<ptrdiff_t>(get() - ptr);
}
ptrdiff_t compare(const weak_intrusive_ptr& other) const {
ptrdiff_t compare(const weak_intrusive_ptr& other) const noexcept {
return compare(other.get());
}
ptrdiff_t compare(std::nullptr_t) const {
ptrdiff_t compare(std::nullptr_t) const noexcept {
return reinterpret_cast<ptrdiff_t>(get());
}
/// Tries to upgrade this weak reference to a strong reference.
intrusive_ptr<T> lock() const {
intrusive_ptr<T> lock() const noexcept {
if (! ptr_ || ! intrusive_ptr_upgrade_weak(ptr_))
return nullptr;
// reference count already increased by intrusive_ptr_upgrade_weak
......@@ -156,14 +158,14 @@ public:
/// Tries to upgrade this weak reference to a strong reference.
/// Returns a pointer with increased strong reference count
/// on success, `nullptr` otherwise.
pointer get_locked() const {
pointer get_locked() const noexcept {
if (! ptr_ || ! intrusive_ptr_upgrade_weak(ptr_))
return nullptr;
return ptr_;
}
private:
void set_ptr(pointer raw_ptr, bool add_ref) {
void set_ptr(pointer raw_ptr, bool add_ref) noexcept {
ptr_ = raw_ptr;
if (raw_ptr && add_ref)
intrusive_ptr_add_weak_ref(raw_ptr);
......
......@@ -69,21 +69,21 @@ void concatenated_tuple::load(size_t pos, deserializer& source) {
selected.first->load(selected.second, source);
}
size_t concatenated_tuple::size() const {
size_t concatenated_tuple::size() const noexcept {
return size_;
}
uint32_t concatenated_tuple::type_token() const {
uint32_t concatenated_tuple::type_token() const noexcept {
return type_token_;
}
message_data::rtti_pair concatenated_tuple::type(size_t pos) const {
message_data::rtti_pair concatenated_tuple::type(size_t pos) const noexcept {
CAF_ASSERT(pos < size());
auto selected = select(pos);
return selected.first->type(selected.second);
}
const void* concatenated_tuple::get(size_t pos) const {
const void* concatenated_tuple::get(size_t pos) const noexcept {
CAF_ASSERT(pos < size());
auto selected = select(pos);
return selected.first->get(selected.second);
......
......@@ -64,19 +64,20 @@ void decorated_tuple::load(size_t pos, deserializer& source) {
return decorated_->load(mapping_[pos], source);
}
size_t decorated_tuple::size() const {
size_t decorated_tuple::size() const noexcept {
return mapping_.size();
}
uint32_t decorated_tuple::type_token() const {
uint32_t decorated_tuple::type_token() const noexcept {
return type_token_;
}
message_data::rtti_pair decorated_tuple::type(size_t pos) const {
message_data::rtti_pair decorated_tuple::type(size_t pos) const noexcept {
CAF_ASSERT(pos < size());
return decorated_->type(mapping_[pos]);
}
const void* decorated_tuple::get(size_t pos) const {
const void* decorated_tuple::get(size_t pos) const noexcept {
CAF_ASSERT(pos < size());
return decorated_->get(mapping_[pos]);
}
......
......@@ -62,21 +62,20 @@ void dynamic_message_data::load(size_t pos, deserializer& source) {
elements_[pos]->load(source);
}
size_t dynamic_message_data::size() const {
size_t dynamic_message_data::size() const noexcept {
return elements_.size();
}
uint32_t dynamic_message_data::type_token() const {
uint32_t dynamic_message_data::type_token() const noexcept {
return type_token_;
}
auto dynamic_message_data::type(size_t pos) const -> rtti_pair {
auto dynamic_message_data::type(size_t pos) const noexcept -> rtti_pair {
CAF_ASSERT(pos < size());
return elements_[pos]->type();
}
const void* dynamic_message_data::get(size_t pos) const {
CAF_ASSERT(pos < size());
const void* dynamic_message_data::get(size_t pos) const noexcept {
CAF_ASSERT(pos < size());
return elements_[pos]->get();
}
......
......@@ -25,37 +25,21 @@
namespace caf {
error::error() : code_(0), category_(atom("")) {
error::error() noexcept : code_(0), category_(atom("")) {
// nop
}
error::error(uint8_t x, atom_value y, message z)
error::error(uint8_t x, atom_value y) noexcept : code_(x), category_(y) {
// nop
}
error::error(uint8_t x, atom_value y, message z) noexcept
: code_(x),
category_(y),
context_(std::move(z)) {
// nop
}
uint8_t error::code() const {
return code_;
}
atom_value error::category() const {
return category_;
}
message& error::context() {
return context_;
}
const message& error::context() const {
return context_;
}
void error::clear() {
code_ = 0;
}
void serialize(serializer& sink, error& x, const unsigned int) {
sink << x.code_ << x.category_ << x.context_;
}
......@@ -64,7 +48,11 @@ void serialize(deserializer& source, error& x, const unsigned int) {
source >> x.code_ >> x.category_ >> x.context_;
}
int error::compare(uint8_t x, atom_value y) const {
int error::compare(const error& x) const noexcept {
return compare(x.code(), x.category());
}
int error::compare(uint8_t x, atom_value y) const noexcept {
// exception: all errors with default value are considered no error -> equal
if (code_ == 0 && x == 0)
return 0;
......@@ -75,10 +63,6 @@ int error::compare(uint8_t x, atom_value y) const {
return static_cast<int>(code_) - x;
}
int error::compare(const error& x) const {
return compare(x.code(), x.category());
}
std::string to_string(const error& x) {
if (! x)
return "no-error";
......
......@@ -71,21 +71,21 @@ void merged_tuple::load(size_t pos, deserializer& source) {
data_[p.first]->load(p.second, source);
}
size_t merged_tuple::size() const {
size_t merged_tuple::size() const noexcept {
return mapping_.size();
}
uint32_t merged_tuple::type_token() const {
uint32_t merged_tuple::type_token() const noexcept {
return type_token_;
}
merged_tuple::rtti_pair merged_tuple::type(size_t pos) const {
merged_tuple::rtti_pair merged_tuple::type(size_t pos) const noexcept {
CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos];
return data_[p.first]->type(p.second);
}
const void* merged_tuple::get(size_t pos) const {
const void* merged_tuple::get(size_t pos) const noexcept {
CAF_ASSERT(pos < mapping_.size());
auto& p = mapping_[pos];
return data_[p.first]->get(p.second);
......
......@@ -34,24 +34,28 @@
namespace caf {
message::message(message&& other) : vals_(std::move(other.vals_)) {
message::message(message&& other) noexcept : vals_(std::move(other.vals_)) {
// nop
}
message::message(const data_ptr& ptr) : vals_(ptr) {
message::message(const data_ptr& ptr) noexcept : vals_(ptr) {
// nop
}
message& message::operator=(message&& other) {
message& message::operator=(message&& other) noexcept {
vals_.swap(other.vals_);
return *this;
}
void message::reset(raw_ptr new_ptr, bool add_ref) {
message::~message() {
// nop
}
void message::reset(raw_ptr new_ptr, bool add_ref) noexcept {
vals_.reset(new_ptr, add_ref);
}
void message::swap(message& other) {
void message::swap(message& other) noexcept {
vals_.swap(other.vals_);
}
......@@ -60,11 +64,6 @@ void* message::get_mutable(size_t p) {
return vals_->get_mutable(p);
}
const void* message::at(size_t p) const {
CAF_ASSERT(vals_);
return vals_->get(p);
}
message message::from(const type_erased_tuple* ptr) {
if (! ptr)
return message{};
......@@ -86,11 +85,6 @@ message message::copy_from(const type_erased_tuple* ptr) {
return mb.move_to_message();
}
bool message::match_element(size_t pos, uint16_t typenr,
const std::type_info* rtti) const {
return vals_->matches(pos, typenr, rtti);
}
message& message::operator+=(const message& x) {
auto tmp = *this + x;
swap(tmp);
......
......@@ -28,7 +28,7 @@ message_data::~message_data() {
// nop
}
bool message_data::shared() const {
bool message_data::shared() const noexcept {
return ! unique();
}
......
......@@ -57,7 +57,7 @@ void type_erased_tuple::save(serializer& sink) const {
}
bool type_erased_tuple::matches(size_t pos, uint16_t nr,
const std::type_info* ptr) const {
const std::type_info* ptr) const noexcept {
CAF_ASSERT(pos < size());
auto tp = type(pos);
if (tp.first != nr)
......
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