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