@@ -82,8 +82,16 @@ static thread_local xpti_tracepoint_t *g_tls_tracepoint_scope_data;
82
82
// / Default stream for the trace framework, if none is provided by the user.
83
83
constexpr const char *g_default_stream = " xpti.framework" ;
84
84
85
+ // / @brief Flag to ensure the default stream is initialized only once.
86
+ // / @details Used with `std::call_once` to initialize the default stream in a
87
+ // / thread-safe manner.
85
88
static std::once_flag g_initialize_default_stream_flag;
86
89
90
+ // / @brief Flag to ensure the default stream is finalized only once.
91
+ // / @details Used with `std::call_once` to finalize the default stream in a
92
+ // / thread-safe manner.
93
+ static std::once_flag g_finalize_default_stream_flag;
94
+
87
95
namespace xpti {
88
96
// / @var env_subscribers
89
97
// / @brief A constant character pointer initialized with the string
@@ -1379,15 +1387,15 @@ class Notifications {
1379
1387
// / @brief Maps a trace type to its associated callback entries.
1380
1388
// / @details This unordered map uses a uint16_t as the key to represent the
1381
1389
// / trace point type, and cb_entries_t to store the associated callbacks.
1382
- using cb_t = std::unordered_map <uint16_t , cb_entries_t >;
1390
+ using cb_t = emhash7::HashMap <uint16_t , cb_entries_t >;
1383
1391
1384
1392
// / @typedef stream_cb_t
1385
1393
// / @brief Maps a stream ID to its corresponding callbacks for different
1386
1394
// / trace types
1387
1395
// / @details This unordered map uses a uint16_t as the key for the stream
1388
1396
// / ID, and cb_t to map the stream to registered callbacks for each trace
1389
1397
// / type
1390
- using stream_cb_t = std::unordered_map <uint16_t , cb_t >;
1398
+ using stream_cb_t = emhash7::HashMap <uint16_t , cb_t >;
1391
1399
1392
1400
// / @typedef statistics_t
1393
1401
// / @brief Keeps track of statistics, typically counts, associated with
@@ -1396,13 +1404,13 @@ class Notifications {
1396
1404
// / the type of statistical data and usually not defined by default. To
1397
1405
// / enable it, XPTI_STATISTICS has to be defined while compiling the
1398
1406
// / frmaework library.
1399
- using statistics_t = std::unordered_map <uint16_t , uint64_t >;
1407
+ using statistics_t = emhash7::HashMap <uint16_t , uint64_t >;
1400
1408
// / @typedef trace_flags_t
1401
1409
// / @brief Maps an trace type to a boolean flag indicating its state.
1402
1410
// / @details This unordered map uses a uint16_t as the key for the trace
1403
1411
// / type, and a boolean value to indicate whether callbacks are registered
1404
1412
// / for this trace type (e.g., registered or unregisterted/no callback).
1405
- using trace_flags_t = std::unordered_map <uint16_t , bool >;
1413
+ using trace_flags_t = emhash7::HashMap <uint16_t , bool >;
1406
1414
1407
1415
// / @typedef stream_flags_t
1408
1416
// / @brief Maps a stream ID to its corresponding trace flags for different
@@ -1411,7 +1419,7 @@ class Notifications {
1411
1419
// / and trace_flags_t to map the trace type to their boolean that indiciates
1412
1420
// / whether a callback has been registered for this trace type in the given
1413
1421
// / stream.
1414
- using stream_flags_t = std::unordered_map <uint8_t , trace_flags_t >;
1422
+ using stream_flags_t = emhash7::HashMap <uint8_t , trace_flags_t >;
1415
1423
1416
1424
// / @brief Registers a callback function for a specific trace type and stream
1417
1425
// / ID.
@@ -2290,6 +2298,9 @@ class Framework {
2290
2298
}
2291
2299
2292
2300
static Framework &instance () {
2301
+ // Using std::call_once has the same overhead as the original approach
2302
+ // std::call_once(g_initialize_framework_flag,
2303
+ // [&]() { MInstance = new Framework(); });
2293
2304
Framework *TmpFramework = MInstance.load (std::memory_order_relaxed);
2294
2305
std::atomic_thread_fence (std::memory_order_acquire);
2295
2306
if (TmpFramework == nullptr ) {
@@ -2309,6 +2320,11 @@ class Framework {
2309
2320
friend void ::xptiFrameworkFinalize ();
2310
2321
2311
2322
static void release () {
2323
+ // Using std::call_once has the same overhead as the original approach
2324
+ // std::call_once(g_release_framework_flag, [&]() {
2325
+ // delete MInstance;
2326
+ // MInstance = nullptr;
2327
+ // });
2312
2328
Framework *TmpFramework = MInstance.load (std::memory_order_relaxed);
2313
2329
MInstance.store (nullptr , std::memory_order_relaxed);
2314
2330
delete TmpFramework;
@@ -2482,7 +2498,10 @@ XPTI_EXPORT_API xpti::result_t xptiInitialize(const char *Stream, uint32_t maj,
2482
2498
// / when the stream is no longer in use.
2483
2499
2484
2500
XPTI_EXPORT_API void xptiFinalize (const char *Stream) {
2485
- xpti::Framework::instance ().finalizeStream (Stream);
2501
+ auto &FW = xpti::Framework::instance ();
2502
+ std::call_once (g_finalize_default_stream_flag,
2503
+ [&]() { FW.finalizeStream (g_default_stream); });
2504
+ FW.finalizeStream (Stream);
2486
2505
}
2487
2506
2488
2507
// / @brief Retrieves the 64-bit universal ID for the current scope, if published
0 commit comments