stlab 2.3.0
Modern, modular C++ algorithms, data structures, and concurrency primitives
Loading...
Searching...
No Matches
model.hpp
Go to the documentation of this file.
1/*
2 Copyright 2015 Adobe
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5*/
6
7/**************************************************************************************************/
8
9#ifndef STLAB_MODEL_HPP
10#define STLAB_MODEL_HPP
11
19
20/**************************************************************************************************/
21
22#include <stlab/config.hpp>
23
24#include <atomic>
25#include <condition_variable>
26#include <iostream>
27#include <mutex>
28
30
31/**************************************************************************************************/
32
33namespace stlab {
34STLAB_VERSION_NAMESPACE_BEGIN()
35
36
41
42/**************************************************************************************************/
43
44
46 std::atomic_size_t _dtor{0};
47 std::atomic_size_t _copy_ctor{0};
48 std::atomic_size_t _move_ctor{0};
49 std::atomic_size_t _copy_assign_lhs{0};
50 std::atomic_size_t _copy_assign_rhs{0};
51 std::atomic_size_t _move_assign_lhs{0};
52 std::atomic_size_t _move_assign_rhs{0};
53 std::atomic_size_t _swap{0};
54 std::atomic_size_t _equality{0};
55 std::mutex _mutex;
56 std::condition_variable _condition;
57
58 auto remaining() const -> std::size_t { return _copy_ctor + _move_ctor - _dtor + 1; }
59
60 void wait(std::size_t count) {
62 std::unique_lock<std::mutex> lock(_mutex);
63 _condition.wait(lock, [&] { return count == remaining(); });
64 });
65 }
66
67 friend inline auto operator<<(std::ostream& out, const annotate_counters& x) -> std::ostream& {
68 out << " dtor: " << x._dtor << "\n";
69 out << " copy_ctor: " << x._copy_ctor << "\n";
70 out << " move_ctor: " << x._move_ctor << "\n";
71 out << "copy_assign_lhs: " << x._copy_assign_lhs << "\n";
72 out << "copy_assign_rhs: " << x._copy_assign_rhs << "\n";
73 out << "move_assign_lhs: " << x._move_assign_lhs << "\n";
74 out << "move_assign_rhs: " << x._move_assign_rhs << "\n";
75 out << " swap: " << x._swap << "\n";
76 out << " equality: " << x._equality << "\n";
77
78 return out;
79 }
80};
81
87struct annotate {
88 annotate_counters* _counters;
89 explicit annotate(annotate_counters& counters) : _counters(&counters) {}
90
91 ~annotate() {
92 {
93 ++_counters->_dtor;
94 _counters->_condition.notify_one();
95 }
96 }
97
98 annotate(const annotate& x) : _counters(x._counters) { ++_counters->_copy_ctor; }
99 annotate(annotate&& x) noexcept : _counters(x._counters) { ++_counters->_move_ctor; }
100
101 auto operator=(const annotate& x) -> annotate& {
102 if (this == &x) return *this;
103 ++x._counters->_copy_assign_rhs;
104 ++_counters->_copy_assign_lhs;
105 return *this;
106 }
107 auto operator=(annotate&& x) noexcept -> annotate& {
108 ++x._counters->_move_assign_rhs;
109 ++_counters->_move_assign_lhs;
110 return *this;
111 }
112
113 friend inline void swap(annotate& x, annotate& y) noexcept {
114 ++x._counters->_swap;
115 ++y._counters->_swap;
116 }
117
118 friend inline auto operator==(const annotate& x, const annotate& y) -> bool {
119 ++x._counters->_equality;
120 ++y._counters->_equality;
121 return true;
122 }
123 friend inline auto operator!=(const annotate& x, const annotate& y) -> bool {
124 return !(x == y);
125 }
126};
127
128/**************************************************************************************************/
129
134struct regular {
135 int _x;
136
137 explicit regular(int x) : _x(x) { std::cout << _x << " ctor" << '\n'; }
138 ~regular() { std::cout << _x << " dtor" << '\n'; }
139
140 regular(const regular& rhs) : _x(rhs._x) { std::cout << _x << " copy-ctor" << '\n'; }
141 regular(regular&& rhs) noexcept : _x(rhs._x) {
142 std::cout << _x << " move-ctor" << '\n';
143 rhs._x = 0;
144 }
145
146 auto operator=(const regular& rhs) -> regular& {
147 std::cout << _x << " assign" << '\n';
148 if (&rhs == this) return *this;
149 _x = rhs._x;
150 return *this;
151 }
152 auto operator=(regular&& rhs) noexcept -> regular& {
153 std::cout << _x << " move-assign" << '\n';
154 _x = rhs._x;
155 rhs._x = 0;
156 return *this;
157 }
158
159 friend inline void swap(regular& lhs, regular& rhs) noexcept {
160 std::cout << lhs._x << "/" << rhs._x << " swap " << '\n';
161 std::swap(lhs._x, rhs._x);
162 }
163
164 friend inline auto operator==(const regular& lhs, const regular& rhs) -> bool {
165 return lhs._x == rhs._x;
166 }
167 friend inline auto operator!=(const regular& lhs, const regular& rhs) -> bool {
168 return !(lhs == rhs);
169 }
170
171 friend inline auto operator<(const regular& lhs, const regular& rhs) -> bool {
172 bool result(lhs._x < rhs._x);
173 std::cout << lhs._x << " < " << rhs._x << ": " << std::boolalpha << result << '\n';
174 return result;
175 }
176};
177
178/**************************************************************************************************/
179
185class move_only {
186private:
187 int _member{0};
188
189public:
190 move_only() = default;
191 move_only(int member) : _member(member) {}
192 move_only(const move_only&) = delete;
193 auto operator=(const move_only&) -> move_only& = delete;
194 move_only(move_only&&) = default;
195 auto operator=(move_only&&) -> move_only& = default;
196 virtual ~move_only() = default;
197
198 auto member() -> int { return _member; }
199 [[nodiscard]] auto member() const -> int { return _member; }
200
201 friend auto operator==(const move_only& a, const move_only& b) -> bool {
202 return a._member == b._member;
203 }
204 friend auto operator!=(const move_only& a, const move_only& b) -> bool { return !(a == b); }
205};
206
207/**************************************************************************************************/
208
210
211STLAB_VERSION_NAMESPACE_END()
212} // namespace stlab
213
214/**************************************************************************************************/
215
216#endif
217
218/**************************************************************************************************/
Blocking wait helpers for futures (await, await_for, deprecated blocking_get, …).
auto invoke_waiting(F &&f)
Assumes f will block waiting; on the portable task system, wakes the pool or adds a worker (up to the...
Definition await.hpp:57
Definition reverse.hpp:28
Shared counters for annotate special-member and comparison instrumentation.
Definition model.hpp:45