|
@@ -14,102 +14,75 @@
|
|
|
|
|
|
namespace robotics {
|
|
|
namespace v3 {
|
|
|
- template<typename ..._Args>
|
|
|
- struct event_trigger {
|
|
|
- event_trigger() {
|
|
|
- start();
|
|
|
- }
|
|
|
- ~event_trigger() {
|
|
|
- stop();
|
|
|
- }
|
|
|
- /**
|
|
|
- * @brief 添加任务
|
|
|
- * @param sleep
|
|
|
- * @param ...args
|
|
|
- */
|
|
|
- void add(time_t sleep, _Args const&...args) {
|
|
|
- std::lock_guard<std::mutex> locker(mutex_);
|
|
|
- task_list_.push_back(std::make_pair(std::make_tuple(args...), v3::utils::steady_time_stamp() + sleep));
|
|
|
- cv_.notify_one();
|
|
|
- }
|
|
|
- /**
|
|
|
- * @brief 清空
|
|
|
- */
|
|
|
- void clear() {
|
|
|
- std::lock_guard<std::mutex> locker(mutex_);
|
|
|
- task_list_.clear();
|
|
|
- }
|
|
|
- /**
|
|
|
- * @brief
|
|
|
- * @param fn
|
|
|
- */
|
|
|
- void bind(std::function<void(_Args...)>&& fn) {
|
|
|
- event.bind(std::move(fn));
|
|
|
- }
|
|
|
- /**
|
|
|
- * @brief
|
|
|
- * @param fn
|
|
|
- */
|
|
|
- void operator+=(std::function<void(_Args...)>&& fn) {
|
|
|
- bind(std::move(fn));
|
|
|
- }
|
|
|
- /**
|
|
|
- * @brief
|
|
|
- * @tparam _Fn
|
|
|
- * @tparam _Obj
|
|
|
- * @param fn
|
|
|
- * @param obj
|
|
|
- */
|
|
|
- template<typename _Fn, typename _Obj>
|
|
|
- void bind(_Fn&& fn, _Obj&& obj) {
|
|
|
- bind(std::bind_front(std::move(fn), std::move(obj)));
|
|
|
- }
|
|
|
- /**
|
|
|
- * @brief 事件
|
|
|
- */
|
|
|
- delegates<_Args...> event;
|
|
|
- private:
|
|
|
- void start() {
|
|
|
- std::thread th(&event_trigger::thread_work, this);
|
|
|
- thread_ = std::move(th);
|
|
|
- }
|
|
|
- void stop() {
|
|
|
- running_ = false;
|
|
|
- cv_.notify_all();
|
|
|
- if (thread_.joinable())
|
|
|
- thread_.join();
|
|
|
- }
|
|
|
- void on_event(int time, _Args...args) {
|
|
|
- event(args...);
|
|
|
- }
|
|
|
- void thread_work() {
|
|
|
- running_ = true;
|
|
|
- while (running_) {
|
|
|
- {
|
|
|
- std::unique_lock<std::mutex> lock(mutex_);
|
|
|
- while (task_list_.empty() && running_)
|
|
|
- cv_.wait(lock);
|
|
|
- time_t current_time = v3::utils::steady_time_stamp();
|
|
|
- for (int i = 0; i < task_list_.size(); ++i) {
|
|
|
- if (task_list_[i].second <= current_time) {
|
|
|
- std::apply([&](auto&&...args) {
|
|
|
- on_event(current_time - task_list_[i].second, std::forward<decltype(args)>(args)...);
|
|
|
- }, task_list_[i].first);
|
|
|
- task_list_.erase(task_list_.begin() + i);
|
|
|
- --i;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- std::this_thread::sleep_for(std::chrono::microseconds(1));
|
|
|
- }
|
|
|
- running_ = false;
|
|
|
- }
|
|
|
- private:
|
|
|
- std::thread thread_;
|
|
|
- bool running_ = false;
|
|
|
- std::mutex mutex_;
|
|
|
- std::condition_variable cv_;
|
|
|
- std::vector<std::pair<std::tuple<_Args...>, time_t>> task_list_;
|
|
|
- };
|
|
|
+ class event_trigger {
|
|
|
+ using _Func = std::function<void()>;
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * @brief 构造
|
|
|
+ */
|
|
|
+ event_trigger() {
|
|
|
+ start();
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * @brief 虚构
|
|
|
+ */
|
|
|
+ ~event_trigger() {
|
|
|
+ stop();
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * @brief 添加任务
|
|
|
+ * @tparam _Fn
|
|
|
+ * @tparam _This
|
|
|
+ * @tparam ..._Args
|
|
|
+ * @param sleep
|
|
|
+ * @param fn
|
|
|
+ * @param ths
|
|
|
+ * @param ...args
|
|
|
+ */
|
|
|
+ template<typename _Fn, typename _This, typename ..._Args>
|
|
|
+ void add(int sleep, _Fn&& fn, _This&& ths, _Args&& ...args) {
|
|
|
+ std::shared_ptr<asio::steady_timer> timer = std::make_shared<asio::steady_timer>(io_, asio::chrono::milliseconds(sleep));
|
|
|
+ _Func bound_fn = std::bind(std::forward<_Fn>(fn), std::forward<_This>(ths), std::forward<_Args>(args)...);
|
|
|
+ std::size_t key = (std::size_t)timer.get();
|
|
|
+ {
|
|
|
+ std::lock_guard<std::mutex> lock(mutex_);
|
|
|
+ task_list_[key] = timer;
|
|
|
+ }
|
|
|
+ timer->async_wait(std::bind(&event_trigger::on_event, this, std::placeholders::_1, bound_fn, key));
|
|
|
+ }
|
|
|
+ v3::delegates<std::string const&> error_event;
|
|
|
+ private:
|
|
|
+ void start() {
|
|
|
+ thread_ = std::thread(&event_trigger::run, this);
|
|
|
+ }
|
|
|
+ void on_event(const asio::error_code& ec, _Func const& fn, std::size_t key) {
|
|
|
+ {
|
|
|
+ std::lock_guard<std::mutex> lock(mutex_);
|
|
|
+ task_list_.erase(key);
|
|
|
+ }
|
|
|
+ if (ec) {
|
|
|
+ error_event(ec.message());
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ fn();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ void stop() {
|
|
|
+ work_->reset();
|
|
|
+ if (thread_.joinable()) {
|
|
|
+ thread_.join();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ void run() {
|
|
|
+ work_.reset(new asio::executor_work_guard<asio::io_context::executor_type>(asio::make_work_guard(io_)));
|
|
|
+ io_.run();
|
|
|
+ }
|
|
|
+ private:
|
|
|
+ std::thread thread_;
|
|
|
+ std::mutex mutex_;
|
|
|
+ asio::io_context io_;
|
|
|
+ std::map<std::size_t, std::shared_ptr<asio::steady_timer>> task_list_;
|
|
|
+ std::shared_ptr<asio::executor_work_guard<asio::io_context::executor_type>> work_;
|
|
|
+ };
|
|
|
}
|
|
|
}
|