Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Instrument.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Framework_SystemPerformance_Instrument_h_
5#define _Stroika_Framework_SystemPerformance_Instrument_h_ 1
6
7#include "Stroika/Frameworks/StroikaPreComp.h"
8
9#include <compare>
10#include <memory>
11
12#include "Stroika/Foundation/Common/Property.h"
13#include "Stroika/Foundation/Containers/Mapping.h"
14#include "Stroika/Foundation/Containers/Set.h"
16#include "Stroika/Foundation/DataExchange/ObjectVariantMapper.h"
19#include "Stroika/Frameworks/SystemPerformance/Measurement.h"
20#include "Stroika/Frameworks/SystemPerformance/MeasurementSet.h"
21
22/**
23 */
24
25namespace Stroika::Frameworks::SystemPerformance {
26
27 using namespace Stroika::Foundation;
30 using Containers::Set;
32
33// for MSVC - C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\WDBGEXTS.H
34#ifdef GetContext
35#undef GetContext
36#endif
37#ifdef SetContext
38#undef SetContext
39#endif
40
41 /**
42 * @todo - consider using independent atom registry
43 */
44 using InstrumentNameType = DataExchange::Atom<>;
45
46 /**
47 * \brief An Instrument is a stateful object from which you can Capture () a series of measurements about a system.
48 *
49 * \note Design Note
50 * Each instrument instance MAY maintain 'shared state' - that affects subsequent calls. For example, for instruments
51 * that measure data over a period of time (like average CPU usage over a time interval) - they may maintain
52 * state, and return an average over the time since the last call to this instrument instance.
53 *
54 * When copying instruments, this shared state remains shared. To break that share, use this.context = nullptr;
55 *
56 * \note Design Note
57 * Averages captured by instruments are generally relative to the capture interval (time between captures)
58 * among all instruments sharing a shared context.
59 *
60 * Though this time can be controlled otherwise, the easiest way is via the CaptureSet 'RunPeriod'
61 *
62 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
63 * o Standard Stroika Comparison support (operator<=>,operator==, etc);
64 *
65 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
66 * (but note that the shared state is internally synchronized); but you still must externally synchronize
67 * access to all instrument non-const methods.
68 */
69 class Instrument {
70 public:
71 /**
72 * This is a base type for capture contexts. Actual contexts will contain more information
73 * relevant to that Instrument (but all private). All users of Instruments can control is, when
74 * copying an instrument, which ones shared context.
75 *
76 * \note \em Thread-Safety <a href="Thread-Safety.md#Internally-Synchronized-Thread-Safety">Internally-Synchronized-Thread-Safety</a>
77 * More importantly, this is a requirement on all subclasses of the capture context
78 */
80 public:
81 virtual ~ICaptureContext () = default;
82 };
83
84 public:
85 /**
86 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
87 */
88 class IRep {
89 public:
90 virtual ~IRep () = default;
91 virtual MeasurementSet Capture () = 0;
92 virtual unique_ptr<IRep> Clone () const = 0;
93 virtual shared_ptr<ICaptureContext> GetContext () const = 0;
94 virtual void SetContext (const shared_ptr<ICaptureContext>& context) = 0;
95 };
96
97 public:
98 /**
99 */
100 Instrument () = delete;
101 Instrument (Instrument&& src) noexcept;
102 Instrument (const Instrument& src);
103 Instrument (InstrumentNameType instrumentName, unique_ptr<IRep>&& capturer, const Set<MeasurementType>& capturedMeasurements,
105
106 public:
107 nonvirtual Instrument& operator= (Instrument&& rhs) noexcept;
108 nonvirtual Instrument& operator= (const Instrument& rhs);
109
110 public:
111 /**
112 * This can return multiple measurements, of different types, but typically will return a single measurement (with multiple name/value pairs).
113 */
114 nonvirtual MeasurementSet Capture ();
115
116 public:
117 /**
118 * Require just one measurement? This can be simpler, but generally better to use Capturer class, at least if
119 * doing a sequence of measurements (so they come in regularly spaced time intervals).
120 */
121 template <typename T>
122 nonvirtual T CaptureOneMeasurement (Range<TimePointSeconds>* measurementTimeOut = nullptr);
123
124 public:
125 /**
126 * The particular types you can convert a measurement to are defined by each subtype of instrument. Typically they are
127 * that instruments "Info" field, but sometimes a given Instrument will generate multiple MeasurementTypes, and will allow
128 * additional conversions.
129 *
130 * If the required MeasurementType is missing from m, nullopt is returned.
131 */
132 template <typename T>
133 nonvirtual T MeasurementAs (const Measurement& m) const;
134 template <typename T>
135 nonvirtual optional<T> MeasurementAs (const MeasurementSet& m) const;
136
137 public:
138 /**
139 * When you copy an Instrument, by default it remains linked to its source for some of its shared (averaging) data.
140 * to break that context link, set this context to nullptr, and it automatically creates a new context.
141 * Get() here - always returns non-null. But - its an opaque type, so not terribly useful, except to assign nullptr.
142 * It is ILLEGAL (Required) that any arguments ASSIGNED to the context be either nullptr or of the exact dynamic
143 * type used by the given Instrument (so copied from an earlier version of this instrument or something known to be
144 * of the same type).
145 */
147
148 public:
149 /**
150 * @brief Instruments all have a displayable name which can be used for reference. Each (type) instrument should have a unique.
151 */
153
154 public:
155 /**
156 * \brief the set of MeasurementTypes measured by this instrument (often just one)
157 *
158 * \post capturedMeasurementTypes ().size () >= 1
159 */
161
162 public:
163 /**
164 * \brief mapper for all the types listed in type2MeasurementTypes().Values (), as well as any required support types.
165 */
167
168 public:
169 /**
170 * @brief Many (all) instruments will have corresponding c++ objects to represent what is captured. Typically
171 * this entry will have only one entry, but multiple types could be supported. This MAY not represent all
172 * measurement types supported by this instrument (that is some may not have a C++ struct equivalent)
173 */
175
176 public:
177 /**
178 */
179 nonvirtual bool operator== (const Instrument& rhs) const;
180
181 public:
182 /**
183 */
184 nonvirtual strong_ordering operator<=> (const Instrument& rhs) const
185 {
186 return fInstrumentName_ <=> rhs.fInstrumentName_;
187 }
188
189 private:
190 InstrumentNameType fInstrumentName_;
191 Mapping<type_index, MeasurementType> fType2MeasurementTypes_;
192 Set<MeasurementType> fCapturedMeasurementTypes_;
193 DataExchange::ObjectVariantMapper fObjectVariantMapper_;
194 unique_ptr<IRep> fCaptureRep_;
195 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex fThisAssertExternallySynchronized_;
196 };
197
198}
199
200/*
201 ********************************************************************************
202 ***************************** Implementation Details ***************************
203 ********************************************************************************
204 */
205#include "Instrument.inl"
206
207#endif /*_Stroika_Framework_SystemPerformance_Instrument_h_*/
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
Definition Realtime.h:82
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
Definition Set.h:105
An Atom is like a String, except that its much cheaper to copy/store/compare, and the semantics of co...
Definition Atom.h:133
ObjectVariantMapper can be used to map C++ types to and from variant-union types, which can be transp...
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
An Instrument is a stateful object from which you can Capture () a series of measurements about a sys...
Definition Instrument.h:69
Common::ReadOnlyProperty< Mapping< type_index, MeasurementType > > type2MeasurementTypes
Many (all) instruments will have corresponding c++ objects to represent what is captured....
Definition Instrument.h:174
Common::ReadOnlyProperty< DataExchange::ObjectVariantMapper > objectVariantMapper
mapper for all the types listed in type2MeasurementTypes().Values (), as well as any required support...
Definition Instrument.h:166
Common::ReadOnlyProperty< Set< MeasurementType > > capturedMeasurementTypes
the set of MeasurementTypes measured by this instrument (often just one)
Definition Instrument.h:160
nonvirtual T MeasurementAs(const Measurement &m) const
Common::Property< shared_ptr< ICaptureContext > > context
Definition Instrument.h:146
nonvirtual T CaptureOneMeasurement(Range< TimePointSeconds > *measurementTimeOut=nullptr)
Common::ReadOnlyProperty< InstrumentNameType > instrumentName
Instruments all have a displayable name which can be used for reference. Each (type) instrument shoul...
Definition Instrument.h:152