libcwdversion 2.0.0
The C++ Debugging Support Library
Loading...
Searching...
No Matches
LibcwdForAllDebugChannels.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2000-2005, 2018, 2020, 2023, 2026 Carlo Wood
2// SPDX-License-Identifier: MIT
3
4#pragma once
5
9
10#ifndef LIBCWD_MACRO_FORALLDEBUGCHANNELS_H
11#define LIBCWD_MACRO_FORALLDEBUGCHANNELS_H
12
13#include "control_flag.h"
14#include "LIBCWD_ASSERT.h"
15#include "libcwd/config.h"
16
17#include <type_traits>
18
19//===================================================================================================
20// Macro ForAllDebugChannels
21//
22
23namespace libcwd {
24
25class Channel;
26class FatalChannel;
27
28#ifndef HIDE_FROM_DOXYGEN
29namespace _private_ {
30
31struct DebugChannels
32{
33 using callback_type = void (*)(Channel&, void*);
34
35 struct Impl;
36 Impl* impl; // Deliberately leaked.
37
38 static DebugChannels const& instance();
39
40 // Return the channel whose label starts with label and is lexicographically largest among matches.
41 //
42 // The registry is read-locked while scanning. A null pointer is returned when no registered channel
43 // matches the requested prefix.
44 Channel* find(char const* label) const;
45
46 // Initialize channel and optionally add it to the public ForAllDebugChannels registry.
47 //
48 // The registry write lock is held while WST_max_len, channel labels, and the sorted registry are
49 // updated so concurrent global-channel initialization cannot observe a partially updated label width.
50 void initialize_channel(Channel& channel, char const* label, LIBCWD_TSD_PARAM, bool add_to_channel_list) const;
51
52 // Initialize a built-in fatal channel without adding it to the public channel registry.
53 //
54 // The function updates the shared label width while holding the same write lock used for normal
55 // channel registration. The fatal channel itself remains write-once/read-mostly state.
56 void initialize_fatal_channel(FatalChannel& channel, char const* label,
57 control_flag_t maskbit) const;
58
59 // Invoke func for each public debug channel currently registered in the registry.
60 //
61 // A read lock is held until all callbacks have returned. The callback receives debugChannel as a
62 // Channel reference; it must not try to register another debug channel while iterating.
63 template <typename Func>
64 void for_each(Func&& func) const
65 {
66 using func_type = std::remove_reference_t<Func>;
67 for_each_impl([](Channel& debugChannel, void* data) { (*static_cast<func_type*>(data))(debugChannel); }, &func);
68 }
69
70 void for_each_impl(callback_type callback, void* data) const;
71};
72
73static_assert(std::is_trivial_v<DebugChannels>, "DebugChannels must be trivial to survive static destruction");
74
75} // namespace _private_
76#endif // HIDE_FROM_DOXYGEN
77
78} // namespace libcwd
79
80#define LibcwdForAllDebugChannels(dc_namespace, ...) \
81 do \
82 { \
83 ::libcwd::_private_::DebugChannels::instance().for_each([&](::libcwd::Channel& debugChannel) { \
84 using namespace ::libcwd; \
85 using namespace ::dc_namespace; \
86 { \
87 __VA_ARGS__; \
88 } \
89 }); \
90 } while (0)
91
92#endif // LIBCWD_MACRO_FORALLDEBUGCHANNELS_H
This object represents a debug channel, it has a fixed label. A debug channel can be viewed upon as a...
Definition Channel.h:74
namespace for libcwd.