SST  14.1.0
StructuralSimulationToolkit
ssthandler.h
1 // Copyright 2009-2024 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-2024, 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_SSTHANDLER_H
13 #define SST_CORE_SSTHANDLER_H
14 
15 #include "sst/core/profile/profiletool.h"
16 #include "sst/core/serialization/serializable.h"
17 #include "sst/core/sst_types.h"
18 
19 namespace SST {
20 
21 class Params;
22 
23 /**
24  Just a tag class for the various metadata that will need to be
25  stored in the simulation object to allow ProfileTools to get the
26  data they need.
27  */
29 {
30 public:
31  virtual ~HandlerMetaData() {}
32 };
33 
34 
35 /**
36  Base class for Profile tools for Handlers
37 */
39 {
40 public:
41  // Register with ELI as base API
42  SST_ELI_REGISTER_PROFILETOOL_API(SST::HandlerProfileToolAPI, Params&)
43 
44 protected:
45  HandlerProfileToolAPI(const std::string& name) : Profile::ProfileTool(name) {}
47 
48 public:
49  virtual uintptr_t registerHandler(const HandlerMetaData& mdata) = 0;
50 
51  virtual void handlerStart(uintptr_t UNUSED(key)) {}
52  virtual void handlerEnd(uintptr_t UNUSED(key)) {}
53 };
54 
55 // This file contains base classes for use as various handlers (object
56 // encapsulating callback functions) in SST. These handlers are
57 // checkpointable and encapsulate a pointer to an object and a pointer
58 // to a member function of the object's class (captured via template
59 // parameter). The classes also allow you to optionally add one
60 // additional piece of static data to be passed into the callback
61 // function along with any data provided by the caller. There are two
62 // versions of this class, one that has no data passed from the caller
63 // (ending with SSTHandlerNoArgs), and one that has a single item
64 // passed from the caller (SSTHandler).
65 
66 // NOTE: Legacy SSTHandler objects are not checkpointable and have
67 // been deprecated. Support for legacy handlers will be removed in
68 // SST 15.
69 
70 // These classes provide the full functionality of the handlers and
71 // can be added to a class with the "using" keyword, as follows (a
72 // class can use any type name they'd like in place of HandlerBase and
73 // Handler, though those names are preferred for consistency):
74 
75 // Note: Until support for legacy handlers are removed, the new-style
76 // handlers should use Handler2Base and Handler2 as the preferred
77 // names. After legacy support is remoed with SST 15, both Handler
78 // and Handler2 should both point to the new style handlers. Handler2
79 // will be deprecated from SST 15 until SST 16, when Handler will be
80 // the approved name.
81 
82 // LEGACY STYLE
83 
84 // using HandlerBase = SSTHandlerBase<return_type_of_callback, arg_type_of_callback>;
85 
86 // template <typename classT, typename dataT = void>
87 // using Handler = SSTHandler<return_type_of_callback, arg_type_of_callback, classT, dataT>;
88 
89 // Or:
90 
91 // using HandlerBase = SSTHandlerBaseNoArgs<return_type_of_callback>;
92 
93 // template <return_type_of_callback, typename classT, typename dataT = void>
94 // using Handler = SSTHandlerNoArgs<return_type_of_callback, classT, dataT>;
95 
96 // The handlers are then instanced as follows:
97 
98 // new Class::Handler<Class>(this, &Class::callback_function)
99 
100 // Or:
101 
102 // new Class::Handler<Class,int>(this, &Class::callback_function, 1)
103 
104 
105 // NEW STYLE
106 // Note: New style SSTHandler2 uses the same class for functions with and without parameters.
107 
108 // Note: HandlerBase is the same both both legacy and new style
109 // using HandlerBase = SSTHandlerBase<return_type_of_callback, arg_type_of_callback>;
110 
111 // template <typename classT, auto funcT, typename dataT = void>
112 // using Handler2 = SSTHandler2<return_type_of_callback, arg_type_of_callback, classT, dataT, funcT>;
113 
114 
115 // The handlers are then instanced as follows:
116 
117 // new Class::Handler2<Class, &Class::callback_function>(this)
118 
119 // Or:
120 
121 // new Class::Handler2<Class, &Class::callback_function, int>(this, 1)
122 
123 
124 /// Functor classes for Event handling
125 
127 {
128 protected:
129  // This class will hold the id for the handler and the profiling
130  // tools attached to it, if profiling is enabled for this handler.
132  {
133  static std::atomic<HandlerId_t> id_counter;
134  HandlerId_t my_id;
135 
136  public:
138 
139  void handlerStart()
140  {
141  for ( auto& x : tools )
142  x.first->handlerStart(x.second);
143  }
144  void handlerEnd()
145  {
146  for ( auto& x : tools )
147  x.first->handlerEnd(x.second);
148  }
149 
150  /**
151  Adds a profile tool the the list and registers this handler
152  with the profile tool
153  */
155  {
156  auto key = tool->registerHandler(mdata);
157  tools.push_back(std::make_pair(tool, key));
158  }
159 
160  HandlerId_t getId() { return my_id; }
161 
162 
163  private:
164  std::vector<std::pair<HandlerProfileToolAPI*, uintptr_t>> tools;
165  };
166 
167  // List of profiling tools attached to this handler
168  HandlerProfileToolList* profile_tools;
169 
170 
171 public:
172  SSTHandlerBaseProfile() : profile_tools(nullptr) {}
173 
174  virtual ~SSTHandlerBaseProfile()
175  {
176  if ( profile_tools ) delete profile_tools;
177  }
178 
179  void addProfileTool(HandlerProfileToolAPI* tool, const HandlerMetaData& mdata)
180  {
181  if ( !profile_tools ) profile_tools = new HandlerProfileToolList();
182  profile_tools->addProfileTool(tool, mdata);
183  }
184 
185  void transferProfilingInfo(SSTHandlerBaseProfile* handler)
186  {
187  if ( handler->profile_tools ) {
188  profile_tools = handler->profile_tools;
189  handler->profile_tools = nullptr;
190  }
191  }
192 
193  /**
194  Get the ID for this Handler. Handler IDs are only used for
195  profiling, so if this function is called, it will also set
196  things up to accept ProfileTools.
197  */
198  HandlerId_t getId()
199  {
200  if ( !profile_tools ) profile_tools = new HandlerProfileToolList();
201  return profile_tools->getId();
202  }
203 
204  ImplementVirtualSerializable(SSTHandlerBaseProfile)
205 };
206 
207 
208 /// Handlers with 1 handler defined argument to callback from caller
209 template <typename returnT, typename argT>
211 {
212  // Implementation of operator() to be done in child classes
213  virtual returnT operator_impl(argT) = 0;
214 
215 public:
216  ~SSTHandlerBase() {}
217 
218  inline returnT operator()(argT arg)
219  {
220  if ( profile_tools ) {
221  if constexpr ( std::is_void_v<returnT> ) {
222  profile_tools->handlerStart();
223  operator_impl(arg);
224  profile_tools->handlerEnd();
225  return;
226  }
227  else {
228  profile_tools->handlerStart();
229  auto ret = operator_impl(arg);
230  profile_tools->handlerEnd();
231  return ret;
232  }
233  }
234  return operator_impl(arg);
235  }
236  ImplementVirtualSerializable(SSTHandlerBase)
237 };
238 
239 
240 /// Handlers with no arguments to callback from caller
241 template <typename returnT>
242 class SSTHandlerBase<returnT, void> : public SSTHandlerBaseProfile
243 {
244 
245 protected:
246  virtual returnT operator_impl() = 0;
247 
248 public:
249  SSTHandlerBase() {}
250 
251  /** Handler function */
252  virtual ~SSTHandlerBase() {}
253 
254  inline returnT operator()()
255  {
256  if ( profile_tools ) {
257  if constexpr ( std::is_void_v<returnT> ) {
258  profile_tools->handlerStart();
259  operator_impl();
260  profile_tools->handlerEnd();
261  return;
262  }
263  else {
264  profile_tools->handlerStart();
265  auto ret = operator_impl();
266  profile_tools->handlerEnd();
267  return ret;
268  }
269  }
270  return operator_impl();
271  }
272  ImplementVirtualSerializable(SSTHandlerBase)
273 };
274 
275 
276 /**************************************
277  * Legacy Handlers
278  **************************************/
279 
280 /**
281  * Handler class with user-data argument
282  */
283 template <typename returnT, typename argT, typename classT, typename dataT = void>
284 class SSTHandler : public SSTHandlerBase<returnT, argT>
285 {
286 private:
287  typedef returnT (classT::*PtrMember)(argT, dataT);
288  classT* object;
289  const PtrMember member;
290  dataT data;
291 
292 public:
293  /** Constructor
294  * @param object - Pointer to Object upon which to call the handler
295  * @param member - Member function to call as the handler
296  * @param data - Additional argument to pass to handler
297  */
298  SSTHandler(classT* const object, PtrMember member, dataT data) :
299  SSTHandlerBase<returnT, argT>(),
300  object(object),
301  member(member),
302  data(data)
303  {}
304 
305  returnT operator_impl(argT arg) override { return (object->*member)(arg, data); }
306 
307  NotSerializable(SSTHandler)
308 };
309 
310 
311 /**
312  * Event Handler class with no user-data.
313  */
314 template <typename returnT, typename argT, typename classT>
315 class SSTHandler<returnT, argT, classT, void> : public SSTHandlerBase<returnT, argT>
316 {
317 private:
318  typedef returnT (classT::*PtrMember)(argT);
319  const PtrMember member;
320  classT* object;
321 
322 public:
323  /** Constructor
324  * @param object - Pointer to Object upon which to call the handler
325  * @param member - Member function to call as the handler
326  */
327  SSTHandler(classT* const object, PtrMember member) : SSTHandlerBase<returnT, argT>(), member(member), object(object)
328  {}
329 
330  returnT operator_impl(argT arg) override { return (object->*member)(arg); }
331 
332  NotSerializable(SSTHandler)
333 };
334 
335 /// Handlers with no arguments to callback from caller
336 template <typename returnT>
338 {
339 
340 protected:
341  virtual returnT operator_impl() = 0;
342 
343 public:
345 
346  /** Handler function */
348 
349  inline returnT operator()()
350  {
351  if ( profile_tools ) {
352  if constexpr ( std::is_void_v<returnT> ) {
353  profile_tools->handlerStart();
354  operator_impl();
355  profile_tools->handlerEnd();
356  return;
357  }
358  else {
359  profile_tools->handlerStart();
360  auto ret = operator_impl();
361  profile_tools->handlerEnd();
362  return ret;
363  }
364  }
365  return operator_impl();
366  }
367  ImplementVirtualSerializable(SSTHandlerBaseNoArgs)
368 };
369 
370 
371 template <>
373 {
374 
375 protected:
376  virtual void operator_impl() = 0;
377 
378 public:
380 
381  /** Handler function */
383 
384  inline void operator()()
385  {
386  if ( profile_tools ) {
387  profile_tools->handlerStart();
388  operator_impl();
389  profile_tools->handlerEnd();
390  return;
391  }
392  return operator_impl();
393  }
394 
395  ImplementVirtualSerializable(SSTHandlerNoArgs)
396 };
397 
398 /**
399  * Event Handler class with user-data argument
400  */
401 template <typename returnT, typename classT, typename dataT = void>
402 class SSTHandlerNoArgs : public SSTHandlerBaseNoArgs<returnT>
403 {
404 private:
405  typedef returnT (classT::*PtrMember)(dataT);
406  classT* object;
407  const PtrMember member;
408  dataT data;
409 
410 public:
411  /** Constructor
412  * @param object - Pointer to Object upon which to call the handler
413  * @param member - Member function to call as the handler
414  * @param data - Additional argument to pass to handler
415  */
416  SSTHandlerNoArgs(classT* const object, PtrMember member, dataT data) :
417  SSTHandlerBaseNoArgs<returnT>(),
418  object(object),
419  member(member),
420  data(data)
421  {}
422 
423  void operator_impl() override { return (object->*member)(data); }
424 
425  NotSerializable(SSTHandlerNoArgs)
426 };
427 
428 
429 /**
430  * Event Handler class with no user-data.
431  */
432 template <typename returnT, typename classT>
433 class SSTHandlerNoArgs<returnT, classT, void> : public SSTHandlerBaseNoArgs<returnT>
434 {
435 private:
436  typedef returnT (classT::*PtrMember)();
437  const PtrMember member;
438  classT* object;
439 
440 public:
441  /** Constructor
442  * @param object - Pointer to Object upon which to call the handler
443  * @param member - Member function to call as the handler
444  */
445  SSTHandlerNoArgs(classT* const object, PtrMember member) :
446  SSTHandlerBaseNoArgs<returnT>(),
447  member(member),
448  object(object)
449  {}
450 
451  void operator_impl() override { return (object->*member)(); }
452 
453  NotSerializable(SSTHandlerNoArgs)
454 };
455 
456 
457 /**************************************
458  * New style Handlers
459  **************************************/
460 
461 /**
462  Base template for the class. If this one gets chosen, then there
463  is a mismatch somewhere, so it will just static_assert
464  */
465 template <typename returnT, typename argT, typename classT, typename dataT, auto funcT>
466 class SSTHandler2 : public SSTHandlerBase<returnT, argT>
467 {
468 
469  // This has to be dependent on a tenplate, otherwise it always
470  // assers. Need to make sure it covers both cases to assert
471  // if this template is expanded.
472  static_assert(std::is_fundamental<dataT>::value, "Mismatched handler templates.");
473  static_assert(!std::is_fundamental<dataT>::value, "Mismatched handler templates.");
474 };
475 
476 
477 /**
478  * Handler class with user-data argument
479  */
480 template <typename returnT, typename argT, typename classT, typename dataT, returnT (classT::*funcT)(argT, dataT)>
481 class SSTHandler2<returnT, argT, classT, dataT, funcT> : public SSTHandlerBase<returnT, argT>
482 // template <typename returnT, typename argT, typename classT, typename dataT, auto funcT>
483 // class SSTHandler2 : public SSTHandlerBase<returnT, argT>
484 {
485 private:
486  classT* object;
487  dataT data;
488 
489 public:
490  /** Constructor
491  * @param object - Pointer to Object upon which to call the handler
492  * @param data - Additional argument to pass to handler
493  */
494  SSTHandler2(classT* const object, dataT data) : SSTHandlerBase<returnT, argT>(), object(object), data(data) {}
495 
496  SSTHandler2() {}
497 
498  returnT operator_impl(argT arg) override { return (object->*funcT)(arg, data); }
499 
500  void serialize_order(SST::Core::Serialization::serializer& ser) override
501  {
502  // SSTHandlerBase<returnT, argT>::serialize_order(ser);
503  ser& object;
504  ser& data;
505  }
506 
507  ImplementSerializable(SSTHandler2)
508 };
509 
510 
511 /**
512  * Event Handler class with no user-data.
513  */
514 template <typename returnT, typename argT, typename classT, returnT (classT::*funcT)(argT)>
515 class SSTHandler2<returnT, argT, classT, void, funcT> : public SSTHandlerBase<returnT, argT>
516 {
517 private:
518  classT* object;
519 
520 public:
521  /** Constructor
522  * @param object - Pointer to Object upon which to call the handler
523  * @param member - Member function to call as the handler
524  */
525  SSTHandler2(classT* const object) : SSTHandlerBase<returnT, argT>(), object(object) {}
526  SSTHandler2() {}
527 
528  returnT operator_impl(argT arg) override { return (object->*funcT)(arg); }
529 
530  void serialize_order(SST::Core::Serialization::serializer& ser) override
531  {
532  // SSTHandlerBase<returnT, argT>::serialize_order(ser);
533  ser& object;
534  }
535 
536  ImplementSerializable(SSTHandler2)
537 };
538 
539 
540 /**
541  * Event Handler class with user-data argument
542  */
543 template <typename returnT, typename classT, typename dataT, returnT (classT::*funcT)(dataT)>
544 class SSTHandler2<returnT, void, classT, dataT, funcT> : public SSTHandlerBase<returnT, void>
545 {
546 private:
547  classT* object;
548  dataT data;
549 
550 public:
551  /** Constructor
552  * @param object - Pointer to Object upon which to call the handler
553  * @param data - Additional argument to pass to handler
554  */
555  SSTHandler2(classT* const object, dataT data) : SSTHandlerBase<returnT, void>(), object(object), data(data) {}
556  SSTHandler2() {}
557 
558  returnT operator_impl() override { return (object->*funcT)(data); }
559 
560  void serialize_order(SST::Core::Serialization::serializer& ser) override
561  {
562  // SSTHandlerBase<returnT, argT>::serialize_order(ser);
563  ser& object;
564  ser& data;
565  }
566 
567  ImplementSerializable(SSTHandler2)
568 };
569 
570 
571 /**
572  * Event Handler class with user-data argument
573  */
574 template <typename returnT, typename classT, returnT (classT::*funcT)()>
575 class SSTHandler2<returnT, void, classT, void, funcT> : public SSTHandlerBase<returnT, void>
576 {
577 private:
578  classT* object;
579 
580 public:
581  /** Constructor
582  * @param object - Pointer to Object upon which to call the handler
583  * @param data - Additional argument to pass to handler
584  */
585  SSTHandler2(classT* const object) : SSTHandlerBase<returnT, void>(), object(object) {}
586  SSTHandler2() {}
587 
588  returnT operator_impl() override { return (object->*funcT)(); }
589 
590  void serialize_order(SST::Core::Serialization::serializer& ser) override
591  {
592  // SSTHandlerBase<returnT, argT>::serialize_order(ser);
593  ser& object;
594  }
595 
596  ImplementSerializable(SSTHandler2)
597 };
598 
599 #if 0
600 
601 /**
602  * Event Handler class with no user-data.
603  */
604 template <typename returnT, typename classT>
605 class SSTHandlerNoArgs<returnT, classT, void> : public SSTHandlerBaseNoArgs<returnT>
606 {
607 private:
608  typedef returnT (classT::*PtrMember)();
609  const PtrMember member;
610  classT* object;
611 
612 public:
613  /** Constructor
614  * @param object - Pointer to Object upon which to call the handler
615  * @param member - Member function to call as the handler
616  */
617  SSTHandlerNoArgs(classT* const object, PtrMember member) :
618  SSTHandlerBaseNoArgs<returnT>(),
619  member(member),
620  object(object)
621  {}
622 
623  void operator_impl() override { return (object->*member)(); }
624 
625  NotSerializable(SSTHandlerNoArgs)
626 };
627 #endif
628 
629 } // namespace SST
630 
631 #endif // SST_CORE_SSTHANDLER_H
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:43
Handlers with 1 handler defined argument to callback from caller.
Definition: ssthandler.h:210
Base template for the class.
Definition: ssthandler.h:466
Handler class with user-data argument.
Definition: ssthandler.h:284
HandlerId_t getId()
Get the ID for this Handler.
Definition: ssthandler.h:198
Definition: action.cc:18
ProfileTool is a class loadable through the factory which allows dynamic addition of profiling capabi...
Definition: profiletool.h:29
void addProfileTool(HandlerProfileToolAPI *tool, const HandlerMetaData &mdata)
Adds a profile tool the the list and registers this handler with the profile tool.
Definition: ssthandler.h:154
Definition: serializable.h:24
Handlers with no arguments to callback from caller.
Definition: ssthandler.h:337
SSTHandler2(classT *const object)
Constructor.
Definition: ssthandler.h:585
virtual ~SSTHandlerBaseNoArgs()
Handler function.
Definition: ssthandler.h:382
Just a tag class for the various metadata that will need to be stored in the simulation object to all...
Definition: ssthandler.h:28
Base class for Profile tools for Handlers.
Definition: ssthandler.h:38
Event Handler class with user-data argument.
Definition: ssthandler.h:402
virtual ~SSTHandlerBase()
Handler function.
Definition: ssthandler.h:252
SSTHandler2(classT *const object, dataT data)
Constructor.
Definition: ssthandler.h:494
SSTHandler2(classT *const object, dataT data)
Constructor.
Definition: ssthandler.h:555
SSTHandler2(classT *const object)
Constructor.
Definition: ssthandler.h:525
Parameter store.
Definition: params.h:55
SSTHandlerNoArgs(classT *const object, PtrMember member, dataT data)
Constructor.
Definition: ssthandler.h:416
Functor classes for Event handling.
Definition: ssthandler.h:126
SSTHandler(classT *const object, PtrMember member, dataT data)
Constructor.
Definition: ssthandler.h:298
SSTHandler(classT *const object, PtrMember member)
Constructor.
Definition: ssthandler.h:327
SSTHandlerNoArgs(classT *const object, PtrMember member)
Constructor.
Definition: ssthandler.h:445
virtual ~SSTHandlerBaseNoArgs()
Handler function.
Definition: ssthandler.h:347