File: message_builder.hpp

package info (click to toggle)
actor-framework 0.18.7-1~exp1
  • links: PTS
  • area: main
  • in suites: experimental
  • size: 8,740 kB
  • sloc: cpp: 85,162; sh: 491; python: 187; makefile: 11
file content (110 lines) | stat: -rw-r--r-- 3,452 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.

#pragma once

#include <vector>

#include "caf/detail/core_export.hpp"
#include "caf/detail/implicit_conversions.hpp"
#include "caf/detail/message_builder_element.hpp"
#include "caf/detail/padded_size.hpp"
#include "caf/detail/type_id_list_builder.hpp"
#include "caf/fwd.hpp"
#include "caf/message.hpp"

namespace caf {

/// Provides a convenient interface for creating `message` objects
/// from a series of values using the member function `append`.
class CAF_CORE_EXPORT message_builder {
public:
  friend class message;

  message_builder() = default;

  message_builder(const message_builder&) = delete;

  message_builder& operator=(const message_builder&) = delete;

  /// Creates a new instance and immediately calls `append(first, last)`.
  template <class Iter>
  message_builder(Iter first, Iter last) {
    append(first, last);
  }

  /// Appends all values in range [first, last).
  template <class Iter>
  message_builder& append(Iter first, Iter last) {
    for (; first != last; ++first)
      append(*first);
    return *this;
  }

  /// Adds `x` to the elements of the buffer.
  template <class T>
  message_builder& append(T&& x) {
    using value_type = detail::strip_and_convert_t<T>;
    static_assert(detail::sendable<value_type>);
    using wrapper_type = detail::message_builder_element_impl<value_type>;
    storage_size_ += detail::padded_size_v<value_type>;
    types_.push_back(type_id_v<value_type>);
    elements_.emplace_back(std::make_unique<wrapper_type>(std::forward<T>(x)));
    return *this;
  }

  /// Adds elements `n` elements from `msg` to the buffer, starting at index
  /// `first`.
  /// @note Always appends *copies* of the elements.
  message_builder& append_from(const caf::message& msg, size_t first,
                               size_t n = 1);

  template <class... Ts>
  message_builder& append_all(Ts&&... xs) {
    (append(std::forward<Ts>(xs)), ...);
    return *this;
  }

  template <class Tuple, size_t... Is>
  message_builder& append_tuple(Tuple& xs, std::index_sequence<Is...>) {
    (append(std::get<Is>(xs)), ...);
    return *this;
  }

  template <class... Ts>
  message_builder& append_tuple(std::tuple<Ts...> xs) {
    return append_tuple(std::integral_constant<size_t, 0>{},
                        std::integral_constant<size_t, sizeof...(Ts)>{}, xs);
  }

  /// Converts the buffer to an actual message object without
  /// invalidating this message builder (nor clearing it).
  message to_message() const;

  /// Converts the buffer to an actual message object and transfers
  /// ownership of the data to it, leaving this object in an invalid state.
  /// @warning Calling *any*  member function on this object afterwards
  ///          is undefined behavior.
  message move_to_message();

  /// Removes all elements from the buffer.
  void clear() noexcept;

  /// Returns whether the buffer is empty.
  bool empty() const noexcept {
    return elements_.empty();
  }

  /// Returns the number of elements in the buffer.
  size_t size() const noexcept {
    return elements_.size();
  }

private:
  size_t storage_size_ = 0;
  detail::type_id_list_builder types_;
  std::vector<detail::message_builder_element_ptr> elements_;
};

} // namespace caf