1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_chrono/system_timer.h"
16
17 #include <thread>
18
19 namespace pw::chrono {
20 namespace {
21
22 using CallbackContext = backend::NativeSystemTimer::CallbackContext;
23
SystemTimerThreadFunction(std::shared_ptr<bool> timer_enabled,std::shared_ptr<CallbackContext> callback_context,SystemClock::time_point expiry_deadline)24 void SystemTimerThreadFunction(
25 std::shared_ptr<bool> timer_enabled,
26 std::shared_ptr<CallbackContext> callback_context,
27 SystemClock::time_point expiry_deadline) {
28 // Sleep until the requested deadline.
29 std::this_thread::sleep_until(expiry_deadline);
30
31 {
32 std::lock_guard lock(callback_context->mutex);
33 // Only invoke the user's callback if this invocation has not been
34 // cancelled.
35 if (*timer_enabled) {
36 (callback_context->callback)(expiry_deadline);
37 }
38 }
39 }
40
41 } // namespace
42
InvokeAt(SystemClock::time_point timestamp)43 void SystemTimer::InvokeAt(SystemClock::time_point timestamp) {
44 std::lock_guard lock(native_type_.callback_context->mutex);
45
46 // First, cancel any outstanding requests.
47 if (native_type_.active_timer_enabled) {
48 *native_type_.active_timer_enabled = false;
49 }
50
51 // Second, active another detached timer thread with a new shared atomic bool.
52 native_type_.active_timer_enabled = std::make_shared<bool>(true);
53 std::thread(SystemTimerThreadFunction,
54 native_type_.active_timer_enabled,
55 native_type_.callback_context,
56 timestamp)
57 .detach();
58 }
59
Cancel()60 void SystemTimer::Cancel() {
61 std::lock_guard lock(native_type_.callback_context->mutex);
62
63 if (native_type_.active_timer_enabled) {
64 *native_type_.active_timer_enabled = false;
65 }
66 }
67
68 } // namespace pw::chrono
69