SST  15.1.0
StructuralSimulationToolkit
ssthandler.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_SSTHANDLER_H
13 #define SST_CORE_SSTHANDLER_H
14 
15 #include "sst/core/serialization/serializable.h"
16 #include "sst/core/sst_types.h"
17 
18 namespace SST {
19 
20 class Params;
21 
22 // This file contains base classes for use as various handlers (object
23 // encapsulating callback functions) in SST. These handlers are
24 // checkpointable and encapsulate a pointer to an object and a pointer
25 // to a member function of the object's class (captured via template
26 // parameter). The classes also allow you to optionally add one
27 // additional piece of static data to be passed into the callback
28 // function along with any data provided by the caller. There are two
29 // versions of this class, one that has no data passed from the caller
30 // (ending with SSTHandlerNoArgs), and one that has a single item
31 // passed from the caller (SSTHandler).
32 
33 // NOTE: Legacy SSTHandler objects are not checkpointable and have
34 // been deprecated. Support for legacy handlers will be removed in
35 // SST 15.
36 
37 // These classes provide the full functionality of the handlers and
38 // can be added to a class with the "using" keyword, as follows (a
39 // class can use any type name they'd like in place of HandlerBase and
40 // Handler, though those names are preferred for consistency):
41 
42 // Note: Until support for legacy handlers are removed, the new-style
43 // handlers should use Handler2Base and Handler2 as the preferred
44 // names. After legacy support is removed with SST 15, both Handler
45 // and Handler2 should both point to the new style handlers. Handler2
46 // will be deprecated from SST 15 until SST 16, when Handler will be
47 // the approved name.
48 
49 // LEGACY STYLE
50 
51 // using HandlerBase = SSTHandlerBase<return_type_of_callback, arg_type_of_callback>;
52 
53 // template <typename classT, typename dataT = void>
54 // using Handler = SSTHandler<return_type_of_callback, arg_type_of_callback, classT, dataT>;
55 
56 // Or:
57 
58 // using HandlerBase = SSTHandlerBaseNoArgs<return_type_of_callback>;
59 
60 // template <return_type_of_callback, typename classT, typename dataT = void>
61 // using Handler = SSTHandlerNoArgs<return_type_of_callback, classT, dataT>;
62 
63 // The handlers are then instanced as follows:
64 
65 // new Class::Handler<Class>(this, &Class::callback_function)
66 
67 // Or:
68 
69 // new Class::Handler<Class,int>(this, &Class::callback_function, 1)
70 
71 
72 // NEW STYLE
73 // Note: New style SSTHandler2 uses the same class for functions with and without parameters.
74 
75 // Note: HandlerBase is the same both both legacy and new style
76 // using HandlerBase = SSTHandlerBase<return_type_of_callback, arg_type_of_callback>;
77 
78 // template <typename classT, auto funcT, typename dataT = void>
79 // using Handler2 = SSTHandler2<return_type_of_callback, arg_type_of_callback, classT, dataT, funcT>;
80 
81 
82 // The handlers are then instanced as follows:
83 
84 // new Class::Handler2<Class, &Class::callback_function>(this)
85 
86 // Or:
87 
88 // new Class::Handler2<Class, &Class::callback_function, int>(this, 1)
89 
90 
91 /**********************************************************************
92  * Base class templates for handlers. The base functionlity includes
93  * the common API for all handlers. It also includes management of
94  * attach points.
95  *
96  * There are 4 total expansions of the template across 2 classes,
97  * based on whether their return and arg values are void or non-void.
98  * Each of these also define the appropriate Attach and/or Intercept
99  * points.
100  **********************************************************************/
101 
102 /**
103  Base template for handlers which take a class defined argument.
104 
105  This default expansion covers the case of non-void return
106  type. This version does not support intercepts.
107 */
108 template <typename returnT, typename argT>
110 {
111 public:
112  /**
113  Attach Point to get notified when a handler starts and stops.
114  This class is used in conjuction with a Tool type base class to
115  create various tool types to attach to the handler.
116  */
118  {
119  public:
120  AttachPoint() {}
121  virtual ~AttachPoint() {}
122 
123  /**
124  Function that will be called when a handler is registered
125  with the tool implementing the attach point. The metadata
126  passed in will be dependent on what type of tool this is
127  attached to. The uintptr_t returned from this function
128  will be passed into the beforeHandler() and afterHandler()
129  functions.
130 
131  @param mdata Metadata to be passed into the tool
132 
133  @return Opaque key that will be passed back into
134  beforeHandler() and afterHandler() to identify the source
135  of the calls
136  */
137  virtual uintptr_t registerHandler(const AttachPointMetaData& mdata) = 0;
138 
139  /**
140  Function to be called before the handler is called.
141 
142  @key uintptr_t returned from registerHandler() when handler
143  was registered with the tool
144 
145  @arg argument that will be passed to the handler function.
146  If argT is a pointer, this will be passed as a const
147  pointer, if not, it will be passed as a const reference
148  */
149  virtual void beforeHandler(uintptr_t key,
150  std::conditional_t<std::is_pointer_v<argT>, const std::remove_pointer_t<argT>*, const argT&> arg) = 0;
151 
152  /**
153  Function to be called after the handler is called. The key
154  passed in is the uintptr_t returned from registerHandler()
155 
156  @param key uintptr_t returned from registerHandler() when
157  handler was registered with the tool
158 
159  @param ret_value value that was returned by the handler. If
160  retunT is a pointer, this will be passed as a const
161  pointer, if not, it will be passed as a const reference
162  */
163  virtual void afterHandler(uintptr_t key,
164  std::conditional_t<std::is_pointer_v<returnT>, const std::remove_pointer_t<returnT>*, const returnT&>
165  ret_value) = 0;
166 
167  /**
168  Function that will be called to handle the key returned
169  from registerHandler, if the AttachPoint tool is
170  serializable. This is needed because the key is opaque to
171  the Link, so it doesn't know how to handle it during
172  serialization. During SIZE and PACK phases of
173  serialization, the tool needs to store out any information
174  that will be needed to recreate data that is reliant on the
175  key. On UNPACK, the function needs to recreate any state
176  and reinitialize the passed in key reference to the proper
177  state to continue to make valid calls to beforeHandler()
178  and afterHandler().
179 
180  Since not all tools will be serializable, there is a
181  default, empty implementation.
182 
183  @param ser Serializer to use for serialization
184 
185  @param key Key that would be passed into the
186  beforeHandler() and afterHandler() functions.
187  */
189  SST::Core::Serialization::serializer& UNUSED(ser), uintptr_t& UNUSED(key))
190  {}
191  };
192 
193 private:
194  using ToolList = std::vector<std::pair<AttachPoint*, uintptr_t>>;
195  ToolList* attached_tools = nullptr;
196 
197 protected:
198  // Implementation of operator() to be done in child classes
199  virtual returnT operator_impl(argT) = 0;
200 
201  void serialize_order(SST::Core::Serialization::serializer& ser) override
202  {
203  switch ( ser.mode() ) {
204  case Core::Serialization::serializer::SIZER:
205  case Core::Serialization::serializer::PACK:
206  {
207  ToolList tools;
208  if ( attached_tools ) {
209  for ( auto x : *attached_tools ) {
210  if ( dynamic_cast<SST::Core::Serialization::serializable*>(x.first) ) {
211  tools.push_back(x);
212  }
213  }
214  }
215  size_t tool_count = tools.size();
216  SST_SER(tool_count);
217  if ( tool_count > 0 ) {
218  // Serialize each tool, then call
219  // serializeEventAttachPointKey() to serialize any
220  // data associated with the key
221  for ( auto x : tools ) {
223  dynamic_cast<SST::Core::Serialization::serializable*>(x.first);
224  SST_SER(obj);
225  x.first->serializeHandlerAttachPointKey(ser, x.second);
226  }
227  }
228  break;
229  }
230  case Core::Serialization::serializer::UNPACK:
231  {
232  size_t tool_count;
233  SST_SER(tool_count);
234  if ( tool_count > 0 ) {
235  attached_tools = new ToolList();
236  for ( size_t i = 0; i < tool_count; ++i ) {
238  uintptr_t key;
239  SST_SER(tool);
240  AttachPoint* ap = dynamic_cast<AttachPoint*>(tool);
241  ap->serializeHandlerAttachPointKey(ser, key);
242  attached_tools->emplace_back(ap, key);
243  }
244  }
245  else {
246  attached_tools = nullptr;
247  }
248  break;
249  }
250  default:
251  break;
252  }
253  }
254 
255 public:
256  virtual ~SSTHandlerBase() {}
257 
258  inline returnT operator()(argT arg)
259  {
260  if ( !attached_tools ) return operator_impl(arg);
261 
262  // Tools attached
263  for ( auto& x : *attached_tools )
264  x.first->beforeHandler(x.second, arg);
265 
266  returnT ret = operator_impl(arg);
267 
268  for ( auto& x : *attached_tools )
269  x.first->afterHandler(x.second, ret);
270 
271  return ret;
272  }
273 
274  /**
275  Attaches a tool to the AttachPoint
276 
277  @param tool Tool to attach
278 
279  @param mdata Metadata to pass to the tool
280  */
281  void attachTool(AttachPoint* tool, const AttachPointMetaData& mdata)
282  {
283  if ( !attached_tools ) attached_tools = new ToolList();
284 
285  auto key = tool->registerHandler(mdata);
286  attached_tools->push_back(std::make_pair(tool, key));
287  }
288 
289  /**
290  Remove an attached tool
291 
292  @param tool Tool to remove. If tool doesn't exist, then no
293  action is taken
294  */
295  void detachTool(AttachPoint* tool)
296  {
297  if ( !attached_tools ) return;
298 
299  for ( auto x = attached_tools->begin(); x != attached_tools->end(); ++x ) {
300  if ( x->first == tool ) {
301  attached_tools->erase(x);
302  break;
303  }
304  }
305  }
306 
307  /**
308  Transfers attached tools from existing handler
309  */
311  {
312  if ( handler->attached_tools ) {
313  attached_tools = handler->attached_tools;
314  handler->attached_tools = nullptr;
315  }
316  }
317 
318 private:
319  ImplementVirtualSerializable(SSTHandlerBase)
320 };
321 
322 
323 /**
324  Base template for handlers which take an class defined argument.
325 
326  This expansion covers the case of void return type. This version
327  supports intercepts.
328 */
329 template <typename argT>
331 {
332 public:
333  /**
334  Attach Point to get notified when a handler starts and stops.
335  This class is used in conjuction with a Tool type base class to
336  create various tool types to attach to the handler.
337  */
338  class AttachPoint
339  {
340  public:
341  AttachPoint() {}
342  virtual ~AttachPoint() {}
343 
344  /**
345  Function that will be called when a handler is registered
346  with the tool implementing the attach point. The metadata
347  passed in will be dependent on what type of tool this is
348  attached to. The uintptr_t returned from this function
349  will be passed into the beforeHandler() and afterHandler()
350  functions.
351 
352  @param mdata Metadata to be passed into the tool
353 
354  @return Opaque key that will be passed back into
355  beforeHandler() and afterHandler() to identify the source
356  of the calls
357  */
358  virtual uintptr_t registerHandler(const AttachPointMetaData& mdata) = 0;
359 
360  /**
361  Function to be called before the handler is called.
362 
363  @key uintptr_t returned from registerHandler() when handler
364  was registered with the tool
365 
366  @arg argument that will be passed to the handler function.
367  If argT is a pointer, this will be passed as a const
368  pointer, if not, it will be passed as a const reference
369  */
370  virtual void beforeHandler(uintptr_t key,
371  std::conditional_t<std::is_pointer_v<argT>, const std::remove_pointer_t<argT>*, const argT&> arg) = 0;
372 
373  /**
374  Function to be called after the handler is called. The key
375  passed in is the uintptr_t returned from registerHandler()
376 
377  @param key uintptr_t returned from registerHandler() when
378  handler was registered with the tool
379  */
380  virtual void afterHandler(uintptr_t key) = 0;
381 
382  /**
383  Function that will be called to handle the key returned
384  from registerHandler, if the AttachPoint tool is
385  serializable. This is needed because the key is opaque to
386  the Link, so it doesn't know how to handle it during
387  serialization. During SIZE and PACK phases of
388  serialization, the tool needs to store out any information
389  that will be needed to recreate data that is reliant on the
390  key. On UNPACK, the function needs to recreate any state
391  and reinitialize the passed in key reference to the proper
392  state to continue to make valid calls to beforeHandler()
393  and afterHandler().
394 
395  Since not all tools will be serializable, there is a
396  default, empty implementation.
397 
398  @param ser Serializer to use for serialization
399 
400  @param key Key that would be passed into the
401  beforeHandler() and afterHandler() functions.
402  */
404  SST::Core::Serialization::serializer& UNUSED(ser), uintptr_t& UNUSED(key))
405  {}
406  };
407 
408 
409  /**
410  Attach Point to intercept the data being delivered by a
411  Handler. Class is not usable for Handlers that don't take a
412  parameter and/or return a value
413  */
414  class InterceptPoint
415  {
416  public:
417  /**
418  Function that will be called when a handler is registered
419  with the tool implementing the intercept attach point. The
420  metadata passed in will be dependent on what type of tool
421  this is attached to. The uintptr_t returned from this
422  function will be passed into the intercept() function.
423 
424  @param mdata Metadata to be passed into the tool
425 
426  @return Opaque key that will be passed back into
427  interceptHandler() calls
428  */
429  virtual uintptr_t registerHandlerIntercept(const AttachPointMetaData& mdata) = 0;
430 
431  /**
432  Function that will be called before the event handler to
433  let the attach point intercept the data. The data can be
434  modified, and if cancel is set to true, the handler will
435  not be executed. If cancel is set to true and the
436  ownership of a pointer is passed by the call to the
437  handler, then the function should also delete the data.
438 
439  @param key Key that was returned from
440  registerHandlerIntercept() function
441 
442  @param data Data that is to be passed to the handler
443 
444  @param[out] cancel Set to true if the handler delivery
445  should be cancelled.
446  */
447  virtual void interceptHandler(uintptr_t key, argT& data, bool& cancel) = 0;
448 
449  /**
450  Function that will be called to handle the key returned
451  from registerHandlerIntercept, if the AttachPoint tool is
452  serializable. This is needed because the key is opaque to
453  the Link, so it doesn't know how to handle it during
454  serialization. During SIZE and PACK phases of
455  serialization, the tool needs to store out any information
456  that will be needed to recreate data that is reliant on the
457  key. On UNPACK, the function needs to recreate any state
458  and reinitialize the passed in key reference to the proper
459  state to continue to make valid calls to
460  interceptHandler().
461 
462  Since not all tools will be serializable, there is a
463  default, empty implementation.
464 
465  @param ser Serializer to use for serialization
466 
467  @param key Key that would be passed into the interceptHandler() function.
468  */
470  SST::Core::Serialization::serializer& UNUSED(ser), uintptr_t& UNUSED(key))
471  {}
472 
473  virtual ~InterceptPoint() = default;
474  };
475 
476 private:
477  struct ToolList
478  {
479  std::vector<std::pair<AttachPoint*, uintptr_t>> attach_tools;
480  std::vector<std::pair<InterceptPoint*, uintptr_t>> intercept_tools;
481  };
482  ToolList* attached_tools = nullptr;
483 
484 protected:
485  // Implementation of operator() to be done in child classes
486  virtual void operator_impl(argT) = 0;
487 
488  void serialize_order(SST::Core::Serialization::serializer& ser) override
489  {
490  switch ( ser.mode() ) {
491  case Core::Serialization::serializer::SIZER:
492  case Core::Serialization::serializer::PACK:
493  {
494  ToolList tools;
495  if ( attached_tools ) {
496  for ( auto x : attached_tools->attach_tools ) {
497  if ( dynamic_cast<SST::Core::Serialization::serializable*>(x.first) ) {
498  tools.attach_tools.push_back(x);
499  }
500  }
501  for ( auto x : attached_tools->intercept_tools ) {
502  if ( dynamic_cast<SST::Core::Serialization::serializable*>(x.first) ) {
503  tools.intercept_tools.push_back(x);
504  }
505  }
506  }
507 
508  // Serialize AttachPoint tools
509  size_t tool_count = tools.attach_tools.size();
510  SST_SER(tool_count);
511  if ( tool_count > 0 ) {
512  // Serialize each tool, then call
513  // serializeEventAttachPointKey() to serialize any
514  // data associated with the key
515  for ( auto x : tools.attach_tools ) {
517  dynamic_cast<SST::Core::Serialization::serializable*>(x.first);
518  SST_SER(obj);
519  x.first->serializeHandlerAttachPointKey(ser, x.second);
520  }
521  }
522  // Serialize InterceptPoint tools
523  tool_count = tools.intercept_tools.size();
524  SST_SER(tool_count);
525  if ( tool_count > 0 ) {
526  // Serialize each tool, then call
527  // serializeEventAttachPointKey() to serialize any
528  // data associated with the key
529  for ( auto x : tools.intercept_tools ) {
531  dynamic_cast<SST::Core::Serialization::serializable*>(x.first);
532  SST_SER(obj);
533  x.first->serializeHandlerInterceptPointKey(ser, x.second);
534  }
535  }
536  break;
537  }
538  case Core::Serialization::serializer::UNPACK:
539  {
540  // Get serialized AttachPoint tools
541  size_t tool_count;
542  SST_SER(tool_count);
543  if ( tool_count > 0 ) {
544  attached_tools = new ToolList();
545  for ( size_t i = 0; i < tool_count; ++i ) {
547  uintptr_t key;
548  SST_SER(tool);
549  AttachPoint* ap = dynamic_cast<AttachPoint*>(tool);
550  ap->serializeHandlerAttachPointKey(ser, key);
551  attached_tools->attach_tools.emplace_back(ap, key);
552  }
553  }
554  else {
555  attached_tools = nullptr;
556  }
557 
558  // Get serialized InterceptPoint tools
559  SST_SER(tool_count);
560  if ( tool_count > 0 ) {
561  if ( nullptr == attached_tools ) attached_tools = new ToolList();
562  for ( size_t i = 0; i < tool_count; ++i ) {
564  uintptr_t key;
565  SST_SER(tool);
566  InterceptPoint* ip = dynamic_cast<InterceptPoint*>(tool);
567  ip->serializeHandlerInterceptPointKey(ser, key);
568  attached_tools->intercept_tools.emplace_back(ip, key);
569  }
570  }
571  break;
572  }
573  default:
574  break;
575  }
576  }
577 
578 public:
579  virtual ~SSTHandlerBase() {}
580 
581  inline void operator()(argT arg)
582  {
583  if ( !attached_tools ) return operator_impl(arg);
584 
585  // Tools attached
586  for ( auto& x : attached_tools->attach_tools )
587  x.first->beforeHandler(x.second, arg);
588 
589  // Check any intercepts
590 
591  bool cancel = false;
592  for ( auto& x : attached_tools->intercept_tools ) {
593  x.first->interceptHandler(x.second, arg, cancel);
594  if ( cancel ) {
595  // Handler cancelled; need to break since arg may
596  // no longer be valid and no other intercepts
597  // should be called
598  break;
599  }
600  }
601  if ( !cancel ) {
602  operator_impl(arg);
603  }
604 
605  for ( auto& x : attached_tools->attach_tools )
606  x.first->afterHandler(x.second);
607 
608  return;
609  }
610 
611 
612  /**
613  Attaches a tool to the AttachPoint
614 
615  @param tool Tool to attach
616 
617  @param mdata Metadata to pass to the tool
618  */
619  void attachTool(AttachPoint* tool, const AttachPointMetaData& mdata)
620  {
621  if ( !attached_tools ) attached_tools = new ToolList();
622 
623  auto key = tool->registerHandler(mdata);
624  attached_tools->attach_tools.push_back(std::make_pair(tool, key));
625  }
626 
627  /**
628  Remove an attached tool
629 
630  @param tool Tool to remove. If tool doesn't exist, then no
631  action is taken
632  */
633  void detachTool(AttachPoint* tool)
634  {
635  if ( !attached_tools ) return;
636 
637  for ( auto x = attached_tools->attach_tools.begin(); x != attached_tools->attach_tools.end(); ++x ) {
638  if ( x->first == tool ) {
639  attached_tools->attach_tools.erase(x);
640  break;
641  }
642  }
643  }
644 
645  /**
646  Attaches a tool to the AttachPoint
647 
648  @param tool Tool to attach
649 
650  @param mdata Metadata to pass to the tool
651  */
652  void attachInterceptTool(InterceptPoint* tool, const AttachPointMetaData& mdata)
653  {
654  if ( !attached_tools ) attached_tools = new ToolList();
655 
656  auto key = tool->registerHandlerIntercept(mdata);
657  attached_tools->intercept_tools.push_back(std::make_pair(tool, key));
658  }
659 
660  /**
661  Remove an attached tool
662 
663  @param tool Tool to remove. If tool doesn't exist, then no
664  action is taken
665  */
666  void detachInterceptTool(InterceptPoint* tool)
667  {
668  if ( !attached_tools ) return;
669 
670  for ( auto x = attached_tools->intercept_tools.begin(); x != attached_tools->intercept_tools.end(); ++x ) {
671  if ( x->first == tool ) {
672  attached_tools->intercept_tools.erase(x);
673  break;
674  }
675  }
676  }
677 
678  /**
679  Transfers attached tools from existing handler
680  */
682  {
683  if ( handler->attached_tools ) {
684  attached_tools = handler->attached_tools;
685  handler->attached_tools = nullptr;
686  }
687  }
688 
689 private:
690  ImplementVirtualSerializable(SSTHandlerBase)
691 };
692 
693 
694 /**
695  Base template for handlers which don't take a class defined
696  argument.
697 
698  This expansion covers the case of non-void return type. This
699  version does not support intercepts.
700 */
701 template <typename returnT>
703 {
704 public:
705  /**
706  Attach Point to get notified when a handler starts and stops.
707  This class is used in conjuction with a Tool type base class to
708  create various tool types to attach to the handler.
709  */
710  class AttachPoint
711  {
712  public:
713  AttachPoint() {}
714  virtual ~AttachPoint() {}
715 
716  /**
717  Function that will be called when a handler is registered
718  with the tool implementing the attach point. The metadata
719  passed in will be dependent on what type of tool this is
720  attached to. The uintptr_t returned from this function
721  will be passed into the beforeHandler() and afterHandler()
722  functions.
723 
724  @param mdata Metadata to be passed into the tool
725 
726  @return Opaque key that will be passed back into
727  beforeHandler() and afterHandler() to identify the source
728  of the calls
729  */
730  virtual uintptr_t registerHandler(const AttachPointMetaData& mdata) = 0;
731 
732  /**
733  Function to be called before the handler is called.
734 
735  @key uintptr_t returned from registerHandler() when handler
736  was registered with the tool
737  */
738  virtual void beforeHandler(uintptr_t key) = 0;
739 
740  /**
741  Function to be called after the handler is called. The key
742  passed in is the uintptr_t returned from registerHandler()
743 
744  @param key uintptr_t returned from registerHandler() when
745  handler was registered with the tool
746 
747  @param ret_value value that was returned by the handler. If
748  retunT is a pointer, this will be passed as a const
749  pointer, if not, it will be passed as a const reference
750  */
751  virtual void afterHandler(uintptr_t key,
752  std::conditional_t<std::is_pointer_v<returnT>, const std::remove_pointer_t<returnT>*, const returnT&>
753  ret_value) = 0;
754 
755  /**
756  Function that will be called to handle the key returned
757  from registerHandler, if the AttachPoint tool is
758  serializable. This is needed because the key is opaque to
759  the Link, so it doesn't know how to handle it during
760  serialization. During SIZE and PACK phases of
761  serialization, the tool needs to store out any information
762  that will be needed to recreate data that is reliant on the
763  key. On UNPACK, the function needs to recreate any state
764  and reinitialize the passed in key reference to the proper
765  state to continue to make valid calls to beforeHandler()
766  and afterHandler().
767 
768  Since not all tools will be serializable, there is a
769  default, empty implementation.
770 
771  @param ser Serializer to use for serialization
772 
773  @param key Key that would be passed into the
774  beforeHandler() and afterHandler() functions.
775  */
777  SST::Core::Serialization::serializer& UNUSED(ser), uintptr_t& UNUSED(key))
778  {}
779  };
780 
781 private:
782  using ToolList = std::vector<std::pair<AttachPoint*, uintptr_t>>;
783  ToolList* attached_tools = nullptr;
784 
785 protected:
786  // Implementation of operator() to be done in child classes
787  virtual returnT operator_impl() = 0;
788 
789  void serialize_order(SST::Core::Serialization::serializer& ser) override
790  {
791  switch ( ser.mode() ) {
792  case Core::Serialization::serializer::SIZER:
793  case Core::Serialization::serializer::PACK:
794  {
795  ToolList tools;
796  if ( attached_tools ) {
797  for ( auto x : *attached_tools ) {
798  if ( dynamic_cast<SST::Core::Serialization::serializable*>(x.first) ) {
799  tools.push_back(x);
800  }
801  }
802  }
803  size_t tool_count = tools.size();
804  SST_SER(tool_count);
805  if ( tool_count > 0 ) {
806  // Serialize each tool, then call
807  // serializeEventAttachPointKey() to serialize any
808  // data associated with the key
809  for ( auto x : tools ) {
811  dynamic_cast<SST::Core::Serialization::serializable*>(x.first);
812  SST_SER(obj);
813  x.first->serializeHandlerAttachPointKey(ser, x.second);
814  }
815  }
816  break;
817  }
818  case Core::Serialization::serializer::UNPACK:
819  {
820  size_t tool_count;
821  SST_SER(tool_count);
822  if ( tool_count > 0 ) {
823  attached_tools = new ToolList();
824  for ( size_t i = 0; i < tool_count; ++i ) {
826  uintptr_t key;
827  SST_SER(tool);
828  AttachPoint* ap = dynamic_cast<AttachPoint*>(tool);
829  ap->serializeHandlerAttachPointKey(ser, key);
830  attached_tools->emplace_back(ap, key);
831  }
832  }
833  else {
834  attached_tools = nullptr;
835  }
836  break;
837  }
838  default:
839  break;
840  }
841  }
842 
843 
844 public:
845  virtual ~SSTHandlerBase() {}
846 
847  inline returnT operator()()
848  {
849  if ( attached_tools ) {
850  for ( auto& x : *attached_tools )
851  x.first->beforeHandler(x.second);
852 
853  returnT ret = operator_impl();
854 
855  for ( auto& x : *attached_tools )
856  x.first->afterHandler(x.second, ret);
857 
858  return ret;
859  }
860  return operator_impl();
861  }
862 
863  /**
864  Attaches a tool to the AttachPoint
865 
866  @param tool Tool to attach
867 
868  @param mdata Metadata to pass to the tool
869  */
870  void attachTool(AttachPoint* tool, const AttachPointMetaData& mdata)
871  {
872  if ( !attached_tools ) attached_tools = new ToolList();
873 
874  auto key = tool->registerHandler(mdata);
875  attached_tools->push_back(std::make_pair(tool, key));
876  }
877 
878  /**
879  Remove an attached tool
880 
881  @param tool Tool to remove. If tool doesn't exist, then no
882  action is taken
883  */
884  void detachTool(AttachPoint* tool)
885  {
886  if ( !attached_tools ) return;
887 
888  for ( auto x = attached_tools->begin(); x != attached_tools->end(); ++x ) {
889  if ( x->first == tool ) {
890  attached_tools->erase(x);
891  break;
892  }
893  }
894  }
895 
896  /**
897  Transfers attached tools from existing handler
898  */
900  {
901  if ( handler->attached_tools ) {
902  attached_tools = handler->attached_tools;
903  handler->attached_tools = nullptr;
904  }
905  }
906 
907 private:
908  ImplementVirtualSerializable(SSTHandlerBase)
909 };
910 
911 
912 /**
913  Base template for handlers which don't take a class defined
914  argument.
915 
916  This expansion covers the case of void return type. This version
917  does not support intercepts.
918 */
919 template <>
921 {
922 public:
923  /**
924  Attach Point to get notified when a handler starts and stops.
925  This class is used in conjuction with a Tool type base class to
926  create various tool types to attach to the handler.
927  */
928  class AttachPoint
929  {
930  public:
931  AttachPoint() {}
932  virtual ~AttachPoint() {}
933 
934  /**
935  Function that will be called when a handler is registered
936  with the tool implementing the attach point. The metadata
937  passed in will be dependent on what type of tool this is
938  attached to. The uintptr_t returned from this function
939  will be passed into the beforeHandler() and afterHandler()
940  functions.
941 
942  @param mdata Metadata to be passed into the tool
943 
944  @return Opaque key that will be passed back into
945  beforeHandler() and afterHandler() to identify the source
946  of the calls
947  */
948  virtual uintptr_t registerHandler(const AttachPointMetaData& mdata) = 0;
949 
950  /**
951  Function to be called before the handler is called.
952 
953  @key uintptr_t returned from registerHandler() when handler
954  was registered with the tool
955  */
956  virtual void beforeHandler(uintptr_t key) = 0;
957 
958  /**
959  Function to be called after the handler is called. The key
960  passed in is the uintptr_t returned from registerHandler()
961 
962  @param key uintptr_t returned from registerHandler() when
963  handler was registered with the tool
964  */
965  virtual void afterHandler(uintptr_t key) = 0;
966 
967  /**
968  Function that will be called to handle the key returned
969  from registerHandler, if the AttachPoint tool is
970  serializable. This is needed because the key is opaque to
971  the Link, so it doesn't know how to handle it during
972  serialization. During SIZE and PACK phases of
973  serialization, the tool needs to store out any information
974  that will be needed to recreate data that is reliant on the
975  key. On UNPACK, the function needs to recreate any state
976  and reinitialize the passed in key reference to the proper
977  state to continue to make valid calls to beforeHandler()
978  and afterHandler().
979 
980  Since not all tools will be serializable, there is a
981  default, empty implementation.
982 
983  @param ser Serializer to use for serialization
984 
985  @param key Key that would be passed into the
986  beforeHandler() and afterHandler() functions.
987  */
989  SST::Core::Serialization::serializer& UNUSED(ser), uintptr_t& UNUSED(key))
990  {}
991  };
992 
993 private:
994  using ToolList = std::vector<std::pair<AttachPoint*, uintptr_t>>;
995  ToolList* attached_tools = nullptr;
996 
997 protected:
998  // Implementation of operator() to be done in child classes
999  virtual void operator_impl() = 0;
1000 
1001  void serialize_order(SST::Core::Serialization::serializer& ser) override
1002  {
1003  switch ( ser.mode() ) {
1004  case Core::Serialization::serializer::SIZER:
1005  case Core::Serialization::serializer::PACK:
1006  {
1007  ToolList tools;
1008  if ( attached_tools ) {
1009  for ( auto x : *attached_tools ) {
1010  if ( dynamic_cast<SST::Core::Serialization::serializable*>(x.first) ) {
1011  tools.push_back(x);
1012  }
1013  }
1014  }
1015  size_t tool_count = tools.size();
1016  SST_SER(tool_count);
1017  if ( tool_count > 0 ) {
1018  // Serialize each tool, then call
1019  // serializeEventAttachPointKey() to serialize any
1020  // data associated with the key
1021  for ( auto x : tools ) {
1023  dynamic_cast<SST::Core::Serialization::serializable*>(x.first);
1024  SST_SER(obj);
1025  x.first->serializeHandlerAttachPointKey(ser, x.second);
1026  }
1027  }
1028  break;
1029  }
1030  case Core::Serialization::serializer::UNPACK:
1031  {
1032  size_t tool_count;
1033  SST_SER(tool_count);
1034  if ( tool_count > 0 ) {
1035  attached_tools = new ToolList();
1036  for ( size_t i = 0; i < tool_count; ++i ) {
1038  uintptr_t key;
1039  SST_SER(tool);
1040  AttachPoint* ap = dynamic_cast<AttachPoint*>(tool);
1041  ap->serializeHandlerAttachPointKey(ser, key);
1042  attached_tools->emplace_back(ap, key);
1043  }
1044  }
1045  else {
1046  attached_tools = nullptr;
1047  }
1048  break;
1049  }
1050  default:
1051  break;
1052  }
1053  }
1054 
1055 public:
1056  virtual ~SSTHandlerBase() {}
1057 
1058  inline void operator()()
1059  {
1060  if ( attached_tools ) {
1061  for ( auto& x : *attached_tools )
1062  x.first->beforeHandler(x.second);
1063 
1064  operator_impl();
1065 
1066  for ( auto& x : *attached_tools )
1067  x.first->afterHandler(x.second);
1068 
1069  return;
1070  }
1071  return operator_impl();
1072  }
1073 
1074  /**
1075  Attaches a tool to the AttachPoint
1076 
1077  @param tool Tool to attach
1078 
1079  @param mdata Metadata to pass to the tool
1080  */
1081  void attachTool(AttachPoint* tool, const AttachPointMetaData& mdata)
1082  {
1083  if ( !attached_tools ) attached_tools = new ToolList();
1084 
1085  auto key = tool->registerHandler(mdata);
1086  attached_tools->push_back(std::make_pair(tool, key));
1087  }
1088 
1089  /**
1090  Remove an attached tool
1091 
1092  @param tool Tool to remove. If tool doesn't exist, then no
1093  action is taken
1094  */
1095  void detachTool(AttachPoint* tool)
1096  {
1097  if ( !attached_tools ) return;
1098 
1099  for ( auto x = attached_tools->begin(); x != attached_tools->end(); ++x ) {
1100  if ( x->first == tool ) {
1101  attached_tools->erase(x);
1102  break;
1103  }
1104  }
1105  }
1106 
1107  /**
1108  Transfers attached tools from existing handler
1109  */
1111  {
1112  if ( handler->attached_tools ) {
1113  attached_tools = handler->attached_tools;
1114  handler->attached_tools = nullptr;
1115  }
1116  }
1117 
1118 private:
1119  ImplementVirtualSerializable(SSTHandlerBase)
1120 };
1121 
1122 
1123 /**********************************************************************
1124  * Legacy Handlers
1125  *
1126  * These handlers do not support checkpointing and will be removed in
1127  * SST 15.
1128  **********************************************************************/
1129 
1130 template <typename returnT>
1131 using SSTHandlerBaseNoArgs = SSTHandlerBase<returnT, void>;
1132 /**
1133  * Handler class with user-data argument
1134  */
1135 template <typename returnT, typename argT, typename classT, typename dataT = void>
1136 class SSTHandler : public SSTHandlerBase<returnT, argT>
1137 {
1138 private:
1139  using PtrMember = returnT (classT::*)(argT, dataT);
1140  classT* object;
1141  const PtrMember member;
1142  dataT data;
1143 
1144 public:
1145  /** Constructor
1146  * @param object - Pointer to Object upon which to call the handler
1147  * @param member - Member function to call as the handler
1148  * @param data - Additional argument to pass to handler
1149  */
1150  SSTHandler(classT* const object, PtrMember member, dataT data) :
1151  SSTHandlerBase<returnT, argT>(),
1152  object(object),
1153  member(member),
1154  data(data)
1155  {}
1156 
1157  SSTHandler(const SSTHandler&) = delete;
1158  SSTHandler& operator=(const SSTHandler&) = delete;
1159 
1160  returnT operator_impl(argT arg) override { return (object->*member)(arg, data); }
1161 
1162  NotSerializable(SSTHandler)
1163 };
1164 
1165 
1166 /**
1167  * Event Handler class with no user-data.
1168  */
1169 template <typename returnT, typename argT, typename classT>
1170 class SSTHandler<returnT, argT, classT, void> : public SSTHandlerBase<returnT, argT>
1171 {
1172 private:
1173  using PtrMember = returnT (classT::*)(argT);
1174  const PtrMember member;
1175  classT* object;
1176 
1177 public:
1178  /** Constructor
1179  * @param object - Pointer to Object upon which to call the handler
1180  * @param member - Member function to call as the handler
1181  */
1182  SSTHandler(classT* const object, PtrMember member) :
1183  SSTHandlerBase<returnT, argT>(),
1184  member(member),
1185  object(object)
1186  {}
1187 
1188  SSTHandler(const SSTHandler&) = delete;
1189  SSTHandler& operator=(const SSTHandler&) = delete;
1190 
1191  returnT operator_impl(argT arg) override { return (object->*member)(arg); }
1192 
1193  NotSerializable(SSTHandler)
1194 };
1195 
1196 
1197 /**
1198  * Event Handler class with user-data argument
1199  */
1200 template <typename returnT, typename classT, typename dataT = void>
1202 {
1203 private:
1204  using PtrMember = returnT (classT::*)(dataT);
1205  classT* object;
1206  const PtrMember member;
1207  dataT data;
1208 
1209 public:
1210  /** Constructor
1211  * @param object - Pointer to Object upon which to call the handler
1212  * @param member - Member function to call as the handler
1213  * @param data - Additional argument to pass to handler
1214  */
1215  SSTHandlerNoArgs(classT* const object, PtrMember member, dataT data) :
1216  SSTHandlerBase<returnT, void>(),
1217  object(object),
1218  member(member),
1219  data(data)
1220  {}
1221 
1222  SSTHandlerNoArgs(const SSTHandlerNoArgs&) = delete;
1223  SSTHandlerNoArgs& operator=(const SSTHandlerNoArgs&) = delete;
1224 
1225  void operator_impl() override { return (object->*member)(data); }
1226 
1227  NotSerializable(SSTHandlerNoArgs)
1228 };
1229 
1230 
1231 /**
1232  * Event Handler class with no user-data.
1233  */
1234 template <typename returnT, typename classT>
1235 class SSTHandlerNoArgs<returnT, classT, void> : public SSTHandlerBaseNoArgs<returnT>
1236 {
1237 private:
1238  using PtrMember = returnT (classT::*)();
1239  const PtrMember member;
1240  classT* object;
1241 
1242 public:
1243  /** Constructor
1244  * @param object - Pointer to Object upon which to call the handler
1245  * @param member - Member function to call as the handler
1246  */
1247  SSTHandlerNoArgs(classT* const object, PtrMember member) :
1248  SSTHandlerBase<returnT, void>(),
1249  member(member),
1250  object(object)
1251  {}
1252 
1253  SSTHandlerNoArgs(const SSTHandlerNoArgs&) = delete;
1254  SSTHandlerNoArgs& operator=(const SSTHandlerNoArgs&) = delete;
1255 
1256  void operator_impl() override { return (object->*member)(); }
1257 
1258  NotSerializable(SSTHandlerNoArgs)
1259 };
1260 
1261 
1262 /**********************************************************************
1263  * New Style Handlers
1264  *
1265  * These handlers support checkpointing
1266  **********************************************************************/
1267 
1268 /**
1269  Base template for the class. If this one gets chosen, then there
1270  is a mismatch somewhere, so it will just static_assert
1271  */
1272 template <typename returnT, typename argT, typename classT, typename dataT, auto funcT>
1273 class SSTHandler2 : public SSTHandlerBase<returnT, argT>
1274 {
1275  // This has to be dependent on a template parameter, otherwise it always asserts.
1276  static_assert((funcT, false), "Mismatched handler templates.");
1277 };
1278 
1279 
1280 /**
1281  * Handler class with user-data argument
1282  */
1283 template <typename returnT, typename argT, typename classT, typename dataT, returnT (classT::*funcT)(argT, dataT)>
1284 class SSTHandler2<returnT, argT, classT, dataT, funcT> : public SSTHandlerBase<returnT, argT>
1285 {
1286 private:
1287  classT* object;
1288  dataT data;
1289 
1290 public:
1291  /** Constructor
1292  * @param object - Pointer to Object upon which to call the handler
1293  * @param data - Additional argument to pass to handler
1294  */
1295  SSTHandler2(classT* const object, dataT data) :
1296  SSTHandlerBase<returnT, argT>(),
1297  object(object),
1298  data(data)
1299  {}
1300 
1301  SSTHandler2() {}
1302 
1303  SSTHandler2(const SSTHandler2&) = delete;
1304  SSTHandler2& operator=(const SSTHandler2&) = delete;
1305 
1306  returnT operator_impl(argT arg) override { return (object->*funcT)(arg, data); }
1307 
1308  void serialize_order(SST::Core::Serialization::serializer& ser) override
1309  {
1310  SSTHandlerBase<returnT, argT>::serialize_order(ser);
1311  SST_SER(object);
1312  SST_SER(data);
1313  }
1314 
1315  ImplementSerializable(SSTHandler2)
1316 };
1317 
1318 
1319 /**
1320  * Event Handler class with no user-data.
1321  */
1322 template <typename returnT, typename argT, typename classT, returnT (classT::*funcT)(argT)>
1323 class SSTHandler2<returnT, argT, classT, void, funcT> : public SSTHandlerBase<returnT, argT>
1324 {
1325 private:
1326  classT* object;
1327 
1328 public:
1329  /** Constructor
1330  * @param object - Pointer to Object upon which to call the handler
1331  * @param member - Member function to call as the handler
1332  */
1333  explicit SSTHandler2(classT* const object) :
1334  SSTHandlerBase<returnT, argT>(),
1335  object(object)
1336  {}
1337  SSTHandler2() {}
1338 
1339  SSTHandler2(const SSTHandler2&) = delete;
1340  SSTHandler2& operator=(const SSTHandler2&) = delete;
1341 
1342  returnT operator_impl(argT arg) override { return (object->*funcT)(arg); }
1343 
1344  void serialize_order(SST::Core::Serialization::serializer& ser) override
1345  {
1346  SSTHandlerBase<returnT, argT>::serialize_order(ser);
1347  SST_SER(object);
1348  }
1349 
1350  ImplementSerializable(SSTHandler2)
1351 };
1352 
1353 
1354 /**
1355  * Event Handler class with user-data argument
1356  */
1357 template <typename returnT, typename classT, typename dataT, returnT (classT::*funcT)(dataT)>
1358 class SSTHandler2<returnT, void, classT, dataT, funcT> : public SSTHandlerBase<returnT, void>
1359 {
1360 private:
1361  classT* object;
1362  dataT data;
1363 
1364 public:
1365  /** Constructor
1366  * @param object - Pointer to Object upon which to call the handler
1367  * @param data - Additional argument to pass to handler
1368  */
1369  SSTHandler2(classT* const object, dataT data) :
1370  SSTHandlerBase<returnT, void>(),
1371  object(object),
1372  data(data)
1373  {}
1374  SSTHandler2() {}
1375 
1376  SSTHandler2(const SSTHandler2&) = delete;
1377  SSTHandler2& operator=(const SSTHandler2&) = delete;
1378 
1379  returnT operator_impl() override { return (object->*funcT)(data); }
1380 
1381  void serialize_order(SST::Core::Serialization::serializer& ser) override
1382  {
1383  SSTHandlerBase<returnT, void>::serialize_order(ser);
1384  SST_SER(object);
1385  SST_SER(data);
1386  }
1387 
1388  ImplementSerializable(SSTHandler2)
1389 };
1390 
1391 
1392 /**
1393  * Event Handler class with user-data argument
1394  */
1395 template <typename returnT, typename classT, returnT (classT::*funcT)()>
1396 class SSTHandler2<returnT, void, classT, void, funcT> : public SSTHandlerBase<returnT, void>
1397 {
1398 private:
1399  classT* object;
1400 
1401 public:
1402  /** Constructor
1403  * @param object - Pointer to Object upon which to call the handler
1404  * @param data - Additional argument to pass to handler
1405  */
1406  explicit SSTHandler2(classT* const object) :
1407  SSTHandlerBase<returnT, void>(),
1408  object(object)
1409  {}
1410  SSTHandler2() {}
1411 
1412  SSTHandler2(const SSTHandler2&) = delete;
1413  SSTHandler2& operator=(const SSTHandler2&) = delete;
1414 
1415  returnT operator_impl() override { return (object->*funcT)(); }
1416 
1417  void serialize_order(SST::Core::Serialization::serializer& ser) override
1418  {
1419  SSTHandlerBase<returnT, void>::serialize_order(ser);
1420  SST_SER(object);
1421  }
1422 
1423  ImplementSerializable(SSTHandler2)
1424 };
1425 
1426 } // namespace SST
1427 
1428 #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:42
Base template for handlers which take a class defined argument.
Definition: ssthandler.h:109
virtual void serializeHandlerAttachPointKey(SST::Core::Serialization::serializer &UNUSED(ser), uintptr_t &UNUSED(key))
Function that will be called to handle the key returned from registerHandler, if the AttachPoint tool...
Definition: ssthandler.h:988
virtual void serializeHandlerAttachPointKey(SST::Core::Serialization::serializer &UNUSED(ser), uintptr_t &UNUSED(key))
Function that will be called to handle the key returned from registerHandler, if the AttachPoint tool...
Definition: ssthandler.h:188
void transferAttachedToolInfo(SSTHandlerBase *handler)
Transfers attached tools from existing handler.
Definition: ssthandler.h:899
void detachInterceptTool(InterceptPoint *tool)
Remove an attached tool.
Definition: ssthandler.h:666
Base template for the class.
Definition: ssthandler.h:1273
Handler class with user-data argument.
Definition: ssthandler.h:1136
virtual void afterHandler(uintptr_t key, std::conditional_t< std::is_pointer_v< returnT >, const std::remove_pointer_t< returnT > *, const returnT &> ret_value)=0
Function to be called after the handler is called.
Definition: action.cc:18
void transferAttachedToolInfo(SSTHandlerBase *handler)
Transfers attached tools from existing handler.
Definition: ssthandler.h:681
void transferAttachedToolInfo(SSTHandlerBase *handler)
Transfers attached tools from existing handler.
Definition: ssthandler.h:310
Definition: serializable.h:23
SSTHandler2(classT *const object)
Constructor.
Definition: ssthandler.h:1406
virtual void beforeHandler(uintptr_t key, std::conditional_t< std::is_pointer_v< argT >, const std::remove_pointer_t< argT > *, const argT &> arg)=0
Function to be called before the handler is called.
Base template for handlers which don&#39;t take a class defined argument.
Definition: ssthandler.h:702
Event Handler class with user-data argument.
Definition: ssthandler.h:1201
void attachTool(AttachPoint *tool, const AttachPointMetaData &mdata)
Attaches a tool to the AttachPoint.
Definition: ssthandler.h:281
void detachTool(AttachPoint *tool)
Remove an attached tool.
Definition: ssthandler.h:1095
SSTHandler2(classT *const object, dataT data)
Constructor.
Definition: ssthandler.h:1295
void attachTool(AttachPoint *tool, const AttachPointMetaData &mdata)
Attaches a tool to the AttachPoint.
Definition: ssthandler.h:1081
SSTHandler2(classT *const object, dataT data)
Constructor.
Definition: ssthandler.h:1369
virtual uintptr_t registerHandler(const AttachPointMetaData &mdata)=0
Function that will be called when a handler is registered with the tool implementing the attach point...
Attach Point to get notified when a handler starts and stops.
Definition: ssthandler.h:117
void detachTool(AttachPoint *tool)
Remove an attached tool.
Definition: ssthandler.h:633
void attachInterceptTool(InterceptPoint *tool, const AttachPointMetaData &mdata)
Attaches a tool to the AttachPoint.
Definition: ssthandler.h:652
void attachTool(AttachPoint *tool, const AttachPointMetaData &mdata)
Attaches a tool to the AttachPoint.
Definition: ssthandler.h:619
SSTHandler2(classT *const object)
Constructor.
Definition: ssthandler.h:1333
virtual void serializeHandlerAttachPointKey(SST::Core::Serialization::serializer &UNUSED(ser), uintptr_t &UNUSED(key))
Function that will be called to handle the key returned from registerHandler, if the AttachPoint tool...
Definition: ssthandler.h:776
SSTHandlerNoArgs(classT *const object, PtrMember member, dataT data)
Constructor.
Definition: ssthandler.h:1215
virtual void serializeHandlerAttachPointKey(SST::Core::Serialization::serializer &UNUSED(ser), uintptr_t &UNUSED(key))
Function that will be called to handle the key returned from registerHandler, if the AttachPoint tool...
Definition: ssthandler.h:403
virtual void serializeHandlerInterceptPointKey(SST::Core::Serialization::serializer &UNUSED(ser), uintptr_t &UNUSED(key))
Function that will be called to handle the key returned from registerHandlerIntercept, if the AttachPoint tool is serializable.
Definition: ssthandler.h:469
void detachTool(AttachPoint *tool)
Remove an attached tool.
Definition: ssthandler.h:884
Struct used as a base class for all AttachPoint metadata passed to registration functions.
Definition: sst_types.h:80
void detachTool(AttachPoint *tool)
Remove an attached tool.
Definition: ssthandler.h:295
SSTHandler(classT *const object, PtrMember member, dataT data)
Constructor.
Definition: ssthandler.h:1150
SSTHandler(classT *const object, PtrMember member)
Constructor.
Definition: ssthandler.h:1182
SSTHandlerNoArgs(classT *const object, PtrMember member)
Constructor.
Definition: ssthandler.h:1247
void attachTool(AttachPoint *tool, const AttachPointMetaData &mdata)
Attaches a tool to the AttachPoint.
Definition: ssthandler.h:870
void transferAttachedToolInfo(SSTHandlerBase *handler)
Transfers attached tools from existing handler.
Definition: ssthandler.h:1110