// Copyright 2021 Google LLC // // 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 // // https://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. #ifndef PLATFORM_IMPL_G3_TIMER_H_ #define PLATFORM_IMPL_G3_TIMER_H_ #include #include #include #include "absl/base/nullability.h" #include "absl/base/thread_annotations.h" #include "absl/functional/any_invocable.h" #include "absl/synchronization/mutex.h" #include "absl/time/time.h" #include "internal/platform/implementation/cancelable.h" #include "internal/platform/implementation/scheduled_executor.h" #include "internal/platform/implementation/timer.h" namespace nearby { namespace g3 { class Timer : public api::Timer { public: explicit Timer(api::ScheduledExecutor* absl_nonnull executor) : executor_(executor) {}; ~Timer() override { Stop(); }; bool Create(int delay, int interval, absl::AnyInvocable callback) override { if (delay < 0 || interval < 0 || callback == nullptr) { return false; } interval_ = absl::Milliseconds(interval); callback_ = std::move(callback); is_stopped_ = false; return Schedule(absl::Milliseconds(delay)); } bool Stop() override { is_stopped_ = true; absl::MutexLock lock(mutex_); if (task_) { bool result = task_->Cancel(); task_.reset(); return result; } return true; } private: bool Schedule(absl::Duration delay) { absl::MutexLock lock(mutex_); if (is_stopped_) { return false; } task_ = executor_->Schedule([this]() { TriggerCallback(); }, delay); return true; } void TriggerCallback() { if (is_stopped_) return; // If interval is 0, timer is one shot. if (interval_ != absl::ZeroDuration()) { Schedule(interval_); } callback_(); } private: absl::Mutex mutex_; absl::AnyInvocable callback_; std::atomic_bool is_stopped_; absl::Duration interval_; std::shared_ptr task_ ABSL_GUARDED_BY(mutex_); api::ScheduledExecutor* absl_nonnull const executor_; }; } // namespace g3 } // namespace nearby #endif // PLATFORM_IMPL_G3_TIMER_H_