Skip to content

Commit f827ba8

Browse files
committed
conforming gstreamer to gfactory class
1 parent e459cf3 commit f827ba8

37 files changed

Lines changed: 298 additions & 219 deletions

gdynamicDigitization/gdynamicdigitization.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ class GTouchableModifiers {
4949

5050
public:
5151
/**
52-
* \brief Inserts a new (id, weight) pair for a given touchable.
52+
* \brief Inserts a new (id, weight) pair for given touchable.
5353
* \param touchableName The name of the touchable.
5454
* \param idValue The identifier value.
5555
* \param weight The weight.
5656
*/
5757
void insertIdAndWeight(std::string touchableName, int idValue, double weight);
5858

5959
/**
60-
* \brief Inserts a new (id, weight, time) triplet for a given touchable.
60+
* \brief Inserts a new (id, weight, time) triplet for given touchable.
6161
* \param touchableName The name of the touchable.
6262
* \param idValue The identifier value.
6363
* \param weight The weight.
@@ -207,8 +207,7 @@ class GDynamicDigitization {
207207
digi_logger->debug(NORMAL, "GDynamicDigitization::load constants");
208208
return loadConstantsImpl(runno, variation);
209209
}
210-
211-
[[nodiscard]] virtual bool loadConstantsImpl([[maybe_unused]] int runno, [[maybe_unused]] std::string const& variation) { return false; }
210+
virtual bool loadConstantsImpl([[maybe_unused]] int runno, [[maybe_unused]] std::string const& variation) { return false; }
212211

213212
/**
214213
* \brief Loads the translation table.
@@ -223,7 +222,7 @@ class GDynamicDigitization {
223222
return loadTTImpl(runno, variation);
224223
}
225224

226-
[[nodiscard]] virtual bool loadTTImpl([[maybe_unused]] int runno, [[maybe_unused]] std::string const& variation) { return false; }
225+
virtual bool loadTTImpl([[maybe_unused]] int runno, [[maybe_unused]] std::string const& variation) { return false; }
227226

228227
/**
229228
* \brief Sets hardware-level charge and time information in the digitized data.
@@ -251,7 +250,7 @@ class GDynamicDigitization {
251250
digi_logger->debug(NORMAL, "GDynamicDigitization::define readout specs");
252251
return defineReadoutSpecsImpl();
253252
};
254-
[[nodiscard]] virtual bool defineReadoutSpecsImpl() = 0;
253+
virtual bool defineReadoutSpecsImpl() = 0;
255254

256255
/// After init, we never mutate these:
257256
std::shared_ptr<const GReadoutSpecs> readoutSpecs;
@@ -283,9 +282,9 @@ class GDynamicDigitization {
283282
*/
284283
void set_loggers(GOptions* const g) {
285284
gopts = g;
286-
data_logger = std::make_shared<GLogger>(gopts.value(), DATA_LOGGER, "data logger");
287-
tt_logger = std::make_shared<GLogger>(gopts.value(), TRANSLATIONTABLE_LOGGER, "tt logger");
288-
digi_logger = std::make_shared<GLogger>(gopts.value(), GDIGITIZATION_LOGGER, "digi logger");
285+
data_logger = std::make_shared<GLogger>(gopts.value(), DATA_LOGGER, "data");
286+
tt_logger = std::make_shared<GLogger>(gopts.value(), TRANSLATIONTABLE_LOGGER, "translation table");
287+
digi_logger = std::make_shared<GLogger>(gopts.value(), GDIGITIZATION_LOGGER, "digitization");
289288
}
290289

291290
protected:

gdynamicDigitization/greadoutSpecs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,10 @@ class GReadoutSpecs {
8989
*/
9090
[[nodiscard]] inline int timeCellIndex(double time) const { return static_cast<int>(std::floor((time - gridStartTime) / timeWindow) + 1); }
9191
};
92+
93+
94+
#include <type_traits>
95+
96+
// At compile time, make sure GReadoutSpecs has trivial destructors,
97+
static_assert(std::is_trivially_destructible_v<GReadoutSpecs>);
98+

gfactory/gfactory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ T* GManager::LoadAndRegisterObjectFromLibrary(std::string_view name, GOptions *g
135135
auto factory = T::instantiate(dynamicLib->handle);
136136
// in c++20 it is possible to use introspection with concept thuse removing the
137137
// need of having to define a set_loggers function
138-
// it didn't work on 5/21/2025 so for now the function is required
138+
// it didn't work on 5/21/2025 so for now the function is required to be defined
139139
factory->set_loggers(gopts);
140140
return factory;
141141
}

goptions/goptions.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ GOptions::GOptions(int argc, char *argv[], const GOptions &user_defined_options)
110110
if (eqPos != string::npos) {
111111
string keyPart = argStr.substr(0, eqPos);
112112
string valuePart = argStr.substr(eqPos + 1);
113+
114+
// Strip outer quotes if present (e.g., -gstreamer="[...]")
115+
if (!valuePart.empty() && valuePart.front() == '"' && valuePart.back() == '"') {
116+
valuePart = valuePart.substr(1, valuePart.length() - 2);
117+
}
118+
113119
size_t dotPos = keyPart.find('.');
114120
if (dotPos != string::npos) {
115121
// Dot–notation detected (e.g. "debug.general=true")

gparticle/meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# expat needed because g4processes
22
sub_dir_name = meson.current_source_dir().split('/').get(-1)
3-
single = '-gparticle="[{name: e-, p: 2300, theta: 23.0}"'
3+
single = '-gparticle="[{name: e-, p: 2300, theta: 23.0}]"'
44
double = '-gparticle="[{name: e-, p: 2300, theta: 23.0}, {name: proton, multiplicity: 2, p: 1200, theta: 14.0, delta_theta: 10}]"'
55
LD += {
66
'name' : sub_dir_name,

gstreamer/examples/gstreamer_example.cc

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
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
1212
const 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

199185
int 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

gstreamer/factories/ASCII/event/event.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include "../gstreamerASCIIFactory.h"
33
#include "gstreamerConventions.h"
44

5-
bool GstreamerTextFactory::startEvent(const GEventDataCollection* eventData, const std::shared_ptr<GLogger>& log) {
5+
bool GstreamerTextFactory::startEventImpl(const GEventDataCollection* eventData) {
66
if (ofile == nullptr) { log->error(ERR_CANTOPENOUTPUT, "Error: can't open ", ofile); }
77

88
auto eventNumber = eventData->getHeader()->getG4LocalEvn();
@@ -12,7 +12,7 @@ bool GstreamerTextFactory::startEvent(const GEventDataCollection* eventData, con
1212
}
1313

1414

15-
bool GstreamerTextFactory::endEvent(const GEventDataCollection* eventData, const std::shared_ptr<GLogger>& log) {
15+
bool GstreamerTextFactory::endEventImpl(const GEventDataCollection* eventData) {
1616
if (ofile == nullptr) { log->error(ERR_CANTOPENOUTPUT, "Error: can't open ", ofile); }
1717

1818
int eventNumber = eventData->getHeader()->getG4LocalEvn();

gstreamer/factories/ASCII/event/eventHeader.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include "../gstreamerASCIIFactory.h"
33
#include "gstreamerConventions.h"
44

5-
bool GstreamerTextFactory::publishEventHeader(const GEventDataCollectionHeader *gheader, std::shared_ptr<GLogger>& log)
5+
bool GstreamerTextFactory::publishEventHeaderImpl(const GEventDataCollectionHeader *gheader)
66
{
77
if (ofile == nullptr) { log->error(ERR_CANTOPENOUTPUT, "Error: can't open ", ofile); }
88

gstreamer/factories/ASCII/event/publishDigitized.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
#include "../gstreamerASCIIFactory.h"
33
#include "gstreamerConventions.h"
44

5-
bool GstreamerTextFactory::publishEventDigitizedData(const std::string detectorName,
6-
const std::vector<GDigitizedData*>* digitizedData,
7-
std::shared_ptr<GLogger>& log) {
5+
bool GstreamerTextFactory::publishEventDigitizedDataImpl(const std::string detectorName,
6+
const std::vector<GDigitizedData*>* digitizedData) {
87
if (ofile == nullptr) { log->error(ERR_CANTOPENOUTPUT, "Error: can't open ", ofile); }
98

109
*ofile << GTAB << "Detector <" << detectorName << "> Digitized Bank {" << std::endl;

gstreamer/factories/ASCII/event/publishTrueInfo.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
#include "../gstreamerASCIIFactory.h"
33
#include "gstreamerConventions.h"
44

5-
bool GstreamerTextFactory::publishEventTrueInfoData(const std::string detectorName,
6-
const std::vector<GTrueInfoData*>* trueInfoData,
7-
std::shared_ptr<GLogger>& log) {
5+
bool GstreamerTextFactory::publishEventTrueInfoDataImpl(const std::string detectorName,
6+
const std::vector<GTrueInfoData*>* trueInfoData) {
87
if (ofile == nullptr) { log->error(ERR_CANTOPENOUTPUT, "Error: can't open ", ofile); }
98

109
*ofile << GTAB << "Detector <" << detectorName << "> True Info Bank {" << std::endl;

0 commit comments

Comments
 (0)