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