|
|
|||
File indexing completed on 2026-11-07 10:11:32
0001 //------------------------------- -*- C++ -*- -------------------------------// 0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details 0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0004 //---------------------------------------------------------------------------// 0005 //! \file celeritas/g4/StateDependent.hh 0006 //---------------------------------------------------------------------------// 0007 #pragma once 0008 0009 #include <functional> 0010 #include <utility> 0011 #include <G4VStateDependent.hh> 0012 0013 #include "corecel/Macros.hh" 0014 #include "corecel/sys/ThreadId.hh" 0015 0016 class G4StateManager; 0017 0018 namespace celeritas 0019 { 0020 //---------------------------------------------------------------------------// 0021 /*! 0022 * Encode a meaningful Geant4 state transition for user callbacks. 0023 * 0024 * The transitions are encoded as `GeantStateChange` values according to 0025 * the following table (previous -> requested): 0026 * 0027 * | Previous State | Requested State | Change | 0028 * |------------------------|------------------------|-----------------| 0029 * | *none* | `G4State_PreInit` | `begin_program` | 0030 * | `G4State_PreInit` | `G4State_Init` | `begin_init` | 0031 * | `G4State_Idle` | `G4State_Init` | `begin_init` | 0032 * | `G4State_Init` | `G4State_Init` | `internal_init` | 0033 * | `G4State_Init` | `G4State_Idle` | `end_init` | 0034 * | `G4State_Idle` | `G4State_GeomClosed` | `begin_run` | 0035 * | `G4State_GeomClosed` | `G4State_EventProc` | `begin_event` | 0036 * | `G4State_EventProc` | `G4State_GeomClosed` | `end_event` | 0037 * | `G4State_GeomClosed` | `G4State_Idle` | `end_run` | 0038 * | *any* | `G4State_Quit` | `end_program` | 0039 * | *any* | `G4State_Abort` | `end_program` | 0040 * | *other* | *other* | `unknown` | 0041 * 0042 * \par Notes: 0043 * 0044 * - \c begin_program is called during the \c G4RunManagerKernel constructor, 0045 * so it will only register if your state dependent is constructed very early 0046 * and on the main thread. 0047 * - In raw mode, the first \c G4State_Init transition from \c G4State_PreInit 0048 * emits an extra \c initialize callback before \c begin_init. 0049 * - In MT mode, \c RunManager::Initialize actually calls begin/end run for 0050 * each thread, including master. 0051 * - \c end_program is called by the G4RunManager and G4RunManagerKernel 0052 * destructor during normal execution (via \c G4State_Quit). 0053 * - \c end_program is called by \c G4Exception when a fatal error occurred 0054 * (via \c G4State_Abort). 0055 */ 0056 enum class GeantStateChange 0057 { 0058 begin_program, 0059 initialize, 0060 begin_init, 0061 internal_init, 0062 end_init, 0063 begin_run, 0064 begin_event, 0065 end_event, 0066 end_run, 0067 end_program, 0068 unknown, 0069 size_, 0070 }; 0071 0072 // Callback receives a stream id and the encoded `GeantStateChange`. 0073 using LocalGeantStateChangeFunc 0074 = std::function<void(StreamId, GeantStateChange)>; 0075 0076 //---------------------------------------------------------------------------// 0077 // HELPER FUNCTIONS (HOST) 0078 //---------------------------------------------------------------------------// 0079 0080 // Get a string corresponding to a Geant4 state change 0081 char const* to_cstring(GeantStateChange); 0082 0083 //---------------------------------------------------------------------------// 0084 /*! 0085 * Receive notifications when the Geant4 application state changes. 0086 * 0087 * This thread-local wrapper observes Geant4 application state transitions and 0088 * calls a shared user-provided function for the creating stream. Raw mode 0089 * dispatches every encoded state transition; lifecycle mode dispatches the 0090 * filtered run lifecycle used by automatic Celeritas setup. 0091 * 0092 * \warning The Geant4 memory semantics for this class are unusual. 0093 * - The thread-local \c G4StateManager singleton keeps a pointer (via the \c 0094 * G4VStateDependent base constructor) to this local instance and calls \c 0095 * delete on it when it's deleted as the run manager shuts down. 0096 * Therefore this class \c must be deleted before \c G4StateManager ends. 0097 * - The base class destructor calls the thread-local \c G4StateManager without 0098 * checking for validity, so the destructor of this class \em after deleting 0099 * the run manager will also crash the code. 0100 * - The thread-local pointer mapping means that this class \em must be 0101 * deallocated on the thread in which it's created. 0102 * 0103 * To bypass the first failure path, we use \c Notify to deregister ourselves 0104 * when we see the run manager is about to exit or abort. 0105 * 0106 * The owner must keep the instance on the creating thread and callbacks must 0107 * not delete the active state-dependent object. In lifecycle mode this object 0108 * should be owned explicitly, similarly to Geant4 UI messenger objects. 0109 * 0110 * In \c Mode::lifecycle this class filters raw Geant4 state changes into the 0111 * lifecycle transitions needed by Celeritas automatic setup: \c begin_run, 0112 * \c end_run, and \c end_program. 0113 */ 0114 class StateDependent final : public G4VStateDependent 0115 { 0116 public: 0117 //! How to dispatch Geant4 state changes 0118 enum class Mode 0119 { 0120 raw, 0121 lifecycle, 0122 }; 0123 0124 //! Lifecycle cleanup scope owned by this monitor 0125 enum class LifecycleRole 0126 { 0127 global, 0128 local, 0129 }; 0130 0131 // Construct locally with state-change callback, dispatch mode, and 0132 // lifecycle role 0133 StateDependent( 0134 LocalGeantStateChangeFunc cb, Mode mode, LifecycleRole lifecycle_role); 0135 0136 //! Construct locally in raw mode with a state-change callback 0137 explicit StateDependent(LocalGeantStateChangeFunc cb) 0138 : StateDependent{std::move(cb), Mode::raw, LifecycleRole::global} 0139 { 0140 } 0141 0142 // Prevent move/copy because the base class registers this object by 0143 // pointer 0144 CELER_DELETE_COPY_MOVE(StateDependent); 0145 0146 // Handle notification when the Geant4 state changes 0147 G4bool Notify(G4ApplicationState state) final; 0148 0149 //! Stream that created this state dependent 0150 StreamId local_stream() const { return local_stream_; } 0151 0152 private: 0153 StreamId local_stream_; 0154 LocalGeantStateChangeFunc cb_; 0155 G4StateManager* manager_{nullptr}; 0156 Mode mode_{Mode::raw}; 0157 LifecycleRole lifecycle_role_{LifecycleRole::global}; 0158 0159 // Whether this local monitor has emitted a lifecycle begin_run that still 0160 // needs a matching end_run. 0161 bool active_run_{false}; 0162 0163 // Dispatch a filtered lifecycle change 0164 void dispatch_lifecycle_change(GeantStateChange); 0165 }; 0166 0167 //---------------------------------------------------------------------------// 0168 } // namespace celeritas
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|