The Sparta Modeling Framework
Loading...
Searching...
No Matches
IterableCollector.hpp
1// <IterableCollector.hpp> -*- C++ -*-
2
3/*
4 */
5
6#pragma once
7
8#include <memory>
9#include <sstream>
10#include <string>
11#include <vector>
12#include <iterator>
13#include <type_traits>
14#include "sparta/utils/Utils.hpp"
15#include "sparta/log/MessageSource.hpp"
20
21namespace sparta {
22namespace collection {
23
68template <typename IterableType, SchedulingPhase collection_phase = SchedulingPhase::Collection, bool sparse_array_type = false>
70{
71public:
72 typedef typename IterableType::size_type size_type;
73
85 const std::string & name,
86 const std::string & group,
87 const uint32_t index,
88 const std::string & desc,
89 const IterableType * iterable,
90 const size_type expected_capacity) :
91 CollectableTreeNode(parent, name, group, index, desc),
92 iterable_object_(iterable),
93 expected_capacity_(expected_capacity),
94 event_set_(this),
95 ev_close_record_(&event_set_, name + "_pipeline_collectable_close_event",
97 {
98 for (size_type i = 0; i < expected_capacity_; ++i)
99 {
100 std::stringstream name_str;
101 name_str << name << i;
102 positions_.emplace_back(new CollectableT(this, name_str.str(), group, i));
103 }
104 }
105
106
118 const std::string & name,
119 const std::string & group,
120 const uint32_t index,
121 const std::string & desc,
122 const IterableType & iterable,
123 const size_type expected_capacity) :
124 IterableCollector(parent, name, group, index, desc, &iterable, expected_capacity)
125 {}
126
136 const std::string & name,
137 const std::string & desc,
138 const IterableType * iterable,
139 const size_type expected_capacity) :
140 IterableCollector(parent, name, name, 0, desc, iterable, expected_capacity)
141 {}
142
152 const std::string & name,
153 const std::string & desc,
154 const IterableType & iterable,
155 const size_type expected_capacity) :
156 IterableCollector(parent, name, name, 0, desc, &iterable, expected_capacity)
157 {}
158
167 const std::string & name,
168 const IterableType * iterable,
169 const size_type expected_capacity) :
170 IterableCollector (parent, name, name + " Iterable Collector",
171 iterable, expected_capacity)
172 {
173 // Delegated constructor
174 }
175
184 const std::string & name,
185 const IterableType & iterable,
186 const size_type expected_capacity) :
187 IterableCollector (parent, name, name + " Iterable Collector",
188 &iterable, expected_capacity)
189 {
190 // Delegated constructor
191 }
192
200 const std::string & name,
201 const size_type expected_capacity) :
202 IterableCollector (parent, name, name + " Iterable Collector",
203 nullptr, expected_capacity)
204 {
205 // Can't auto collect without setting iterable_object_
207 }
208
211 void createSimDbEntryPoint(simdb::argos::ArgosCollector* argos_collector) override final
212 {
213 if constexpr (use_dynamic_fields<BinValueT>) {
214 std::ostringstream oss;
215 oss << "Collecting non-trivial classes using operator<< is no longer supported. Use PairDefinition.\n";
216 oss << " - path: " << getLocation() << "\n";
217 oss << " - type: " << simdb::demangle_type<BinValueT>() << " (container)";
218 argos_collector->postNotif(oss.str(), simdb::argos::NotifType::WARNING);
219 } else {
220 auto loc = getLocation();
221 auto clk_name = notNull(getClock())->getName();
222 auto type = encodeCollectedType();
223 entry_point_ = argos_collector->createContainerCollector(loc, clk_name, type);
224
225 auto tiny_strings = argos_collector->getTinyStrings();
226 auto enum_inspector = argos_collector->getEnumInspector();
227 bit_bucket_ = std::make_shared<IterableCollectorBitBucket<sparse_array_type>>(tiny_strings, enum_inspector, expected_capacity_);
228 for (auto & bin : positions_) {
229 bin->setBitBucket(bit_bucket_);
230 }
231 }
232 }
233
236 void serializeStructSchema(simdb::DatabaseManager* db_mgr, std::set<std::string>& serialized_types) override final
237 {
238 positions_.at(0)->serializeStructSchema(db_mgr, serialized_types);
239 }
240
241 std::string encodeCollectedType(bool human_readable = false) const override final
242 {
243 auto type = positions_.at(0)->encodeCollectedType();
244 auto human_readable_type = positions_.at(0)->encodeCollectedType(true);
245 auto human_readable_desc = human_readable_type.substr(type.size() + 1);
246
247 if constexpr (sparse_array_type) {
248 type += "_sparse";
249 } else {
250 type += "_contig";
251 }
252 type += "_capacity" + std::to_string(expected_capacity_);
253 if (human_readable) {
254 type += " " + human_readable_desc;
255 }
256 return type;
257 }
258
263 void collect(const IterableType * iterable_object)
264 {
265 // If pointer has become nullified, close the records
266 if(nullptr == iterable_object) {
267 closeRecord();
268 }
270 {
271 if(SPARTA_EXPECT_FALSE(iterable_object->size() > expected_capacity_))
272 {
273 if(SPARTA_EXPECT_FALSE(warn_on_size_))
274 {
276 << "WARNING! The collected object '"
277 << getLocation() << "' has grown beyond the "
278 << "expected capacity (given at construction) for collection. "
279 << "Expected " << expected_capacity_ << " but grew to "
280 << iterable_object->size()
281 << " This is your first and last warning.";
282 warn_on_size_ = false;
283 }
284 }
285 collectImpl_(iterable_object, std::integral_constant<bool, sparse_array_type>());
286 }
287 }
288
290 void collect() override {
291 collect(iterable_object_);
292 }
293
297 void closeRecord(const bool & = false) override {
299 entry_point_->closeRecord();
300 }
301 }
302
304 void scheduleCloseRecord(sparta::Clock::Cycle cycle) {
306 ev_close_record_.preparePayload(false)->schedule(cycle);
307 }
308 }
309
313 auto_collect_ = false;
314 }
315
318 void collectWithDuration(sparta::Clock::Cycle duration) {
320 collect();
321 if(duration != 0) {
322 ev_close_record_.preparePayload(false)->schedule(duration);
323 }
324 }
325 }
326
328 void reattach(const IterableType * obj) {
329 iterable_object_ = obj;
330 }
331
332private:
333 typedef typename std::iterator_traits<typename IterableType::iterator>::value_type BinT;
334 typedef MetaStruct::remove_any_pointer_t<BinT> BinValueT;
335 typedef Collectable<BinT> CollectableT;
337
338 // Standard walk of iterable types
339 void collectImpl_(const IterableType * iterable_object, std::false_type)
340 {
341 // Unit tests may not have any entry point / bit bucket / simulation set up.
342 if (!entry_point_) {
343 return;
344 }
345
346 sparta_assert(bit_bucket_);
347 sparta_assert(nullptr != iterable_object,
348 "Can't collect iterable_object because it's a nullptr! How did we get here?");
349 auto itr = iterable_object->begin();
350 auto eitr = iterable_object->end();
351 auto size = std::distance(itr, eitr);
352 bit_bucket_->clear();
353 for (uint32_t i = 0; i < size; ++i)
354 {
355 bit_bucket_->setActiveBinIdx(i);
356 positions_[i]->collect(*itr);
357 ++itr;
358 }
359
360 bit_bucket_->writeTo(entry_point_);
361 }
362
363 // Full iteration walk, checking validity of the iterator. This
364 // is used for Pipe and Array where the iterator points to valid
365 // and not valid entries in the component
366 void collectImpl_(const IterableType * iterable_object, std::true_type)
367 {
368 // Unit tests may not have any entry point / bit bucket / simulation set up.
369 if (!entry_point_) {
370 return;
371 }
372
373 sparta_assert(bit_bucket_);
374 sparta_assert(nullptr != iterable_object,
375 "Can't collect iterable_object because it's a nullptr! How did we get here?");
376 auto itr = iterable_object->begin();
377 bit_bucket_->clear();
378 for (uint32_t i = 0; i < expected_capacity_; ++i)
379 {
380 sparta_assert(itr != iterable_object->end());
381 if (itr.isValid()) {
382 bit_bucket_->setActiveBinIdx(i);
383 positions_[i]->collect(*itr);
384 }
385 ++itr;
386 }
387
388 bit_bucket_->writeTo(entry_point_);
389 }
390
393 void setCollecting_(bool collect, Collector * collector) override
394 {
395 if(collect && auto_collect_) {
396 PipelineCollector * pipeline_col = dynamic_cast<PipelineCollector *>(collector);
397 sparta_assert(pipeline_col != nullptr);
398
399 // Add this Collectable to the PipelineCollector's
400 // list of objects requiring collection
401 pipeline_col->addToAutoCollection(this, collection_phase);
402 }
403 else {
404 closeRecord();
405 }
406 }
407
408 const IterableType * iterable_object_;
409 std::vector<std::unique_ptr<CollectableT>> positions_;
410 const size_type expected_capacity_ = 0;
411 bool auto_collect_ = true;
412 bool warn_on_size_ = true;
413 std::shared_ptr<BitBucketT> bit_bucket_;
414
415 // For those folks that want a value to automatically
416 // disappear in the future
417 sparta::EventSet event_set_;
419
420};
421} // namespace collection
422} // namespace sparta
define a CollectableTreeNode type TreeNode.
Implementation of the Collectable class that allows a user to collect an object into an pipeViewer pi...
Class to facilitate pipeline collection operations.
File that defines the phases used in simulation.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
#define SPARTA_EXPECT_FALSE(x)
A macro for hinting to the compiler a particular condition should be considered most likely false.
#define CREATE_SPARTA_HANDLER_WITH_DATA(clname, meth, dataT)
Set of Events that a unit (or sparta::TreeNode, sparta::Resource) contains and are visible through a ...
Definition EventSet.hpp:26
Class to schedule a Scheduleable in the future with a payload, typed on both the data type and the sc...
ScheduleableHandle preparePayload(const DataT &payload)
Prepare a Scheduleable Payload for scheduling either now or later.
void schedule()
Schedule this event with its pre-set delay using the pre-set Clock.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:204
std::string getLocation() const override final
const Clock * getClock() override
Walks up parents (starting with self) until a parent with an associated local clock is found,...
An abstract type of TreeNode that has virtual calls to start collection on this node,...
simdb::argos::EntryPoint * entry_point_
Entry point into the SimDB collection system.
bool isCollected() const
Determine whether or not this node has collection turned on or off.
BitBucket implementation for sparse IterableCollectors.
A collector of any iterable type (std::vector, std::list, sparta::Buffer, etc)
void createSimDbEntryPoint(simdb::argos::ArgosCollector *argos_collector) override final
void reattach(const IterableType *obj)
Reattach to a new iterable object (used for moves)
void collect(const IterableType *iterable_object)
std::string encodeCollectedType(bool human_readable=false) const override final
Encode the collected data type in a way Argos python deserializers will understand:
void setManualCollection()
Do not perform any automatic collection The SchedulingPhase is ignored.
void scheduleCloseRecord(sparta::Clock::Cycle cycle)
Schedule event to close all records for this iterable type.
IterableCollector(TreeNode *parent, const std::string &name, const std::string &desc, const IterableType &iterable, const size_type expected_capacity)
constructor
IterableCollector(TreeNode *parent, const std::string &name, const IterableType &iterable, const size_type expected_capacity)
constructor with no description
void collect() override
Collect the contents of the associated iterable object.
void serializeStructSchema(simdb::DatabaseManager *db_mgr, std::set< std::string > &serialized_types) override final
IterableCollector(TreeNode *parent, const std::string &name, const IterableType *iterable, const size_type expected_capacity)
constructor with no description
IterableCollector(TreeNode *parent, const std::string &name, const std::string &group, const uint32_t index, const std::string &desc, const IterableType *iterable, const size_type expected_capacity)
constructor
IterableCollector(TreeNode *parent, const std::string &name, const std::string &group, const uint32_t index, const std::string &desc, const IterableType &iterable, const size_type expected_capacity)
constructor
void collectWithDuration(sparta::Clock::Cycle duration)
Perform a collection, then close the records in the future.
IterableCollector(TreeNode *parent, const std::string &name, const size_type expected_capacity)
constructor with no iterable object associated
void closeRecord(const bool &=false) override
IterableCollector(TreeNode *parent, const std::string &name, const std::string &desc, const IterableType *iterable, const size_type expected_capacity)
constructor
static MessageSource & getGlobalWarn()
Gets the global warning logger. These messages can be picked up by placing a Tap on the sparta::TreeN...
Macros for handling exponential backoff.
T * notNull(T *p)
Ensures that a pointer is not null.
Definition Utils.hpp:235