File: param.hpp

package info (click to toggle)
actor-framework 0.17.6-3.2
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 9,008 kB
  • sloc: cpp: 77,684; sh: 674; python: 309; makefile: 13
file content (126 lines) | stat: -rw-r--r-- 3,660 bytes parent folder | download | duplicates (4)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <type_traits>

#include "caf/atom.hpp"

namespace caf {

/// Represents a message handler parameter of type `T` and
/// guarantees copy-on-write semantics.
template <class T>
class param {
public:
  enum flag {
    shared_access,    // x_ lives in a shared type_erased_tuple
    exclusive_access, // x_ lives in an unshared type_erased_tuple
    private_access    // x_ is a copy of the original value
  };

  param(const void* ptr, bool is_shared)
      : x_(reinterpret_cast<T*>(const_cast<void*>(ptr))) {
    flag_ = is_shared ? shared_access : exclusive_access;
  }

  param(const param& other) = delete;
  param& operator=(const param& other) = delete;

  param(param&& other) : x_(other.x_), flag_(other.flag_) {
    other.x_ = nullptr;
  }

  ~param() {
    if (flag_ == private_access)
      delete x_;
  }

  const T& get() const {
    return *x_;
  }

  operator const T&() const {
    return *x_;
  }

  const T* operator->() const {
    return x_;
  }

  /// Detaches the value if needed and returns a mutable reference to it.
  T& get_mutable() {
    if (flag_ == shared_access) {
      auto cpy = new T(get());
      x_ = cpy;
      flag_ = private_access;
    }
    return *x_;
  }

  /// Moves the value out of the `param`.
  T&& move() {
    return std::move(get_mutable());
  }

private:
  T* x_;
  flag flag_;
};

/// Converts `T` to `param<T>` unless `T` is arithmetic, an atom constant, or
/// a stream handshake.
template <class T>
struct add_param : std::conditional<std::is_arithmetic<T>::value, T, param<T>> {
  // nop
};

template <atom_value V>
struct add_param<atom_constant<V>> {
  using type = atom_constant<V>;
};

template <class T>
struct add_param<stream<T>> {
  using type = stream<T>;
};

/// Convenience alias that wraps `T` into `param<T>` unless `T` is arithmetic,
/// a stream handshake or an atom constant.
template <class T>
using param_t = typename add_param<T>::type;

/// Unpacks `param<T>` to `T`.
template <class T>
struct remove_param {
  using type = T;
};

template <class T>
struct remove_param<param<T>> {
  using type = T;
};

/// Convenience struct for `remove_param<std::decay<T>>`.
template <class T>
struct param_decay {
  using type = typename remove_param<typename std::decay<T>::type>::type;
};

} // namespace caf