From de2ad7048ccd8792accb90478eaed024b74c25eb Mon Sep 17 00:00:00 2001 From: smanes0213 Date: Wed, 8 Apr 2026 10:18:19 +0530 Subject: [PATCH 1/4] Add Benchmark COM-RPC interfaces - Add IBenchmark.h: trigger/collectdata/setthreshold APIs with nanosecond latency stats, memory stats, pass/fail thresholds, and PerformanceCheckCompleted event notification - Add IBenchmarkPayloadCOMRPC.h: payload interface for benchmarking various COM-RPC parameter types (uint32, string, structs, buffers) - Update QAIds.h: register interface IDs for IBenchmark, IBenchmarkPayload, and associated iterators Signed-off-by: smanes0213 --- qa_interfaces/IBenchmark.h | 71 +++++++++++++++++++++++ qa_interfaces/IBenchmarkPayloadCOMRPC.h | 76 +++++++++++++++++++++++++ qa_interfaces/QAIds.h | 8 ++- 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 qa_interfaces/IBenchmark.h create mode 100644 qa_interfaces/IBenchmarkPayloadCOMRPC.h diff --git a/qa_interfaces/IBenchmark.h b/qa_interfaces/IBenchmark.h new file mode 100644 index 00000000..9b58bf8c --- /dev/null +++ b/qa_interfaces/IBenchmark.h @@ -0,0 +1,71 @@ +#pragma once + +#include "Module.h" + +// @stubgen:include + +namespace Thunder { +namespace QualityAssurance { + + // @json 1.0.0 @text:legacy_lowercase + struct EXTERNAL IBenchmark : virtual public Core::IUnknown { + enum { ID = ID_BENCHMARK }; + + ~IBenchmark() override = default; + + struct RoundTripStats { + uint64_t minNs; + uint64_t avgNs; + uint64_t maxNs; + uint64_t stddevNs; + }; + + struct MemoryStats { + uint64_t residentBefore; // RSS in bytes before benchmark + uint64_t residentAfter; // RSS in bytes after benchmark + uint64_t allocatedBefore; // Allocated in bytes before benchmark + uint64_t allocatedAfter; // Allocated in bytes after benchmark + }; + + + struct BenchmarkResult { + string apiName; + uint32_t iterations; + + RoundTripStats roundTrip; + MemoryStats memory; + + bool passed; // true if within configured thresholds + string failureReason; // empty if passed, describes which threshold was exceeded + }; + + typedef RPC::IIteratorType IBenchmarkResultIterator; + + // @brief Run the benchmark + // @param iterations: Denotes the number of iterations the benchmark should run + // @param success: True if the benchmark completed successfully + virtual Core::hresult Trigger(const uint32_t iterations, bool& success /* @out */) = 0; + + virtual Core::hresult CollectData(IBenchmarkResultIterator*& report /* @out */) const = 0; + + // @brief Set pass/fail thresholds for benchmark results + // @param maxLatencyDeviationPct: Maximum allowed % deviation in avg latency compared to first-run baseline (0 = no latency check) + // @param maxMemoryGrowthBytes: Maximum allowed RSS growth in bytes per method (0 = no memory check) + // @param success: True if thresholds were set + virtual Core::hresult SetThreshold(const float maxLatencyDeviationPct, const uint64_t maxMemoryGrowthBytes, bool& success /* @out */) = 0; + + // @event + struct EXTERNAL INotification : virtual public Core::IUnknown { + enum { ID = ID_BENCHMARK_NOTIFICATION }; + + ~INotification() override = default; + + virtual void PerformanceCheckCompleted() = 0; + }; + + virtual Core::hresult Register(const IBenchmark::INotification* sink) = 0; + virtual Core::hresult Unregister(const IBenchmark::INotification* sink) = 0; + }; + +} +} \ No newline at end of file diff --git a/qa_interfaces/IBenchmarkPayloadCOMRPC.h b/qa_interfaces/IBenchmarkPayloadCOMRPC.h new file mode 100644 index 00000000..cfd2925e --- /dev/null +++ b/qa_interfaces/IBenchmarkPayloadCOMRPC.h @@ -0,0 +1,76 @@ +#pragma once +#include "Module.h" + +// @stubgen:include + +namespace Thunder { + namespace QualityAssurance { + + + struct SampleData + { + uint32_t id; + uint32_t value; + string name; + }; + + struct EXTERNAL IBenchmarkPayload : virtual public Core::IUnknown + { + enum { ID = ID_BENCHMARK_PAYLOAD }; + + enum PayloadType : uint8_t + { + PAYLOAD_UNKNOWN, + PAYLOAD_SMALL, + PAYLOAD_MEDIUM, + PAYLOAD_LARGE + }; + + typedef RPC::IIteratorType IPayloadTypeIterator; + + virtual uint32_t GetPayloadTypes(IPayloadTypeIterator*& types /* @out */) const = 0; + + virtual uint32_t SendUint16(const uint16_t value) = 0; + + virtual uint32_t SendUint32(const uint32_t value) = 0; + + virtual uint32_t SendUint64(const uint64_t value) = 0; + + virtual uint32_t SendBool(const bool value) = 0; + + virtual uint32_t SendFloat(const float value) = 0; + + virtual uint32_t SendDouble(const double value) = 0; + + virtual uint32_t SendString(const string& value) = 0; + + virtual uint32_t SendSampleData(const SampleData& data) = 0; + + virtual uint32_t SendWithNoParameters() = 0; + + virtual uint32_t SendBuffer(const uint16_t bufferSize, const uint8_t buffer[] /* @length:bufferSize @in */) = 0; + + virtual uint32_t SendReceiveUint16(const uint16_t input, uint16_t &output /* @out */) const = 0; + + virtual uint32_t SendReceiveUint32(const uint32_t input, uint32_t &output /* @out */) const = 0; + + virtual uint32_t SendReceiveUint64(const uint64_t input, uint64_t &output /* @out */) const = 0; + + virtual uint32_t SendReceiveBool(const bool input, bool &output /* @out */) const = 0; + + virtual uint32_t SendReceiveFloat(const float input, float &output /* @out */) const = 0; + + virtual uint32_t SendReceiveDouble(const double input, double &output /* @out */) const = 0; + + virtual uint32_t SendReceiveString(const string &input, string &output /* @out */) const = 0; + + virtual uint32_t SendReceiveSampleData(const SampleData &input, SampleData &output /* @out */) const = 0; + + virtual uint32_t SendReceiveBuffer(uint16_t &bufferSize /* @inout */, uint8_t buffer[] /* @length:bufferSize @inout */) const = 0; + + virtual uint32_t Add(const uint32_t a, const uint32_t b, uint32_t &result /* @out */) const = 0; + + ~IBenchmarkPayload() override = default; + }; +} +} \ No newline at end of file diff --git a/qa_interfaces/QAIds.h b/qa_interfaces/QAIds.h index 08173dc0..403ad713 100644 --- a/qa_interfaces/QAIds.h +++ b/qa_interfaces/QAIds.h @@ -74,8 +74,14 @@ namespace QualityAssurance { ID_TESTKEEP = ID_TESTTEXTOPTIONS + 4, ID_TESTKEEP_NOTIFICATION = ID_TESTTEXTOPTIONS + 5, ID_TESTCUSTOM = ID_TESTTEXTOPTIONS + 6, - ID_TESTCUSTOM_NOTIFICATION = ID_TESTTEXTOPTIONS + 7 + ID_TESTCUSTOM_NOTIFICATION = ID_TESTTEXTOPTIONS + 7, + ID_BENCHMARK = RPC::IDS::ID_EXTERNAL_QA_INTERFACE_OFFSET + 0x040, + ID_BENCHMARK_NOTIFICATION = ID_BENCHMARK + 1, + ID_BENCHMARK_RESULT_ITERATOR = ID_BENCHMARK + 2, + + ID_BENCHMARK_PAYLOAD = RPC::IDS::ID_EXTERNAL_QA_INTERFACE_OFFSET + 0x050, + ID_PAYLOADTYPE_ITERATOR = ID_BENCHMARK_PAYLOAD + 1, }; } } From e1230c258b9355a114fe1306e4490fee5df9d529 Mon Sep 17 00:00:00 2001 From: Sankalp Maneshwar Date: Tue, 12 May 2026 11:03:22 +0530 Subject: [PATCH 2/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- qa_interfaces/IBenchmarkPayloadCOMRPC.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa_interfaces/IBenchmarkPayloadCOMRPC.h b/qa_interfaces/IBenchmarkPayloadCOMRPC.h index cfd2925e..8ed45d21 100644 --- a/qa_interfaces/IBenchmarkPayloadCOMRPC.h +++ b/qa_interfaces/IBenchmarkPayloadCOMRPC.h @@ -66,7 +66,7 @@ namespace Thunder { virtual uint32_t SendReceiveSampleData(const SampleData &input, SampleData &output /* @out */) const = 0; - virtual uint32_t SendReceiveBuffer(uint16_t &bufferSize /* @inout */, uint8_t buffer[] /* @length:bufferSize @inout */) const = 0; + virtual uint32_t SendReceiveBuffer(uint16_t& bufferSize /* @inout */, uint8_t buffer[] /* @length:bufferSize @inout */) const = 0; virtual uint32_t Add(const uint32_t a, const uint32_t b, uint32_t &result /* @out */) const = 0; From d6d620796ab794d13cc528af5229380a6944f265 Mon Sep 17 00:00:00 2001 From: smanes0213 Date: Thu, 14 May 2026 10:13:02 +0530 Subject: [PATCH 3/4] Resolve review comments --- qa_interfaces/IBenchmark.h | 37 +++++++--- qa_interfaces/IBenchmarkPayload.h | 95 +++++++++++++++++++++++++ qa_interfaces/IBenchmarkPayloadCOMRPC.h | 76 -------------------- qa_interfaces/QAIds.h | 2 +- 4 files changed, 125 insertions(+), 85 deletions(-) create mode 100644 qa_interfaces/IBenchmarkPayload.h delete mode 100644 qa_interfaces/IBenchmarkPayloadCOMRPC.h diff --git a/qa_interfaces/IBenchmark.h b/qa_interfaces/IBenchmark.h index 9b58bf8c..6ad1cb72 100644 --- a/qa_interfaces/IBenchmark.h +++ b/qa_interfaces/IBenchmark.h @@ -1,3 +1,22 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 Metrological + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #pragma once #include "Module.h" @@ -43,16 +62,18 @@ namespace QualityAssurance { // @brief Run the benchmark // @param iterations: Denotes the number of iterations the benchmark should run - // @param success: True if the benchmark completed successfully - virtual Core::hresult Trigger(const uint32_t iterations, bool& success /* @out */) = 0; + // @retval ERROR_NONE Benchmark completed and all thresholds passed + // @retval ERROR_GENERAL Benchmark completed but one or more thresholds exceeded + virtual Core::hresult Trigger(const uint32_t iterations) = 0; + // @brief Collect the results of the most recent benchmark run + // @param report: Iterator over the per-method benchmark results virtual Core::hresult CollectData(IBenchmarkResultIterator*& report /* @out */) const = 0; // @brief Set pass/fail thresholds for benchmark results - // @param maxLatencyDeviationPct: Maximum allowed % deviation in avg latency compared to first-run baseline (0 = no latency check) + // @param maxLatencyDeviationPct: Maximum allowed deviation in avg latency compared to first-run baseline, in millipercent (1000 = 1%, 0 = no latency check) // @param maxMemoryGrowthBytes: Maximum allowed RSS growth in bytes per method (0 = no memory check) - // @param success: True if thresholds were set - virtual Core::hresult SetThreshold(const float maxLatencyDeviationPct, const uint64_t maxMemoryGrowthBytes, bool& success /* @out */) = 0; + virtual Core::hresult SetThreshold(const uint32_t maxLatencyDeviationPct, const uint64_t maxMemoryGrowthBytes) = 0; // @event struct EXTERNAL INotification : virtual public Core::IUnknown { @@ -63,9 +84,9 @@ namespace QualityAssurance { virtual void PerformanceCheckCompleted() = 0; }; - virtual Core::hresult Register(const IBenchmark::INotification* sink) = 0; - virtual Core::hresult Unregister(const IBenchmark::INotification* sink) = 0; + virtual Core::hresult Register(IBenchmark::INotification* sink) = 0; + virtual Core::hresult Unregister(IBenchmark::INotification* sink) = 0; }; } -} \ No newline at end of file +} diff --git a/qa_interfaces/IBenchmarkPayload.h b/qa_interfaces/IBenchmarkPayload.h new file mode 100644 index 00000000..8773ffa9 --- /dev/null +++ b/qa_interfaces/IBenchmarkPayload.h @@ -0,0 +1,95 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 Metrological + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include "Module.h" + +// @stubgen:include + +namespace Thunder { + namespace QualityAssurance { + + struct EXTERNAL IBenchmarkPayload : virtual public Core::IUnknown + { + enum { ID = ID_BENCHMARK_PAYLOAD }; + + ~IBenchmarkPayload() override = default; + + struct SampleData + { + uint32_t id; + uint32_t value; + string name; + }; + + enum PayloadType : uint8_t + { + PAYLOAD_UNKNOWN, + PAYLOAD_SMALL, + PAYLOAD_MEDIUM, + PAYLOAD_LARGE + }; + + typedef RPC::IIteratorType IPayloadTypeIterator; + + // @brief Retrieve supported payload types via an iterator (exercises COM-RPC iterator serialization) + virtual Core::hresult GetPayloadTypes(IPayloadTypeIterator*& types /* @out */) const = 0; + + virtual Core::hresult SendUint16(const uint16_t value) = 0; + + virtual Core::hresult SendUint32(const uint32_t value) = 0; + + virtual Core::hresult SendUint64(const uint64_t value) = 0; + + virtual Core::hresult SendBool(const bool value) = 0; + + virtual Core::hresult SendFloat(const float value) = 0; + + virtual Core::hresult SendDouble(const double value) = 0; + + virtual Core::hresult SendString(const string& value) = 0; + + virtual Core::hresult SendSampleData(const SampleData& data) = 0; + + virtual Core::hresult SendNoPayload() = 0; + + virtual Core::hresult SendBuffer(const uint16_t bufferSize, const uint8_t buffer[] /* @length:bufferSize @in */) = 0; + + virtual Core::hresult SendReceiveUint16(const uint16_t input, uint16_t &output /* @out */) const = 0; + + virtual Core::hresult SendReceiveUint32(const uint32_t input, uint32_t &output /* @out */) const = 0; + + virtual Core::hresult SendReceiveUint64(const uint64_t input, uint64_t &output /* @out */) const = 0; + + virtual Core::hresult SendReceiveBool(const bool input, bool &output /* @out */) const = 0; + + virtual Core::hresult SendReceiveFloat(const float input, float &output /* @out */) const = 0; + + virtual Core::hresult SendReceiveDouble(const double input, double &output /* @out */) const = 0; + + virtual Core::hresult SendReceiveString(const string &input, string &output /* @out */) const = 0; + + virtual Core::hresult SendReceiveSampleData(const SampleData &input, SampleData &output /* @out */) const = 0; + + virtual Core::hresult SendReceiveBuffer(uint16_t &bufferSize /* @inout */, uint8_t buffer[] /* @length:bufferSize @inout */) const = 0; + + virtual Core::hresult Add(const uint32_t a, const uint32_t b, uint32_t &result /* @out */) const = 0; + }; +} +} diff --git a/qa_interfaces/IBenchmarkPayloadCOMRPC.h b/qa_interfaces/IBenchmarkPayloadCOMRPC.h deleted file mode 100644 index 8ed45d21..00000000 --- a/qa_interfaces/IBenchmarkPayloadCOMRPC.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include "Module.h" - -// @stubgen:include - -namespace Thunder { - namespace QualityAssurance { - - - struct SampleData - { - uint32_t id; - uint32_t value; - string name; - }; - - struct EXTERNAL IBenchmarkPayload : virtual public Core::IUnknown - { - enum { ID = ID_BENCHMARK_PAYLOAD }; - - enum PayloadType : uint8_t - { - PAYLOAD_UNKNOWN, - PAYLOAD_SMALL, - PAYLOAD_MEDIUM, - PAYLOAD_LARGE - }; - - typedef RPC::IIteratorType IPayloadTypeIterator; - - virtual uint32_t GetPayloadTypes(IPayloadTypeIterator*& types /* @out */) const = 0; - - virtual uint32_t SendUint16(const uint16_t value) = 0; - - virtual uint32_t SendUint32(const uint32_t value) = 0; - - virtual uint32_t SendUint64(const uint64_t value) = 0; - - virtual uint32_t SendBool(const bool value) = 0; - - virtual uint32_t SendFloat(const float value) = 0; - - virtual uint32_t SendDouble(const double value) = 0; - - virtual uint32_t SendString(const string& value) = 0; - - virtual uint32_t SendSampleData(const SampleData& data) = 0; - - virtual uint32_t SendWithNoParameters() = 0; - - virtual uint32_t SendBuffer(const uint16_t bufferSize, const uint8_t buffer[] /* @length:bufferSize @in */) = 0; - - virtual uint32_t SendReceiveUint16(const uint16_t input, uint16_t &output /* @out */) const = 0; - - virtual uint32_t SendReceiveUint32(const uint32_t input, uint32_t &output /* @out */) const = 0; - - virtual uint32_t SendReceiveUint64(const uint64_t input, uint64_t &output /* @out */) const = 0; - - virtual uint32_t SendReceiveBool(const bool input, bool &output /* @out */) const = 0; - - virtual uint32_t SendReceiveFloat(const float input, float &output /* @out */) const = 0; - - virtual uint32_t SendReceiveDouble(const double input, double &output /* @out */) const = 0; - - virtual uint32_t SendReceiveString(const string &input, string &output /* @out */) const = 0; - - virtual uint32_t SendReceiveSampleData(const SampleData &input, SampleData &output /* @out */) const = 0; - - virtual uint32_t SendReceiveBuffer(uint16_t& bufferSize /* @inout */, uint8_t buffer[] /* @length:bufferSize @inout */) const = 0; - - virtual uint32_t Add(const uint32_t a, const uint32_t b, uint32_t &result /* @out */) const = 0; - - ~IBenchmarkPayload() override = default; - }; -} -} \ No newline at end of file diff --git a/qa_interfaces/QAIds.h b/qa_interfaces/QAIds.h index 403ad713..d91d89e2 100644 --- a/qa_interfaces/QAIds.h +++ b/qa_interfaces/QAIds.h @@ -81,7 +81,7 @@ namespace QualityAssurance { ID_BENCHMARK_RESULT_ITERATOR = ID_BENCHMARK + 2, ID_BENCHMARK_PAYLOAD = RPC::IDS::ID_EXTERNAL_QA_INTERFACE_OFFSET + 0x050, - ID_PAYLOADTYPE_ITERATOR = ID_BENCHMARK_PAYLOAD + 1, + ID_BENCHMARK_PAYLOADTYPE_ITERATOR = ID_BENCHMARK_PAYLOAD + 1, }; } } From e2a7856e97b620adf9ce4600649799ab0ef8f782 Mon Sep 17 00:00:00 2001 From: smanes0213 Date: Tue, 2 Jun 2026 10:52:12 +0530 Subject: [PATCH 4/4] Resolve review comments --- qa_interfaces/IBenchmark.h | 25 ++++++++++++++++++------- qa_interfaces/IBenchmarkPayload.h | 4 ++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/qa_interfaces/IBenchmark.h b/qa_interfaces/IBenchmark.h index 6ad1cb72..6650353c 100644 --- a/qa_interfaces/IBenchmark.h +++ b/qa_interfaces/IBenchmark.h @@ -26,7 +26,7 @@ namespace Thunder { namespace QualityAssurance { - // @json 1.0.0 @text:legacy_lowercase + // @json 2.0.0 struct EXTERNAL IBenchmark : virtual public Core::IUnknown { enum { ID = ID_BENCHMARK }; @@ -47,6 +47,12 @@ namespace QualityAssurance { }; + enum FailureReason : uint8_t { + LATENCY_THRESHOLD_EXCEEDED, + MEMORY_THRESHOLD_EXCEEDED, + LATENCY_AND_MEMORY_THRESHOLD_EXCEEDED + }; + struct BenchmarkResult { string apiName; uint32_t iterations; @@ -54,8 +60,8 @@ namespace QualityAssurance { RoundTripStats roundTrip; MemoryStats memory; - bool passed; // true if within configured thresholds - string failureReason; // empty if passed, describes which threshold was exceeded + bool passed; + Core::OptionalType failureReason; }; typedef RPC::IIteratorType IBenchmarkResultIterator; @@ -70,10 +76,15 @@ namespace QualityAssurance { // @param report: Iterator over the per-method benchmark results virtual Core::hresult CollectData(IBenchmarkResultIterator*& report /* @out */) const = 0; - // @brief Set pass/fail thresholds for benchmark results - // @param maxLatencyDeviationPct: Maximum allowed deviation in avg latency compared to first-run baseline, in millipercent (1000 = 1%, 0 = no latency check) - // @param maxMemoryGrowthBytes: Maximum allowed RSS growth in bytes per method (0 = no memory check) - virtual Core::hresult SetThreshold(const uint32_t maxLatencyDeviationPct, const uint64_t maxMemoryGrowthBytes) = 0; + // @property + // @brief Maximum allowed deviation in avg latency compared to first-run baseline, in millipercent (1000 = 1%, 0 = no latency check) + virtual Core::hresult LatencyThreshold(const uint32_t maxLatencyDeviationPct) = 0; + virtual Core::hresult LatencyThreshold(uint32_t& maxLatencyDeviationPct /* @out */) const = 0; + + // @property + // @brief Maximum allowed RSS growth in bytes per method (0 = no memory check) + virtual Core::hresult MemoryThreshold(const uint64_t maxMemoryGrowthBytes) = 0; + virtual Core::hresult MemoryThreshold(uint64_t& maxMemoryGrowthBytes /* @out */) const = 0; // @event struct EXTERNAL INotification : virtual public Core::IUnknown { diff --git a/qa_interfaces/IBenchmarkPayload.h b/qa_interfaces/IBenchmarkPayload.h index 8773ffa9..7babdfa0 100644 --- a/qa_interfaces/IBenchmarkPayload.h +++ b/qa_interfaces/IBenchmarkPayload.h @@ -71,6 +71,8 @@ namespace Thunder { virtual Core::hresult SendBuffer(const uint16_t bufferSize, const uint8_t buffer[] /* @length:bufferSize @in */) = 0; + virtual Core::hresult SendUint32Array(const std::vector& data /* @restrict:1..1024 */) = 0; + virtual Core::hresult SendReceiveUint16(const uint16_t input, uint16_t &output /* @out */) const = 0; virtual Core::hresult SendReceiveUint32(const uint32_t input, uint32_t &output /* @out */) const = 0; @@ -89,6 +91,8 @@ namespace Thunder { virtual Core::hresult SendReceiveBuffer(uint16_t &bufferSize /* @inout */, uint8_t buffer[] /* @length:bufferSize @inout */) const = 0; + virtual Core::hresult SendReceiveUint32Array(const std::vector& input /* @restrict:1..1024 */, std::vector& output /* @out @restrict:1..1024 */) const = 0; + virtual Core::hresult Add(const uint32_t a, const uint32_t b, uint32_t &result /* @out */) const = 0; }; }