11// gstreamer
2- #include " gstreamer_options .h"
2+ #include " gstreamer .h"
33
44// gemc
55#include " glogger.h"
66#include " gdynamicdigitization.h"
77#include " gutilities.h"
88#include " gdata_options.h"
9- #include < gtouchable_options.h>
9+ #include " gtouchable_options.h"
1010
1111// this example uses the gplugin built by gdynamicDigitization example
1212const std::string plugin_name = " gplugin_test_example" ;
@@ -21,22 +21,6 @@ const std::string plugin_name = "gplugin_test_example";
2121#include < memory> // smart pointers
2222#include < unordered_map>
2323
24- // -----------------------------------------------------------------------------
25- // Shared state (visible to all threads)
26- // -----------------------------------------------------------------------------
27-
28- // runData holds the finished events. We store them as *unique_ptr* because
29- // each event is owned by the container and *only* by the container (single
30- // ownership → choose unique_ptr, not shared_ptr).
31- inline std::vector<std::unique_ptr<GEventDataCollection>> runData;
32-
33- // Protect runData from concurrent push_back calls. Only the push itself is
34- // guarded; building events happens outside the critical section.
35- inline std::mutex runDataMtx;
36-
37- // If loggers / dynamicRoutines themselves are *not* thread-safe you would
38- // add their own mutexes here (omitted for brevity).
39-
4024// ===== portable jthread-like wrapper =========================================
4125// If real std::jthread is present, use it. Otherwise, define a minimal shim
4226// that joins in the destructor (no stop_token support, but good enough here).
@@ -62,10 +46,10 @@ class jthread_alias : public std::thread {
6246// Build a single event and hand back exclusive ownership
6347// Trailing-return syntax: auto f(args) -> ReturnType
6448// -----------------------------------------------------------------------------
65- auto build_event (int evn,
66- const std::shared_ptr<GLogger>& loge,
67- const std::shared_ptr<GLogger>& logt,
68- std::unordered_map<std::string, std::shared_ptr<GDynamicDigitization>> dynamicRoutines ) -> std::unique_ptr<GEventDataCollection> {
49+ auto build_event (int evn,
50+ const std::shared_ptr<GLogger>& loge,
51+ const std::shared_ptr<GLogger>& logt,
52+ std::unordered_map<std::string, std::shared_ptr<GDynamicDigitization>> dynamicRoutinesMap ) -> std::unique_ptr<GEventDataCollection> {
6953 // --------- Header construction ------------------------------------------
7054 // unique_ptr means *exactly one* owner. We start as the owner and later
7155 // transfer ownership to eventData (see release() below).
@@ -113,12 +97,12 @@ auto build_event(int evn,
11397 hit1->randomizeHitForTesting (10 );
11498 hit2->randomizeHitForTesting (5 );
11599
116- // dynamicRoutines assumed thread-safe
117- auto truedata1 = dynamicRoutines [plugin_name]->collectTrueInformation (hit1.get (), 1 );
118- auto truedata2 = dynamicRoutines [plugin_name]->collectTrueInformation (hit2.get (), 2 );
100+ // dynamicRoutinesMap assumed thread-safe
101+ auto truedata1 = dynamicRoutinesMap [plugin_name]->collectTrueInformation (hit1.get (), 1 );
102+ auto truedata2 = dynamicRoutinesMap [plugin_name]->collectTrueInformation (hit2.get (), 2 );
119103
120- auto digi1 = dynamicRoutines [plugin_name]->digitizeHit (hit1.get (), 1 );
121- auto digi2 = dynamicRoutines [plugin_name]->digitizeHit (hit2.get (), 2 );
104+ auto digi1 = dynamicRoutinesMap [plugin_name]->digitizeHit (hit1.get (), 1 );
105+ auto digi2 = dynamicRoutinesMap [plugin_name]->digitizeHit (hit2.get (), 2 );
122106
123107 eventData->addDetectorDigitizedData (plugin_name, digi1);
124108 eventData->addDetectorDigitizedData (plugin_name, digi2);
@@ -136,7 +120,9 @@ void run_simulation(int
136120 int nthreads,
137121 const std::shared_ptr<GLogger>& loge,
138122 const std::shared_ptr<GLogger>& logt,
139- std::unordered_map<std::string, std::shared_ptr<GDynamicDigitization>> dynamicRoutines) {
123+ std::unordered_map<std::string, std::shared_ptr<GDynamicDigitization>> dynamicRoutinesMap,
124+ std::vector<std::unique_ptr<GEventDataCollection>>& runData,
125+ std::mutex& runDataMtx) {
140126 // thread-safe integer counter starts at 1.
141127 // fetch_add returns the old value *and* bumps.
142128 // Zero contention: each thread fetches the next free event number.
@@ -172,7 +158,7 @@ void run_simulation(int
172158 int evn = next.fetch_add (1 , std::memory_order_relaxed); // atomically returns the current value and increments it by 1.
173159 if (evn > nevents) break ; // exit the while loop
174160
175- auto event = build_event (evn, loge, logt, dynamicRoutines );
161+ auto event = build_event (evn, loge, logt, dynamicRoutinesMap );
176162
177163 // ---- Critical section: push into the shared vector ----------
178164 // std::scoped_lock locks *all* mutexes passed to it and unlocks
@@ -197,49 +183,69 @@ void run_simulation(int
197183}
198184
199185int main (int argc, char * argv[]) {
186+ // runData holds the finished events. We store them as *unique_ptr* because
187+ // each event is owned by the container and *only* by the container (single
188+ // ownership → choose unique_ptr, not shared_ptr).
189+ std::vector<std::unique_ptr<GEventDataCollection>> runData;
190+
191+ // Protect runData from concurrent push_back calls. Only the push itself is
192+ // guarded; building events happens outside the critical section.
193+ std::mutex runDataMtx;
194+
200195 // Create GOptions using gdata::defineOptions, which aggregates options from gdata and gtouchable.
201196 auto gopts = new GOptions (argc, argv, gstreamer::defineOptions ());
202197
203- auto log = new GLogger (gopts, GSTREAMER_LOGGER , " gstreamer_example: main" );
204- auto plugin_log = std::make_shared<GLogger>(gopts, GSTREAMER_LOGGER , " gstreamer_example: plugin manager" );
205- auto loge = std::make_shared<GLogger>(gopts, DATA_LOGGER , " gstreamer_example example: GEventDataCollection" );
206- auto logt = std::make_shared<GLogger>(gopts, TOUCHABLE_LOGGER , " gstreamer_example example: GTouchable" );
198+ auto log = std::make_shared<GLogger>(gopts, GSTREAMER_LOGGER , " gstreamer_example: main" );
199+ auto loge = std::make_shared<GLogger>(gopts, DATA_LOGGER , " gstreamer_example example: GEventDataCollection" );
200+ auto logt = std::make_shared<GLogger>(gopts, TOUCHABLE_LOGGER , " gstreamer_example example: GTouchable" );
207201
208- GManager manager (plugin_log);
209-
210- // using dynamicRoutines map
211- std::map<std::string, GDynamicDigitization*> dynamicRoutines;
202+ // Digitization plugin manager
203+ GManager manager (log);
212204
213205 // mutable map of shared pointers to GDynamicDigitization objects
214- std::unordered_map<std::string,
215- std::shared_ptr<GDynamicDigitization>> dynamicRoutines2;
216-
206+ std::unordered_map<std::string, std::shared_ptr<GDynamicDigitization>> dynamicRoutinesMap;
217207
218- dynamicRoutines[plugin_name] = manager.LoadAndRegisterObjectFromLibrary <GDynamicDigitization>(" test_gdynamic_plugin" , gopts);
208+ dynamicRoutinesMap.emplace (plugin_name,
209+ manager.LoadAndRegisterObjectFromLibrary <GDynamicDigitization>(" test_gdynamic_plugin" , gopts));
219210
211+ log->info (0 , " dynamicRoutinesMap[" , plugin_name, " ]: " , dynamicRoutinesMap[plugin_name]);
220212
221- dynamicRoutines2.emplace (plugin_name, manager.LoadAndRegisterObjectFromLibrary <GDynamicDigitization>(
222- " test_gdynamic_plugin" , gopts));
223213
224- log->info (0 , " dynamicRoutines[" , plugin_name, " ]: " , dynamicRoutines[plugin_name]);
225- log->info (0 , " dynamicRoutines2[" , plugin_name, " ]: " , dynamicRoutines2[plugin_name]);
226-
227- if (dynamicRoutines[plugin_name]->loadConstants (1 , " default" ) == false ) {
228- log->error (1 , " Failed to load constants for dynamic routine 'test' for run number 1 with variation 'default'." );
229- }
230- if (dynamicRoutines2[plugin_name]->loadConstants (1 , " default" ) == false ) {
214+ if (dynamicRoutinesMap[plugin_name]->loadConstants (1 , " default" ) == false ) {
231215 log->error (1 , " Failed to load constants for dynamic routine 'test' for run number 1 with variation 'default'." );
232216 }
233217
234218 // Freeze the map before passing it to worker threads
235219 // unordered_map is read-only the entire time the event threads run, and the C ++standard
236220 // guarantees that concurrent reads on a const container are safe so long as no thread mutates it
237- const auto & dynRoutinesConst = dynamicRoutines; // const reference
221+ const auto & dynRoutinesConstMap = dynamicRoutinesMap; // const reference
222+
223+
224+ // gstreamer plugin manager
225+ std::unordered_map<std::string, std::shared_ptr<GStreamer>> gstreamersMap;
226+
227+ auto goutput_defs = gstreamer::getGStreamerDefinition (gopts);
228+
229+ if (goutput_defs.size () > 0 ) {
230+ for (auto & goutput_def : goutput_defs) {
231+ std::string gstreamer_plugin = goutput_def.gstreamerPluginName ();
232+ gstreamersMap.emplace (gstreamer_plugin,
233+ manager.LoadAndRegisterObjectFromLibrary <GStreamer>(gstreamer_plugin, gopts));
234+ log->info (0 , " gstreamersMap[" , gstreamer_plugin, " ]: " , gstreamersMap[gstreamer_plugin]);
235+ gstreamersMap[gstreamer_plugin]->define_gstreamer (goutput_def);
236+ if (!gstreamersMap[gstreamer_plugin]->openConnection ()) {
237+ log->error (1 , " Failed to open connection for gstreamer plugin '" , gstreamer_plugin, " '." );
238+ return EXIT_FAILURE ;
239+ }
240+ }
241+ }
242+
243+ const auto & gstreamerFactoryMap = gstreamersMap; // const reference
238244
239245 constexpr int nevents = 20 ;
240246 constexpr int nthreads = 8 ;
241247
242- run_simulation (nevents, nthreads, loge, logt, dynamicRoutines2 );
248+ run_simulation (nevents, nthreads, loge, loge, dynRoutinesConstMap, runData, runDataMtx );
243249
244250 log->info (0 , " Finished processing " , runData.size (), " events." );
245251
0 commit comments