Skip to content

Commit c31affa

Browse files
committed
Introduce functional value monitor
1 parent 6ac3ccc commit c31affa

3 files changed

Lines changed: 139 additions & 0 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 Tendry Lab
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#pragma once
7+
8+
#include <functional>
9+
10+
#include "ocs_core/ivalue_monitor.h"
11+
#include "ocs_core/noncopyable.h"
12+
#include "ocs_status/code.h"
13+
14+
namespace ocs {
15+
namespace core {
16+
17+
//! Value monitor that delegates the update to the provided function.
18+
template <typename T>
19+
class FuncValueMonitor : public IValueMonitor<T>, private NonCopyable<> {
20+
public:
21+
//! Function to update the underlying monitor.
22+
using Func = std::function<status::StatusCode()>;
23+
24+
//! Initialize.
25+
//!
26+
//! @params
27+
//! - @p monitor to get the latest sampled value.
28+
//! - @p func to update the @p monitor, e.g. asynchronously on a specific task.
29+
FuncValueMonitor(IValueMonitor<T>& monitor, Func func)
30+
: monitor_(monitor)
31+
, func_(func) {
32+
}
33+
34+
//! Get latest sampled value from the underlying monitor.
35+
T get() const override {
36+
return monitor_.get();
37+
}
38+
39+
//! Call the function to update the underlying monitor.
40+
status::StatusCode update() override {
41+
return func_();
42+
}
43+
44+
private:
45+
IValueMonitor<T>& monitor_;
46+
Func func_;
47+
};
48+
49+
} // namespace core
50+
} // namespace ocs

‎components/ocs_core/test/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ idf_component_register(
99
"test_byte_writer.cpp"
1010
"test_byte_reader.cpp"
1111
"test_byte_transceiver.cpp"
12+
"test_func_value_monitor.cpp"
1213

1314
REQUIRES
1415
"unity"
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 Tendry Lab
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "unity.h"
7+
8+
#include "ocs_core/func_value_monitor.h"
9+
#include "ocs_core/noncopyable.h"
10+
11+
namespace ocs {
12+
namespace core {
13+
14+
namespace {
15+
16+
class TestValueMonitor : public IValueMonitor<int>, private NonCopyable<> {
17+
public:
18+
int get() const override {
19+
return value;
20+
}
21+
22+
status::StatusCode update() override {
23+
++update_call_count;
24+
25+
return status::StatusCode::OK;
26+
}
27+
28+
int value { 0 };
29+
size_t update_call_count { 0 };
30+
};
31+
32+
} // namespace
33+
34+
TEST_CASE("Func value monitor: get value from the underlying monitor",
35+
"[func_value_monitor], [ocs_core]") {
36+
TestValueMonitor monitor;
37+
size_t func_call_count = 0;
38+
39+
FuncValueMonitor<int> func_monitor(monitor, [&func_call_count]() {
40+
++func_call_count;
41+
42+
return status::StatusCode::OK;
43+
});
44+
45+
monitor.value = 42;
46+
TEST_ASSERT_EQUAL(42, func_monitor.get());
47+
48+
monitor.value = -1;
49+
TEST_ASSERT_EQUAL(-1, func_monitor.get());
50+
51+
TEST_ASSERT_EQUAL(0, func_call_count);
52+
TEST_ASSERT_EQUAL(0, monitor.update_call_count);
53+
}
54+
55+
TEST_CASE("Func value monitor: update calls the function",
56+
"[func_value_monitor], [ocs_core]") {
57+
TestValueMonitor monitor;
58+
size_t func_call_count = 0;
59+
60+
FuncValueMonitor<int> func_monitor(monitor, [&func_call_count]() {
61+
++func_call_count;
62+
63+
return status::StatusCode::OK;
64+
});
65+
66+
TEST_ASSERT_EQUAL(status::StatusCode::OK, func_monitor.update());
67+
TEST_ASSERT_EQUAL(1, func_call_count);
68+
69+
TEST_ASSERT_EQUAL(status::StatusCode::OK, func_monitor.update());
70+
TEST_ASSERT_EQUAL(2, func_call_count);
71+
72+
// The underlying monitor is only updated by the function.
73+
TEST_ASSERT_EQUAL(0, monitor.update_call_count);
74+
}
75+
76+
TEST_CASE("Func value monitor: update propagates the function failure",
77+
"[func_value_monitor], [ocs_core]") {
78+
TestValueMonitor monitor;
79+
80+
FuncValueMonitor<int> func_monitor(monitor, []() {
81+
return status::StatusCode::Error;
82+
});
83+
84+
TEST_ASSERT_EQUAL(status::StatusCode::Error, func_monitor.update());
85+
}
86+
87+
} // namespace core
88+
} // namespace ocs

0 commit comments

Comments
 (0)