Skip to content

Commit 9a57392

Browse files
Added support for atomic flags
1 parent 731e0f0 commit 9a57392

8 files changed

Lines changed: 72 additions & 22 deletions

File tree

include/rfl/atomic/is_atomic.hpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33

44
#include <array>
55
#include <atomic>
6-
#include <memory>
76
#include <type_traits>
87

9-
#include "../Box.hpp"
108
#include "../NamedTuple.hpp"
11-
#include "../Ref.hpp"
129
#include "../Tuple.hpp"
1310
#include "../named_tuple_t.hpp"
1411
#include "../to_view.hpp"
@@ -34,6 +31,19 @@ struct is_atomic<std::atomic<T>> {
3431
};
3532
};
3633

34+
template <>
35+
struct is_atomic<std::atomic_flag> {
36+
static constexpr bool value = true;
37+
using RemoveAtomicT = bool;
38+
static void set(RemoveAtomicT&& val, std::atomic_flag* _t) {
39+
if (val) {
40+
_t->test_and_set(std::memory_order_relaxed);
41+
} else {
42+
_t->clear(std::memory_order_relaxed);
43+
}
44+
}
45+
};
46+
3747
template <class T, size_t N>
3848
struct is_atomic<std::array<T, N>> {
3949
using Type = std::remove_cvref_t<T>;
@@ -58,7 +68,7 @@ struct is_atomic<T[N]> {
5868
static void set(RemoveAtomicT&& val, T (*_t)[N]) {
5969
for (size_t i = 0; i < N; ++i) {
6070
is_atomic<T>::set(
61-
std::forward<typename is_atomic<T>::RemoveAtomicT>(val[i]),
71+
std::forward<typename is_atomic<Type>::RemoveAtomicT>(val[i]),
6272
&((*_t)[i]));
6373
}
6474
}
@@ -75,16 +85,16 @@ struct is_atomic<NamedTuple<Fields...>> {
7585

7686
static void set(RemoveAtomicT&& val, NamedTuple<Fields...>* _t) {
7787
(is_atomic<typename Fields::Type>::set(
78-
std::forward<typename is_atomic<typename Fields::Type>::RemoveAtomicT>(
88+
std::forward<typename is_atomic<
89+
std::remove_cvref_t<typename Fields::Type>>::RemoveAtomicT>(
7990
val.template get<Fields::name_>()),
8091
&(_t->template get<Fields::name_>())),
8192
...);
8293
}
8394
};
8495

8596
template <class T>
86-
requires(std::is_class_v<T> && std::is_aggregate_v<T> &&
87-
!std::is_move_constructible_v<T>)
97+
requires(std::is_class_v<T> && std::is_aggregate_v<T>)
8898
struct is_atomic<T> {
8999
static constexpr bool value = is_atomic<named_tuple_t<T>>::value;
90100

include/rfl/parsing/Parser.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "Parser_array.hpp"
55
#include "Parser_atomic.hpp"
6+
#include "Parser_atomic_flag.hpp"
67
#include "Parser_base.hpp"
78
#include "Parser_basic_type.hpp"
89
#include "Parser_box.hpp"

include/rfl/parsing/Parser_atomic.hpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@ template <class R, class W, class T, class ProcessorsType>
1818
struct Parser<R, W, std::atomic<T>, ProcessorsType> {
1919
using InputVarType = typename R::InputVarType;
2020

21-
using ParentType = Parent<W>;
22-
23-
static Result<T> read(const R& _r, const InputVarType& _var) noexcept {
24-
return Parser<R, W, std::remove_cvref_t<T>, ProcessorsType>::read(_r, _var);
25-
}
21+
/// Read is not supported for atomic types - we must used rfl::atomic instead.
2622

2723
template <class P>
2824
static void write(const W& _w, const std::atomic<T>& _a, const P& _parent) {
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifndef RFL_PARSING_PARSER_ATOMIC_FLAG_HPP_
2+
#define RFL_PARSING_PARSER_ATOMIC_FLAG_HPP_
3+
4+
#include <atomic>
5+
#include <map>
6+
#include <type_traits>
7+
8+
#include "../DefaultVal.hpp"
9+
#include "AreReaderAndWriter.hpp"
10+
#include "Parent.hpp"
11+
#include "Parser_base.hpp"
12+
#include "schema/Type.hpp"
13+
14+
namespace rfl::parsing {
15+
16+
template <class R, class W, class ProcessorsType>
17+
requires AreReaderAndWriter<R, W, std::atomic_flag>
18+
struct Parser<R, W, std::atomic_flag, ProcessorsType> {
19+
using InputVarType = typename R::InputVarType;
20+
21+
/// Read is not supported for atomic types - we must used rfl::atomic instead.
22+
23+
template <class P>
24+
static void write(const W& _w, const std::atomic_flag& _a, const P& _parent) {
25+
Parser<R, W, bool, ProcessorsType>::write(
26+
_w, _a.test(std::memory_order_relaxed), _parent);
27+
}
28+
29+
static schema::Type to_schema(
30+
std::map<std::string, schema::Type>* _definitions) {
31+
return schema::Type{
32+
Parser<R, W, bool, ProcessorsType>::to_schema(_definitions)};
33+
}
34+
};
35+
36+
} // namespace rfl::parsing
37+
38+
#endif

tests/json/test_atomic.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace test_atomic {
1111
struct Stats {
1212
std::atomic<std::uint64_t> bytes_downloaded;
1313
std::atomic<bool> finished;
14+
std::atomic_flag atomic_flag;
1415
rfl::Ref<std::atomic<int>> ref_atomic_int;
1516
rfl::Box<std::atomic<int>> box_atomic_int;
1617
std::shared_ptr<std::atomic<int>> shared_atomic_int;
@@ -21,6 +22,7 @@ TEST(json, test_atomic) {
2122
auto stats =
2223
Stats{.bytes_downloaded = 123456789,
2324
.finished = true,
25+
.atomic_flag = ATOMIC_FLAG_INIT,
2426
.ref_atomic_int = rfl::make_ref<std::atomic<int>>(42),
2527
.box_atomic_int = rfl::Box<std::atomic<int>>::make(7),
2628
.shared_atomic_int = std::make_shared<std::atomic<int>>(13),
@@ -40,6 +42,6 @@ TEST(json, test_atomic) {
4042
EXPECT_EQ(rfl::json::write(stats2), json_str);
4143
EXPECT_EQ(
4244
json_str,
43-
R"({"bytes_downloaded":123456789,"finished":true,"ref_atomic_int":42,"box_atomic_int":7,"shared_atomic_int":13,"unique_atomic_int":21})");
45+
R"({"bytes_downloaded":123456789,"finished":true,"atomic_flag":false,"ref_atomic_int":42,"box_atomic_int":7,"shared_atomic_int":13,"unique_atomic_int":21})");
4446
}
4547
} // namespace test_atomic

tests/json/test_atomic_array.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,20 @@ namespace test_atomic_array {
1010
struct Stats {
1111
std::atomic<std::uint64_t> bytes_downloaded;
1212
std::atomic<bool> finished;
13+
std::atomic_flag atomic_flag = ATOMIC_FLAG_INIT;
1314
};
1415

1516
TEST(json, test_atomic_array) {
1617
auto arr = rfl::Ref<std::array<Stats, 2>>{};
1718
(*arr)[0].bytes_downloaded = 123456789;
1819
(*arr)[0].finished = true;
20+
(*arr)[0].atomic_flag.test_and_set();
1921
(*arr)[1].bytes_downloaded = 987654321;
2022
(*arr)[1].finished = false;
23+
(*arr)[1].atomic_flag.clear();
2124

2225
write_and_read(
2326
arr,
24-
R"([{"bytes_downloaded":123456789,"finished":true},{"bytes_downloaded":987654321,"finished":false}])");
27+
R"([{"bytes_downloaded":123456789,"finished":true,"atomic_flag":true},{"bytes_downloaded":987654321,"finished":false,"atomic_flag":false}])");
2528
}
2629
} // namespace test_atomic_array

tests/json/test_atomic_box.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55

66
#include "write_and_read.hpp"
77

8-
namespace test_atomic_ref {
8+
namespace test_atomic_box {
99

1010
struct Stats {
1111
std::atomic<std::uint64_t> bytes_downloaded;
1212
std::atomic<bool> finished;
1313
};
1414

15-
TEST(json, test_atomic_ref) {
16-
auto stats = rfl::make_ref<Stats>(123456789, true);
15+
TEST(json, test_atomic_box) {
16+
auto stats = rfl::make_box<Stats>(123456789, true);
1717

1818
write_and_read(stats, R"({"bytes_downloaded":123456789,"finished":true})");
1919
}
20-
} // namespace test_atomic_ref
20+
} // namespace test_atomic_box

tests/json/test_atomic_ref.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55

66
#include "write_and_read.hpp"
77

8-
namespace test_atomic_box {
8+
namespace test_atomic_ref {
99

1010
struct Stats {
1111
std::atomic<std::uint64_t> bytes_downloaded;
1212
std::atomic<bool> finished;
1313
};
1414

15-
TEST(json, test_atomic_box) {
16-
auto stats = rfl::make_box<Stats>(123456789, true);
15+
TEST(json, test_atomic_ref) {
16+
auto stats = rfl::make_ref<Stats>(123456789, true);
1717

1818
write_and_read(stats, R"({"bytes_downloaded":123456789,"finished":true})");
1919
}
20-
} // namespace test_atomic_box
20+
} // namespace test_atomic_ref

0 commit comments

Comments
 (0)