SST  15.1.0
StructuralSimulationToolkit
timeVortexBinnedMap.h
1 // Copyright 2009-2025 NTESS. Under the terms
2 // of Contract DE-NA0003525 with NTESS, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2025, NTESS
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 #ifndef SST_CORE_IMPL_TIMEVORTEX_TIMEVORTEXBINNEDMAP_H
13 #define SST_CORE_IMPL_TIMEVORTEX_TIMEVORTEXBINNEDMAP_H
14 
15 #include "sst/core/threadsafe.h"
16 
17 #include <atomic>
18 #include <cstdint>
19 #include <map>
20 #include <queue>
21 #include <sst/core/timeVortex.h>
22 #include <vector>
23 
24 namespace SST {
25 
26 class Output;
27 
28 namespace IMPL {
29 
30 
31 template <typename T>
32 class Pool
33 {
34 
35  std::vector<T*> pool;
36 
37 public:
38  ~Pool()
39  {
40  for ( auto x : pool ) {
41  delete x;
42  }
43  }
44 
45  T* remove()
46  {
47  if ( pool.empty() ) {
48  pool.push_back(new T());
49  }
50  auto ret = pool.back();
51  pool.pop_back();
52  return ret;
53  }
54 
55  void insert(T* item) { pool.push_back(item); }
56 };
57 
58 /**
59  * Primary Event Queue
60  */
61 template <bool TS>
63 {
64 
65 private:
66  // Class to hold a vector and a delivery time
67  class TimeUnit
68  {
69  private:
70  SimTime_t sort_time;
71  std::vector<Activity*> activities;
72  bool sorted;
73 
74  CACHE_ALIGNED(SST::Core::ThreadSafe::Spinlock, tu_lock);
75 
76  public:
77  // Create with initial event
78  TimeUnit() :
79  sorted(false)
80  {}
81 
82  ~TimeUnit()
83  {
84  for ( auto x : activities ) {
85  delete x;
86  }
87  }
88 
89  inline SimTime_t getSortTime() { return sort_time; }
90  inline void setSortTime(SimTime_t time) { sort_time = time; }
91 
92 
93  // Inserts can happen by multiple threads
94  void insert(Activity* act)
95  {
96  if ( TS ) tu_lock.lock();
97  activities.push_back(act);
98  sorted = false;
99  if ( TS ) tu_lock.unlock();
100  }
101 
102  // pop only happens by one thread
103  Activity* pop()
104  {
105  if ( 0 == activities.size() ) return nullptr;
106  if ( !sorted ) sort();
107  auto ret = activities.back();
108  activities.pop_back();
109  return ret;
110  }
111 
112  // front only happens by one thread
113  Activity* front()
114  {
115  if ( 0 == activities.size() ) return nullptr;
116  if ( !sorted ) sort();
117  return activities.back();
118  }
119 
120  void sort();
121 
122  inline bool operator<(const TimeUnit& rhs) { return this->sort_time < rhs.sort_time; }
123 
124  /** To use with STL priority queues, that order in reverse. */
125  class pq_less
126  {
127  public:
128  /** Compare pointers */
129  inline bool operator()(const TimeUnit* lhs, const TimeUnit* rhs) { return lhs->sort_time > rhs->sort_time; }
130 
131  /** Compare references */
132  inline bool operator()(const TimeUnit& lhs, const TimeUnit& rhs) { return lhs.sort_time > rhs.sort_time; }
133  };
134  };
135 
136 
137 public:
138  explicit TimeVortexBinnedMapBase(Params& params);
140 
141  bool empty() override;
142  int size() override;
143  void insert(Activity* activity) override;
144  Activity* pop() override;
145  Activity* front() override;
146 
147 
148  /** Print the state of the TimeVortex */
149  void print(Output& out) const override;
150 
151  uint64_t getCurrentDepth() const override { return current_depth; }
152  uint64_t getMaxDepth() const override { return max_depth; }
153 
154  // TODO: Implement getContents(). For now, just return an empty
155  // vector.
156  void getContents(std::vector<Activity*>& UNUSED(activities)) const override {}
157 
158 private:
159  // Should only ever be accessed by the "active" thread. Not safe
160  // for concurrent access.
161  TimeUnit* current_time_unit;
162 
163  using mapType_t = std::map<SimTime_t, TimeUnit*>;
164 
165  // Accessed by multiple threads, must be locked when accessing
166  mapType_t map;
167  std::conditional_t<TS, std::atomic<uint64_t>, uint64_t> insertOrder;
168  std::conditional_t<TS, std::atomic<uint64_t>, uint64_t> current_depth;
169 
170  // Should only ever be accessed by the "active" thread, or in a
171  // mutex. There are no internal mutexes.
172  Pool<TimeUnit> pool;
173 
174  CACHE_ALIGNED(SST::Core::ThreadSafe::Spinlock, slock);
175 };
176 
177 } // namespace IMPL
178 } // namespace SST
179 
180 #endif // SST_CORE_IMPL_TIMEVORTEX_TIMEVORTEXBINNEDMAP_H
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file...
Definition: output.h:57
bool operator()(const TimeUnit *lhs, const TimeUnit *rhs)
Compare pointers.
Definition: timeVortexBinnedMap.h:129
Definition: timeVortexBinnedMap.h:32
bool empty() override
Returns true if the queue is empty.
Definition: timeVortexBinnedMap.cc:63
Base class for all Activities in the SST Event Queue.
Definition: activity.h:47
void print(Output &out) const override
Print the state of the TimeVortex.
Definition: timeVortexBinnedMap.cc:166
Primary Event Queue.
Definition: timeVortex.h:31
Definition: action.cc:18
To use with STL priority queues, that order in reverse.
Definition: timeVortexBinnedMap.h:125
int size() override
Returns the number of activities in the queue.
Definition: timeVortexBinnedMap.cc:73
Primary Event Queue.
Definition: timeVortexBinnedMap.h:62
void insert(Activity *activity) override
Insert a new activity into the queue.
Definition: timeVortexBinnedMap.cc:80
Activity * pop() override
Remove and return the next activity.
Definition: timeVortexBinnedMap.cc:127
Activity * front() override
Returns the next activity.
Definition: timeVortexBinnedMap.cc:151
Definition: threadsafe.h:135
bool operator()(const TimeUnit &lhs, const TimeUnit &rhs)
Compare references.
Definition: timeVortexBinnedMap.h:132
Parameter store.
Definition: params.h:63