Sen API
Sen Libraries
Loading...
Searching...
No Matches
object_list.h
Go to the documentation of this file.
1// === object_list.h ===================================================================================================
2// Sen Infrastructure
3// Released under the Apache License v2.0 (SPDX-License-Identifier Apache-2.0).
4// See the LICENSE.txt file for more information.
5// © Airbus SAS, Airbus Helicopters, and Airbus Defence and Space SAU/GmbH/SAS.
6// =====================================================================================================================
7
8#ifndef SEN_CORE_OBJ_OBJECT_LIST_H
9#define SEN_CORE_OBJ_OBJECT_LIST_H
10
11// sen
16
17// std
18#include <list>
19
20namespace sen
21{
22
25
28template <typename T>
30{
31public:
32 SEN_MOVE_ONLY(ObjectList)
33
34 static constexpr std::size_t defaultListSizeHint = 10U;
35
36public: // types
43
44 using TypedObjectList = std::list<T*>;
45 using UntypedObjectList = std::list<std::shared_ptr<Object>>;
46
47 struct Iterators
48 {
49 typename TypedObjectList::iterator typedBegin;
50 typename TypedObjectList::iterator typedEnd;
51 typename UntypedObjectList::iterator untypedBegin;
52 typename UntypedObjectList::iterator untypedEnd;
53
55 [[nodiscard]] typename TypedObjectList::iterator begin() const { return typedBegin; }
56 [[nodiscard]] typename TypedObjectList::iterator end() const { return typedEnd; }
57
59 [[nodiscard]] auto untyped() const { return sen::util::makeRange(untypedBegin, untypedEnd); }
60
62 [[nodiscard]] auto typed() const { return sen::util::makeRange(typedBegin, typedEnd); }
63 };
64
65 using Callback = std::function<void(const Iterators& iterators)>;
66
67public: // special members
71 explicit ObjectList(std::size_t sizeHint = defaultListSizeHint) { iteratorMap_.reserve(sizeHint); }
72
74 ObjectList(ObjectProvider& provider, std::size_t sizeHint): ObjectList(sizeHint) { provider.addListener(this, true); }
75
76 ~ObjectList() override = default;
77
78public:
82 [[nodiscard]] Callback onAdded(Callback&& function) noexcept;
83
87 [[nodiscard]] Callback onRemoved(Callback&& function) noexcept
88 {
89 return std::exchange(onRemoved_, std::move(function));
90 }
91
92public: // multiple object lookup
94 [[nodiscard]] const std::list<T*>& getObjects() const noexcept { return typedObjects_; }
95
97 [[nodiscard]] const std::list<std::shared_ptr<Object>>& getUntypedObjects() const noexcept { return untypedObjects_; }
98
99protected: // implements ObjectProviderListener
100 void onObjectsAdded(const ObjectAdditionList& additions) override;
101 void onObjectsRemoved(const ObjectRemovalList& removals) override;
102
103private:
104 [[nodiscard]] T* getCastedObject(Object* object);
105
106private:
107 struct IteratorPair
108 {
109 typename TypedObjectList::const_iterator typed;
110 typename UntypedObjectList::const_iterator untyped;
111 };
112
113private:
114 TypedObjectList typedObjects_;
115 UntypedObjectList untypedObjects_;
116 std::unordered_map<ObjectId, IteratorPair> iteratorMap_;
117 Callback onAdded_ = nullptr;
118 Callback onRemoved_ = nullptr;
119};
120
122
123//----------------------------------------------------------------------------------------------------------------------
124// Inline implementation
125//----------------------------------------------------------------------------------------------------------------------
126
127template <typename T>
128inline typename ObjectList<T>::Callback ObjectList<T>::onAdded(Callback&& function) noexcept
129{
130 auto previous = std::exchange(onAdded_, std::move(function));
131
132 if (onAdded_ && !untypedObjects_.empty())
133 {
134 onAdded_({typedObjects_.begin(), typedObjects_.end(), untypedObjects_.begin(), untypedObjects_.end()});
135 }
136
137 return previous;
138}
139
140template <typename T>
141inline T* ObjectList<T>::getCastedObject(Object* object)
142{
143 if constexpr (!std::is_same_v<T, Object>)
144 {
145 auto* castedObject = dynamic_cast<T*>(object);
146 if (castedObject == nullptr)
147 {
148 std::string err;
149 err.append("error casting object named '");
150 err.append(object->getName());
151 err.append("' of class '");
152 err.append(object->getClass()->getQualifiedName());
153 err.append("' to a native type '");
154 err.append(typeid(T).name());
155 err.append("' within an ObjectList");
157 }
158
159 return castedObject;
160 }
161 else
162 {
163 return object;
164 }
165}
166
167template <typename T>
169{
170 Iterators iterators;
171 bool added = false;
172
173 for (const auto& addition: additions)
174 {
175 // only react to discovered instances
176 auto* instance = getObjectInstance(addition);
177 if (instance == nullptr)
178 {
179 continue;
180 }
181
182 auto castedObject = getCastedObject(instance);
183 auto lastTyped = typedObjects_.insert(typedObjects_.end(), castedObject);
184 auto lastUntyped = untypedObjects_.insert(untypedObjects_.end(), instance->shared_from_this());
185
186 if (!added)
187 {
188 iterators.untypedBegin = lastUntyped;
189 iterators.typedBegin = lastTyped;
190 added = true;
191 }
192
193 // store the object
194 iteratorMap_.insert({instance->getId(), {lastTyped, lastUntyped}});
195 }
196
197 if (!added)
198 {
199 return;
200 }
201
202 if (onAdded_)
203 {
204 iterators.typedEnd = typedObjects_.end();
205 iterators.untypedEnd = untypedObjects_.end();
206 onAdded_(iterators);
207 }
208}
209
210template <typename T>
212{
213 TypedObjectList typedRemovals;
214 UntypedObjectList untypedRemovals;
215
216 for (const auto& removal: removals)
217 {
218 auto itr = iteratorMap_.find(removal.objectid);
219 if (itr != iteratorMap_.end())
220 {
221 auto castedObject = *(itr->second.typed);
222 auto nonCastedObject = *(itr->second.untyped);
223
224 untypedObjects_.erase(itr->second.untyped);
225 typedObjects_.erase(itr->second.typed);
226 iteratorMap_.erase(itr);
227
228 if (onRemoved_)
229 {
230 typedRemovals.push_back(castedObject);
231 untypedRemovals.push_back(nonCastedObject);
232 }
233 }
234 }
235
236 if (onRemoved_ && !typedRemovals.empty())
237 {
238 Iterators iterators;
239 iterators.typedBegin = typedRemovals.begin();
240 iterators.typedEnd = typedRemovals.end();
241 iterators.untypedBegin = untypedRemovals.begin();
242 iterators.untypedEnd = untypedRemovals.end();
243
244 onRemoved_(iterators);
245 }
246}
247
248} // namespace sen
249
250#endif // SEN_CORE_OBJ_OBJECT_LIST_H
The following macros implement a replacement of assert that is connected to the overall fault handlin...
Base class for event or method callbacks. It stores the queue where to push the response....
Definition callback.h:146
A sen object.
Definition object.h:76
virtual const std::string & getName() const noexcept=0
The name given to the object upon construction.
virtual ConstTypeHandle< ClassType > getClass() const noexcept=0
Reflection information.
std::list< T * > TypedObjectList
Definition object_list.h:44
SearchMode
How to search for objects.
Definition object_list.h:39
@ ignoreSubClasses
Definition object_list.h:41
@ includeSubClasses
Definition object_list.h:40
Callback onAdded(Callback &&function) noexcept
Installs a function to be called when objects are added / discovered. This function will be called du...
Definition object_list.h:128
const std::list< T * > & getObjects() const noexcept
Gets the list of currently-registered objects.
Definition object_list.h:94
static constexpr std::size_t defaultListSizeHint
Definition object_list.h:34
ObjectList(ObjectProvider &provider, std::size_t sizeHint)
Automatically adds itself as a listener to the provider.
Definition object_list.h:74
std::list< std::shared_ptr< Object > > UntypedObjectList
Definition object_list.h:45
std::function< void(const Iterators &iterators)> Callback
Definition object_list.h:65
void onObjectsRemoved(const ObjectRemovalList &removals) override
Called when objects will be removed from a source.
Definition object_list.h:211
const std::list< std::shared_ptr< Object > > & getUntypedObjects() const noexcept
Gets the list of currently-registered objects.
Definition object_list.h:97
void onObjectsAdded(const ObjectAdditionList &additions) override
Called when objects are been added to a source.
Definition object_list.h:168
~ObjectList() override=default
ObjectList(std::size_t sizeHint=defaultListSizeHint)
The sizeHint reserves space the internal containers to prevent memory reallocation in the initial ite...
Definition object_list.h:71
Callback onRemoved(Callback &&function) noexcept
Installs a function to be called when objects are added / discovered. This function will be called du...
Definition object_list.h:87
virtual void addListener(ObjectProviderListener *listener, bool notifyAboutExistingObjects)
Registers an event listener.
friend class ObjectProvider
Definition object_provider.h:128
void throwRuntimeError(const std::string &err)
Throws std::exception that attempts to collect the stack trace. We also wrap it to avoid including st...
Object * getObjectInstance(const ObjectAddition &discovery)
Definition object_provider.h:97
std::vector< ObjectAddition > ObjectAdditionList
Sequence of object additions.
Definition object_provider.h:71
std::vector< ObjectRemoval > ObjectRemovalList
Sequence of object removals.
Definition object_provider.h:74
IteratorRange< IteratorType > makeRange(IteratorType begin, IteratorType end)
Create a simple range for the two iterators.
Definition iterator_adapters.h:52
Definition assert.h:17
STL namespace.
Definition object_list.h:48
TypedObjectList::iterator typedBegin
Definition object_list.h:49
UntypedObjectList::iterator untypedEnd
Definition object_list.h:52
auto untyped() const
Range-for support iterates over untyped objects.
Definition object_list.h:59
TypedObjectList::iterator begin() const
Range-for support iterates over typed objects.
Definition object_list.h:55
UntypedObjectList::iterator untypedBegin
Definition object_list.h:51
TypedObjectList::iterator end() const
Definition object_list.h:56
TypedObjectList::iterator typedEnd
Definition object_list.h:50
auto typed() const
Range-for support iterates over untype objects (here for simmetry with untyped()).
Definition object_list.h:62