gdynamicDigitization
Loading...
Searching...
No Matches
plugin_load_example.cc
Go to the documentation of this file.
1
2
3// example on how to use the gdynamic library
4
5// gdynamic
8
9// gemc
10#include "gfactory.h"
11#include "event/gEventDataCollection.h"
12#include "gthreads.h"
13
14const std::string plugin_name = "test_gdynamic_plugin";
15
17 int nthreads,
18 const std::shared_ptr<GOptions>& gopt,
19 const std::shared_ptr<GLogger>& log,
20 const std::shared_ptr<const gdynamicdigitization::dRoutinesMap>& dynamicRoutinesMap) -> std::vector<std::unique_ptr<GEventDataCollection>> {
21 std::mutex collectorMtx;
22 std::vector<std::unique_ptr<GEventDataCollection>> collected;
23
24 // thread-safe integer counter starts at 1.
25 // fetch_add returns the old value *and* bumps.
26 // zero contention: each thread fetches the next free event number.
27 std::atomic<int> next{1};
28
29 // pool of jthreads. jthread joins in its destructor so we don’t need an
30 // explicit loop at the end.
31 // each element represents one worker thread running your event-processing lambda.
32 // std::vector<std::jthread> pool; use this when C++20 is widely available
33 std::vector<jthread_alias> pool; // was std::vector<std::jthread>
34
35 pool.reserve(nthreads);
36
37 for (int tid = 0; tid < nthreads; ++tid) {
38 // The capture [&, tid] gives the thread references to variables like tid
39 pool.emplace_back([&, tid] // capture tid *by value*
40 {
41 // start the thread with a lambda
42 log->info(0, "worker ", tid, " started");
43
44 int localCount = 0; // events built by *this* worker
45 thread_local std::vector<std::unique_ptr<GEventDataCollection>> localRunData;
46
47 while (true) {
48 // repeatedly asks the shared atomic counter for “the next unclaimed event
49 // number,” processes that event, stores the result, and goes back for more.
50 // memory_order_relaxed: we only need *atomicity*, no ordering
51 int evn = next.fetch_add(1, std::memory_order_relaxed); // atomically returns the current value and increments it by 1.
52 if (evn > nevents) break; // exit the while loop
53
54 auto gheader = GEventHeader::create(gopt);
55 auto eventData = std::make_unique<GEventDataCollection>(gopt, std::move(gheader));
56
57 // each event has 2 hits
58 for (unsigned i = 1; i < 3; i++) {
59 auto hit = GHit::create(gopt);
60 auto true_data = dynamicRoutinesMap->at(plugin_name)->collectTrueInformation(hit, i);
61 auto digi_data = dynamicRoutinesMap->at(plugin_name)->digitizeHit(hit, i);
62
63 eventData->addDetectorDigitizedData("ctof", std::move(digi_data));
64 eventData->addDetectorTrueInfoData("ctof", std::move(true_data));
65 }
66
67 log->info(0, "worker ", tid, " event ", evn, " has ", eventData->getDataCollectionMap().at("ctof")->getDigitizedData().size(), " digitized hits");
68
69 localRunData.emplace_back(std::move(eventData));
70
71 ++localCount; // tally for this worker
72 }
73
74 // braces: locks the mutex when it's constructed and unlocks it when destroyed
75 {
76 std::scoped_lock lk(collectorMtx);
77 for (auto& evt : localRunData) {
78 // only collect 2 events total so that the log doesn't go crazy with the destructor
79 if (collected.size() >= 2) break;
80 collected.emplace_back(std::move(evt));
81 }
82 localRunData.clear();
83 }
84
85 log->info(0, "worker ", tid, " processed ", localCount, " events");
86 }); // jthread constructor launches the thread immediately
87 } // pool’s destructor blocks until every jthread has joined
88 return collected;
89}
90
91
92// emulation of a run of events, collecting data in separate threads
93
94
95int main(int argc, char* argv[]) {
96 // Create GOptions using gdata::defineOptions, which aggregates options from gdata and gtouchable.
97 auto gopts = std::make_shared<GOptions>(argc, argv, gdynamicdigitization::defineOptions());
98
99 // duplicate plugin logger here
100 auto log = std::make_shared<GLogger>(gopts, SFUNCTION_NAME, PLUGIN_LOGGER);
101
102 constexpr int nevents = 10;
103 constexpr int nthreads = 8;
104
105 auto dynamicRoutinesMap = gdynamicdigitization::dynamicRoutinesMap({plugin_name}, gopts);
106 if (dynamicRoutinesMap->at(plugin_name)->loadConstants(1, "default") == false) {
107 log->error(1, "Failed to load constants for dynamic routine", plugin_name, "for run number 1 with variation 'default'.");
108 }
109
110 auto runData = run_simulation_in_threads(nevents, nthreads, gopts, log, dynamicRoutinesMap);
111
112 // For demonstration, we'll simply print the event numbers.
113 for (size_t i = 0; i < runData.size(); i++) { log->info(" > Event ", i + 1, " collected with local event number: ", runData[i]->getEventNumber()); }
114
115 return EXIT_SUCCESS;
116}
Defines the options for the GDynamicDigitization module.
GOptions defineOptions()
Returns an array of options definitions for the GDynamicDigitization module.
std::shared_ptr< const dRoutinesMap > dynamicRoutinesMap(const std::vector< std::string > &plugin_names, const std::shared_ptr< GOptions > &gopts)
int main(int argc, char *argv[])
const std::string plugin_name
auto run_simulation_in_threads(int nevents, int nthreads, const std::shared_ptr< GOptions > &gopt, const std::shared_ptr< GLogger > &log, const std::shared_ptr< const gdynamicdigitization::dRoutinesMap > &dynamicRoutinesMap) -> std::vector< std::unique_ptr< GEventDataCollection > >