| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 |
| |
| #ifndef GEODE_EXPIRYTASKMANAGER_H_ |
| #define GEODE_EXPIRYTASKMANAGER_H_ |
| |
| #include <chrono> |
| #include <condition_variable> |
| #include <map> |
| #include <mutex> |
| #include <thread> |
| |
| #include <boost/asio/executor_work_guard.hpp> |
| #include <boost/asio/io_context.hpp> |
| |
| #include "ExpiryTask.hpp" |
| |
| namespace apache { |
| namespace geode { |
| namespace client { |
| |
| /** |
| * @class ExpiryTaskManager ExpiryTaskManager.hpp |
| * |
| * This class manages all the ExpiryTaskManagers |
| * It uses Boost.Asio and Boost timers to schedule ExpiryTasks |
| */ |
| class ExpiryTaskManager { |
| public: |
| /** |
| * Default class constructor |
| */ |
| ExpiryTaskManager(); |
| |
| /** |
| * Class destructor |
| */ |
| virtual ~ExpiryTaskManager() noexcept; |
| |
| /** |
| * Starts the manager |
| * @throw IllegalStateException An exception is thrown if the manager is |
| * already started. |
| */ |
| void start(); |
| |
| /** |
| * Stops the manager |
| * @throw IllegalStateException An exception is thrown if the manager is |
| * already stopped. |
| */ |
| void stop(); |
| |
| /** |
| * Returns whether or not the manager is running. |
| */ |
| bool running() const { return running_; } |
| |
| /** |
| * Returns the number of scheduled tasks. |
| */ |
| std::size_t count() const { return task_map_.size(); } |
| |
| /** |
| * Schedules a new expiry task. |
| * @param task Reference to the task. |
| * @param delay Amount of nano-seconds in which the task expires. |
| * @param interval Amount of nano-seconds in which the task is executed again. |
| * If this parameter is set to zero, the task will only |
| * execute once and finish, otherwise it will execute |
| * continuously every interval nano-seconds until cancelled. |
| * @return ID of the created task. If there was any error during the |
| * task creation ExpiryTask::invalid() is returned as ID. |
| * @note Possible errors are:<br> |
| * - Manager is not running |
| */ |
| ExpiryTask::id_t schedule(std::shared_ptr<ExpiryTask> task, |
| const ExpiryTask::duration_t &delay, |
| const ExpiryTask::duration_t &interval); |
| |
| /** |
| * Schedules a new expiry task. |
| * @param task Task reference. |
| * @param delay Amount of nano-seconds in which the task expires. |
| * @return ID of the created task. If there was any error during the |
| * task creation ExpiryTask::invalid() is returned as ID. |
| * @note Possible errors are:<br> |
| * - Manager is not running |
| */ |
| ExpiryTask::id_t schedule(std::shared_ptr<ExpiryTask> task, |
| const ExpiryTask::duration_t &delay) { |
| return schedule(std::move(task), delay, ExpiryTask::duration_t::zero()); |
| } |
| |
| /** |
| * Re-triggers a task to run in the given delay. |
| * @param task_id ID of the task to be re-triggered. |
| * @param delay Amount of nano-seconds in which the task expires. |
| * @return Returns -1 if the task did not existed, and otherwise it |
| * returns the number of pending executions. Take into account |
| * that if 0 is returned it means the task was being executed |
| * while reset was called. |
| */ |
| int32_t reset(ExpiryTask::id_t task_id, const ExpiryTask::duration_t &delay); |
| |
| /** |
| * Cancels an already scheduled expiry task |
| * @param task_id ID of the task to be cancelled. |
| * @return Returns -1 if the task did not existed, and otherwise it |
| * returns the number of pending executions. Take into account |
| * that if 0 is returned it means the task was being executed |
| * while cancel was called. |
| */ |
| int32_t cancel(ExpiryTask::id_t task_id); |
| |
| protected: |
| /// Internal types |
| |
| using duration_t = std::chrono::nanoseconds; |
| using task_map_t = std::map<ExpiryTask::id_t, std::shared_ptr<ExpiryTask>>; |
| |
| protected: |
| friend class ExpiryTask; |
| |
| /** |
| * Cancels all scheduled tasks |
| */ |
| void cancel_all(); |
| |
| /** |
| * Removes the reference to the task matching the given ID |
| * @param task_id ID of the task |
| */ |
| void remove(ExpiryTask::id_t task_id); |
| |
| /** |
| * Returns Boost IO context |
| */ |
| boost::asio::io_context &io_context() { return io_context_; } |
| |
| protected: |
| /// Class member attributes |
| |
| /** |
| * Flag indicating whether or not the manager is running. |
| */ |
| bool running_; |
| |
| /** |
| * Thread running the io_context. |
| */ |
| std::thread runner_; |
| |
| /* |
| * Boost IO context processing expiry tasks events. |
| */ |
| boost::asio::io_context io_context_; |
| |
| /** |
| * Executor guard. It keeps the IO context running even when there are |
| * no task scheduled. |
| */ |
| boost::asio::executor_work_guard<boost::asio::io_context::executor_type> |
| work_guard_; |
| |
| /** |
| * Manager mutex. It has the following uses:<br> |
| * - Avoids race conditions involving the task container. |
| * - Avoids creation of new task while the expiry task is being stopped. |
| * - Avoids concurrent modification of the task counter. |
| */ |
| std::mutex mutex_; |
| |
| /** |
| * Task container |
| */ |
| task_map_t task_map_; |
| |
| /** |
| * Task counter. It's used to assign tasks an UID. |
| */ |
| ExpiryTask::id_t last_task_id_; |
| }; |
| } // namespace client |
| } // namespace geode |
| } // namespace apache |
| |
| #endif // GEODE_EXPIRYTASKMANAGER_H_ |