BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balm_category.h
Go to the documentation of this file.
1/// @file balm_category.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balm_category.h -*-C++-*-
8#ifndef INCLUDED_BALM_CATEGORY
9#define INCLUDED_BALM_CATEGORY
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: balm_category.h,v 1.4 2008/04/16 20:00:49 hversche Exp $")
13
14/// @defgroup balm_category balm_category
15/// @brief Provide a representation of a metric category.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balm
19/// @{
20/// @addtogroup balm_category
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balm_category-purpose"> Purpose</a>
25/// * <a href="#balm_category-classes"> Classes </a>
26/// * <a href="#balm_category-description"> Description </a>
27/// * <a href="#balm_category-alternative-systems-for-telemetry"> Alternative Systems for Telemetry </a>
28/// * <a href="#balm_category-thread-safety"> Thread Safety </a>
29/// * <a href="#balm_category-usage"> Usage </a>
30/// * <a href="#balm_category-example-1-basic-usage"> Example 1: Basic Usage </a>
31///
32/// # Purpose {#balm_category-purpose}
33/// Provide a representation of a metric category.
34///
35/// # Classes {#balm_category-classes}
36///
37/// - balm::Category: a representation of a metric category
38///
39/// @see balm_metricregistry, balm_metricid, balm_metricdescription
40///
41/// # Description {#balm_category-description}
42/// This component provides a class, `balm::Category`, whose values
43/// are used to categorize collected metrics. A metric "category" is an
44/// identifier (chosen by the application) that groups together one or more
45/// metrics. A `balm::Category` object contains the address of a string holding
46/// the name of the category and a boolean value indicating whether the
47/// category is currently enabled. The `balm::Category` class suppresses copy
48/// construction and assignment, and does not provide equality operators;
49/// applications should use a *single* `balm::Category` object instance per
50/// category (such as one provided by the *`balm::MetricRegistry`* component).
51///
52/// IMPORTANT: The category name, whose type is `const char *`, must remain
53/// constant and valid throughout the lifetime of the `balm::Category` object.
54///
55/// ## Alternative Systems for Telemetry {#balm_category-alternative-systems-for-telemetry}
56///
57///
58/// Bloomberg software may alternatively use the GUTS telemetry API, which is
59/// integrated into Bloomberg infrastructure.
60///
61/// ## Thread Safety {#balm_category-thread-safety}
62///
63///
64/// `balm::Category` is generally *const* *thread-safe*, meaning that accessors
65/// may be invoked concurrently from different threads, but it is not safe to
66/// access or modify a `balm::Category` in one thread while another thread
67/// modifies the same object. However, it is safe to *access* the `enabled`
68/// property on one (or more) thread(s) while the object is being modified on
69/// another thread.
70///
71/// ## Usage {#balm_category-usage}
72///
73///
74/// This section illustrates intended use of this component.
75///
76/// ### Example 1: Basic Usage {#balm_category-example-1-basic-usage}
77///
78///
79/// The following example demonstrates how to create, access, and modify a
80/// `balm::Category` object. We start by creating three category objects with
81/// different names:
82/// @code
83/// balm::Category categoryA("A", true);
84/// balm::Category categoryB("B", false);
85/// balm::Category categoryC("C");
86/// @endcode
87/// Once the category objects have been created, we can use the `name` and
88/// `enabled` methods to access their values:
89/// @code
90/// assert(0 == bsl::strcmp("A", categoryA.name()));
91/// assert(0 == bsl::strcmp("B", categoryB.name()));
92/// assert(0 == bsl::strcmp("C", categoryC.name()));
93///
94/// assert( categoryA.enabled());
95/// assert(!categoryB.enabled());
96/// assert( categoryC.enabled());
97/// @endcode
98/// Finally, we modify the enablement status of one of the categories, and then
99/// write all three categories to the console:
100/// @code
101/// categoryC.setEnabled(false);
102///
103/// bsl::cout << "categoryA: " << categoryA << bsl::endl
104/// << "categoryB: " << categoryB << bsl::endl
105/// << "categoryC: " << categoryC << bsl::endl;
106/// @endcode
107/// With the resulting console output:
108/// @code
109/// categoryA: [ A ENABLED ]
110/// categoryB: [ B DISABLED ]
111/// categoryC: [ C DISABLED ]
112/// @endcode
113/// @}
114/** @} */
115/** @} */
116
117/** @addtogroup bal
118 * @{
119 */
120/** @addtogroup balm
121 * @{
122 */
123/** @addtogroup balm_category
124 * @{
125 */
126
127#include <balscm_version.h>
128
129#include <bsls_atomic.h>
130#include <bsls_libraryfeatures.h>
131
132#include <bsl_iosfwd.h>
133
134
135
136
137namespace balm {
138
139class CategoryHolder;
140
141 // ==============
142 // class Category
143 // ==============
144
145/// This class provides a mechanism for representing a category. A category
146/// is an identifier used to group related metrics. A `Category` object
147/// contains the address of a null-terminated string, `name`, holding the
148/// name of the category and a boolean value, `enabled`, indicating whether
149/// the category is currently enabled.
150///
151/// See @ref balm_category
152class Category {
153
154 // DATA
155 const char *d_name_p; // name of the category (held, not owned)
156
157 bsls::AtomicInt d_enabled; // whether the category is enabled
158
159 CategoryHolder *d_holders_p; // linked list of holders of this category
160
161 private:
162 // NOT IMPLEMENTED
163 Category(const Category& );
164 Category& operator=(const Category& );
165
166 public:
167 // CREATORS
168
169 /// Create a category having the specified `name` address. Optionally
170 /// specify `enabledFlag`, the enabled status of the category; if
171 /// `enabledFlag` is not specified, the `enabled` status is `true`.
172 ///
173 /// \pre The behavior is undefined unless `name` remains valid and unmodified for
174 /// the lifetime of this object.
175 explicit Category(const char *name, bool enabledFlag = true);
176
177 /// Destroy this category object.
179
180 // MANIPULATORS
181
182 /// Set the name of this metric to the specified `name` address.
183 ///
184 /// \pre The behavior is undefined unless `name` remains valid and unmodified
185 /// for the lifetime of this object.
186 void setName(const char *name);
187
188 /// Set the `enabled` state of this category to the value of the
189 /// specified `enabledFlag` and update any `CategoryHolder` objects registered with this category.
190 ///
191 /// \note Note that this operation is *not*
192 /// atomic, and other threads may simultaneously access the current
193 /// enabled value while this operation is performed. Also note that
194 /// this operation has *linear* performance with respect to the number
195 /// of registered category holders for `category`.
196 void setEnabled(bool enabledFlag);
197
198 /// Load into the specified `holder` the address of this category, its
199 /// `enabled()` status, and the address of the next holder in the
200 /// linked list of category holders maintained by this object
201 /// (prepending `holder` to this category's linked list of category
202 /// holders). This category will update `holder->enabled()` when its
203 /// enabled state changes, and will reset `holder` (i.e.,
204 /// `holder->reset()`) when this category is destroyed.
205 ///
206 /// \pre The behavior is undefined unless `holder` remains valid and *unmodified* (by the
207 /// client) for the lifetime of this object and is *not* registered
208 /// again with any category (including this one).
210
211 // ACCESSORS
212
213 /// Return the address of the non-modifiable null-terminated string
214 /// containing the name of this category.
215 const char *name() const;
216
217 /// Report whether this category is enabled. This function is fully
218 /// thread-safe.
219 bool enabled() const;
220
221 /// Return a *reference* to a const value indicating the enabled status
222 /// of this category, allowing downstream uses to minimize latency by
223 /// avoiding indirection through abstracted interfaces, albeit at some
224 /// risk of object-lifetime violations. The returned reference must not
225 /// be allowed to outlive this category object.
226 const bsls::AtomicInt& isEnabledRaw() const;
227
228 /// Print this category to the specified output `stream` in some human
229 /// readable form, and return the modifiable `stream`.
230 bsl::ostream& print(bsl::ostream& stream) const;
231};
232
233// ============================================================================
234// INLINE DEFINITIONS
235// ============================================================================
236
237// FREE OPERATORS
238
239/// Output a formatted description of the specified `rhs` category to the
240/// specified `stream`, and return the modifiable `stream`.
241inline
242bsl::ostream& operator<<(bsl::ostream& stream, const Category& rhs);
243
244 // ====================
245 // class CategoryHolder
246 // ====================
247
248/// This class, informally referred to as a "category holder" (or simply
249/// "holder"), holds a category, an enabled value, and a pointer to a
250/// "next" holder. Both the category and next pointer may be null. The
251/// intended use is as follows: (1) instances of this class are (only)
252/// declared in contexts where collecting a metric occurs; (2) if the
253/// enabled value is true, the category contains the address of a valid,
254/// enabled, category; (3) if the next pointer is non-null, then the holder
255/// pointed to holds the same category and threshold. Instances of this
256/// class must be *statically* initializable. Hence, the data members are
257/// `public`, and no constructors or destructor are defined.
258///
259/// This class should *not* be used directly by client code. It is an
260/// implementation detail of the `balm` metric collection system.
261///
262/// See @ref balm_category
264
265 private:
266 // NOT IMPLEMENTED
267 CategoryHolder& operator=(const CategoryHolder& rhs);
268
269 public:
270
271 // PUBLIC DATA MEMBERS
272
273#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY
274 bsls::AtomicBool d_enabled; // whether the category
275 // is enabled
276
278 // owned)
279
280 bsls::AtomicPointer<CategoryHolder> d_next_p; // next category holder
281 // in linked list
282#else
283 bool d_enabled; // whether the category is enabled
284 const Category *d_category_p; // held category (not owned)
285 CategoryHolder *d_next_p; // next category holder in linked list
286#endif
287
288 // CREATORS
289
290 // No constructors or destructors are declared in order to allow for static
291 // initialization of instances of this class.
292
293 // MANIPULATORS
294
295 /// Reset this object to its default value. The default value is:
296 /// @code
297 /// { false, 0, 0 }
298 /// @endcode
299 void reset();
300
301 /// Set the address of the category held by this holder to the specified
302 /// `category`.
303 void setCategory(const Category *category);
304
305 /// Set the `enabled` state of this category to the value of the
306 /// specified `enabledFlag`.
307 void setEnabled(bool enabledFlag);
308
309 /// Set this holder to point to the specified `holder`.
310 void setNext(CategoryHolder *holder);
311
312 // ACCESSORS
313
314 /// Return the address of the non-modifiable category held by this
315 /// holder.
316 const Category *category() const;
317
318 /// Return `true` if `category` is valid (i.e., non-null) and enabled,
319 /// and `false` otherwise.
320 bool enabled() const;
321
322 /// Return the address of the modifiable holder pointed to by this
323 /// holder.
324 CategoryHolder *next() const;
325};
326
327// ============================================================================
328// INLINE FUNCTION DEFINITIONS
329// ============================================================================
330
331 // --------------
332 // class Category
333 // --------------
334
335// CREATORS
336inline
337Category::Category(const char *name, bool enabledFlag)
338: d_name_p(name)
339, d_enabled(enabledFlag)
340, d_holders_p(0)
341{
342}
343
344// MANIPULATORS
345inline
346void Category::setName(const char *name)
347{
348 d_name_p = name;
349}
350
351// ACCESSORS
352inline
353const char *Category::name() const
354{
355 return d_name_p;
356}
357
358inline
360{
361 return d_enabled;
362}
363
364inline
366{
367 return d_enabled;
368}
369
370 // --------------------
371 // class CategoryHolder
372 // --------------------
373
374// MANIPULATORS
375inline
377{
379}
380
381inline
382void CategoryHolder::setEnabled(bool enabledFlag)
383{
384 d_enabled = enabledFlag;
385}
386
387inline
389{
390 d_next_p = holder;
391}
392
393// ACCESSORS
394inline
396{
397 return d_category_p;
398}
399
400inline
402{
403 return d_enabled;
404}
405
406inline
408{
409 return d_next_p;
410}
411} // close package namespace
412
413// FREE OPERATORS
414inline
415bsl::ostream& balm::operator<<(bsl::ostream& stream, const Category& rhs)
416{
417 return rhs.print(stream);
418}
419
420
421
422#endif
423
424// ----------------------------------------------------------------------------
425// Copyright 2015 Bloomberg Finance L.P.
426//
427// Licensed under the Apache License, Version 2.0 (the "License");
428// you may not use this file except in compliance with the License.
429// You may obtain a copy of the License at
430//
431// http://www.apache.org/licenses/LICENSE-2.0
432//
433// Unless required by applicable law or agreed to in writing, software
434// distributed under the License is distributed on an "AS IS" BASIS,
435// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
436// See the License for the specific language governing permissions and
437// limitations under the License.
438// ----------------------------- END-OF-FILE ----------------------------------
439
440/** @} */
441/** @} */
442/** @} */
Definition balm_category.h:263
CategoryHolder * next() const
Definition balm_category.h:407
const Category * category() const
Definition balm_category.h:395
void setEnabled(bool enabledFlag)
Definition balm_category.h:382
bool enabled() const
Definition balm_category.h:401
CategoryHolder * d_next_p
Definition balm_category.h:285
void setNext(CategoryHolder *holder)
Set this holder to point to the specified holder.
Definition balm_category.h:388
const Category * d_category_p
Definition balm_category.h:284
bool d_enabled
Definition balm_category.h:283
void setCategory(const Category *category)
Definition balm_category.h:376
Definition balm_category.h:152
void setName(const char *name)
Definition balm_category.h:346
void registerCategoryHolder(CategoryHolder *holder)
~Category()
Destroy this category object.
const char * name() const
Definition balm_category.h:353
bsl::ostream & print(bsl::ostream &stream) const
bool enabled() const
Definition balm_category.h:359
const bsls::AtomicInt & isEnabledRaw() const
Definition balm_category.h:365
void setEnabled(bool enabledFlag)
Definition bsls_atomic.h:1490
Definition bsls_atomic.h:744
Definition bsls_atomic.h:1362
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition balm_bdlmmetricsadapter.h:142
bsl::ostream & operator<<(bsl::ostream &stream, const Category &rhs)