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