1111
1212#include < algorithm>
1313#include < atomic>
14+ #include < cstddef>
1415#include < iostream>
1516#include < type_traits>
1617#include < vector>
1718
19+ #include " assert.hh"
20+ #include " fwd.hh"
21+
1822namespace reactor {
1923
2024class BaseMultiport { // NOLINT cppcoreguidelines-special-member-functions,-warnings-as-errors
21- protected :
22- std::atomic<std::size_t > size_{0 }; // NOLINT
23- std::vector<std::size_t > present_ports_{}; // NOLINT
25+ private :
26+ std::atomic<std::size_t > size_{0 };
27+ std::vector<std::size_t > present_ports_{};
2428
25- public:
26- BaseMultiport () = default ;
27- ~BaseMultiport () = default ;
29+ // record that the port with the given index has been set
30+ inline void set_present (std::size_t index);
2831
29- // tells the parent multiport that this port has been set.
30- [[nodiscard]] inline auto set_present (std::size_t index) -> bool {
31- auto calculated_index = size_.fetch_add (1 , std::memory_order_relaxed);
32+ // reset the list of set port indexes
33+ inline void reset () noexcept { size_.store (0 , std::memory_order_relaxed); }
3234
33- reactor_assert (calculated_index < present_ports_.size ());
35+ [[nodiscard]] auto get_set_callback (std::size_t index) noexcept -> PortCallback;
36+ const PortCallback clean_callback_{[this ]([[maybe_unused]] const BasePort& port) { this ->reset (); }};
3437
35- present_ports_[calculated_index] = index;
36- return true ;
37- }
38+ [[nodiscard]] auto get_clean_callback () const noexcept -> const PortCallback& { return clean_callback_; }
3839
39- // resets parent multiport
40- inline void clear () noexcept { size_.store (0 , std::memory_order_relaxed); }
40+ protected:
41+ [[nodiscard]] inline auto present_ports () const -> const auto& { return present_ports_; }
42+ [[nodiscard]] inline auto present_ports_size () const -> auto { return size_.load (); }
43+
44+ inline void present_ports_reserve (size_t n) { present_ports_.reserve (n); }
45+
46+ void register_port (BasePort& port, size_t idx);
47+
48+ public:
49+ BaseMultiport () = default ;
50+ ~BaseMultiport () = default ;
4151};
4252
4353template <class T , class A = std::allocator<T>>
4454class Multiport : public BaseMultiport { // NOLINT cppcoreguidelines-special-member-functions
4555protected:
46- std::vector<T> data_ {}; // NOLINT cppcoreguidelines-non-private-member-variables-in-classes
56+ std::vector<T> ports_ {}; // NOLINT cppcoreguidelines-non-private-member-variables-in-classes
4757
4858public:
4959 using value_type = typename A::value_type;
@@ -56,29 +66,30 @@ public:
5666 ~Multiport () noexcept = default ;
5767
5868 auto operator ==(const Multiport& other) const noexcept -> bool {
59- return std::equal (std::begin (data_ ), std::end (data_ ), std::begin (other.data_ ), std::end (other.data_ ));
69+ return std::equal (std::begin (ports_ ), std::end (ports_ ), std::begin (other.ports_ ), std::end (other.ports_ ));
6070 }
6171 auto operator !=(const Multiport& other) const noexcept -> bool { return !(*this == other); };
62- inline auto operator [](std::size_t index) noexcept -> T& { return data_ [index]; }
63- inline auto operator [](std::size_t index) const noexcept -> const T& { return data_ [index]; }
72+ inline auto operator [](std::size_t index) noexcept -> T& { return ports_ [index]; }
73+ inline auto operator [](std::size_t index) const noexcept -> const T& { return ports_ [index]; }
6474
65- inline auto begin () noexcept -> iterator { return data_ .begin (); };
66- inline auto begin () const noexcept -> const_iterator { return data_ .begin (); };
67- inline auto cbegin () const noexcept -> const_iterator { return data_ .cbegin (); };
68- inline auto end () noexcept -> iterator { return data_ .end (); };
69- inline auto end () const noexcept -> const_iterator { return data_ .end (); };
70- inline auto cend () const noexcept -> const_iterator { return data_ .cend (); };
75+ inline auto begin () noexcept -> iterator { return ports_ .begin (); };
76+ inline auto begin () const noexcept -> const_iterator { return ports_ .begin (); };
77+ inline auto cbegin () const noexcept -> const_iterator { return ports_ .cbegin (); };
78+ inline auto end () noexcept -> iterator { return ports_ .end (); };
79+ inline auto end () const noexcept -> const_iterator { return ports_ .end (); };
80+ inline auto cend () const noexcept -> const_iterator { return ports_ .cend (); };
7181
72- inline auto size () const noexcept -> size_type { return data_ .size (); };
73- [[nodiscard]] inline auto empty () const noexcept -> bool { return data_ .empty (); };
82+ inline auto size () const noexcept -> size_type { return ports_ .size (); };
83+ [[nodiscard]] inline auto empty () const noexcept -> bool { return ports_ .empty (); };
7484
7585 [[nodiscard]] inline auto present_indices_unsorted () const noexcept -> std::vector<std::size_t> {
76- return std::vector<std::size_t >(std::begin (present_ports_) , std::begin (present_ports_) + size_. load ());
86+ return std::vector<std::size_t >(std::begin (present_ports ()) , std::begin (present_ports ()) + present_ports_size ());
7787 }
7888
7989 [[nodiscard]] inline auto present_indices_sorted () const noexcept -> std::vector<std::size_t> {
80- std::sort (std::begin (present_ports_), std::begin (present_ports_) + size_.load ());
81- return std::vector<std::size_t >(std::begin (present_ports_), std::begin (present_ports_) + size_.load ());
90+ std::vector<std::size_t > indices (std::begin (present_ports ()), std::begin (present_ports ()) + present_ports_size ());
91+ std::sort (std::begin (indices), std::end (indices));
92+ return indices;
8293 }
8394};
8495
@@ -89,18 +100,18 @@ public:
89100 ~ModifableMultiport () = default ;
90101
91102 inline void reserve (std::size_t size) noexcept {
92- this ->data_ .reserve (size);
93- this ->present_ports_ . reserve (size);
103+ this ->ports_ .reserve (size);
104+ this ->present_ports_reserve (size);
94105 }
95106
96107 inline void push_back (const T& elem) noexcept {
97- this ->data_ .push_back (elem);
98- this ->present_ports_ . emplace_back ( 0 );
108+ this ->ports_ .push_back (elem);
109+ this ->register_port ( this -> ports_ . back (), this -> ports_ . size () - 1 );
99110 }
100111
101112 template <class ... Args> inline void emplace_back (Args&&... args) noexcept {
102- this ->data_ .emplace_back (args...);
103- this ->present_ports_ . emplace_back ( 0 );
113+ this ->ports_ .emplace_back (args...);
114+ this ->register_port ( this -> ports_ . back (), this -> ports_ . size () - 1 );
104115 }
105116};
106117} // namespace reactor
0 commit comments