|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // <experimental/timer> -*- C++ -*-
-
- // Copyright (C) 2015-2020 Free Software Foundation, Inc.
- //
- // This file is part of the GNU ISO C++ Library. This library is free
- // software; you can redistribute it and/or modify it under the
- // terms of the GNU General Public License as published by the
- // Free Software Foundation; either version 3, or (at your option)
- // any later version.
-
- // This library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
-
- // Under Section 7 of GPL version 3, you are granted additional
- // permissions described in the GCC Runtime Library Exception, version
- // 3.1, as published by the Free Software Foundation.
-
- // You should have received a copy of the GNU General Public License and
- // a copy of the GCC Runtime Library Exception along with this program;
- // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- // <http://www.gnu.org/licenses/>.
-
- /** @file experimental/timer
- * This is a TS C++ Library header.
- * @ingroup networking-ts
- */
-
- #ifndef _GLIBCXX_EXPERIMENTAL_TIMER
- #define _GLIBCXX_EXPERIMENTAL_TIMER 1
-
- #pragma GCC system_header
-
- #if __cplusplus >= 201402L
-
- #include <chrono>
- #include <system_error>
- #include <thread>
- #include <experimental/netfwd>
- #include <experimental/io_context>
- #include <experimental/bits/net.h>
-
- namespace std _GLIBCXX_VISIBILITY(default)
- {
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
- namespace experimental
- {
- namespace net
- {
- inline namespace v1
- {
-
- /** @addtogroup networking-ts
- * @{
- */
-
- template<typename _Clock>
- struct wait_traits
- {
- static typename _Clock::duration
- to_wait_duration(const typename _Clock::duration& __d)
- { return __d; }
-
- static typename _Clock::duration
- to_wait_duration(const typename _Clock::time_point& __t)
- {
- auto __now = _Clock::now();
- auto __diff = __t - __now;
- if (__diff > _Clock::duration::max())
- return _Clock::duration::max();
- if (__diff < _Clock::duration::min())
- return _Clock::duration::min();
- return __diff;
- }
- };
-
- template<typename _Clock, typename _WaitTraits>
- class basic_waitable_timer
- {
- public:
- // types:
-
- typedef io_context::executor_type executor_type;
- typedef _Clock clock_type;
- typedef typename clock_type::duration duration;
- typedef typename clock_type::time_point time_point;
- typedef _WaitTraits traits_type;
-
- // construct / copy / destroy:
-
- explicit
- basic_waitable_timer(io_context& __ctx)
- : _M_ex(__ctx.get_executor()), _M_expiry()
- { }
-
- basic_waitable_timer(io_context& __ctx, const time_point& __t)
- : _M_ex(__ctx.get_executor()), _M_expiry(__t)
- { }
-
- basic_waitable_timer(io_context& __ctx, const duration& __d)
- : _M_ex(__ctx.get_executor()), _M_expiry(_Clock::now() + __d)
- { }
-
- basic_waitable_timer(const basic_waitable_timer&) = delete;
-
- basic_waitable_timer(basic_waitable_timer&& __rhs)
- : _M_ex(std::move(__rhs._M_ex)), _M_expiry(__rhs._M_expiry)
- {
- _M_key.swap(__rhs._M_key);
- __rhs._M_expiry = time_point{};
- }
-
- ~basic_waitable_timer() { cancel(); }
-
- basic_waitable_timer& operator=(const basic_waitable_timer&) = delete;
-
- basic_waitable_timer&
- operator=(basic_waitable_timer&& __rhs)
- {
- if (this == std::addressof(__rhs))
- return *this;
- cancel();
- _M_ex = std::move(__rhs._M_ex);
- _M_expiry = __rhs._M_expiry;
- __rhs._M_expiry = time_point{};
- _M_key.swap(__rhs._M_key);
- return *this;
- }
-
- // basic_waitable_timer operations:
-
- executor_type get_executor() noexcept { return _M_ex; }
-
- size_t cancel() { return _M_ex.context().cancel(*this); }
- size_t cancel_one() { return _M_ex.context().cancel_one(*this); }
-
- time_point expiry() const { return _M_expiry; }
-
- size_t expires_at(const time_point& __t)
- {
- size_t __cancelled = cancel();
- _M_expiry = __t;
- return __cancelled;
- }
-
- size_t expires_after(const duration& __d)
- { return expires_at(_Clock::now() + __d); }
-
- void wait();
- void wait(error_code& __ec);
-
- template<typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code)>
- async_wait(_CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code)> __init(__token);
- _M_ex.context().async_wait(*this,
- std::move(__init.completion_handler));
- return __init.result.get();
- }
-
- private:
- executor_type _M_ex;
- time_point _M_expiry;
-
- struct _Key { }; // TODO move _M_expiry into here?
- unique_ptr<_Key> _M_key{new _Key};
-
- friend class io_context;
- };
-
- typedef basic_waitable_timer<chrono::system_clock> system_timer;
- typedef basic_waitable_timer<chrono::steady_clock> steady_timer;
- typedef basic_waitable_timer<chrono::high_resolution_clock>
- high_resolution_timer;
-
- template<typename _Clock, typename _WaitTraits>
- void
- basic_waitable_timer<_Clock, _WaitTraits>::wait()
- {
- _M_ex.dispatch([this] {
- while (clock_type::now() < _M_expiry)
- this_thread::sleep_for(traits_type::to_wait_duration(_M_expiry));
- }, allocator<void>{});
- }
-
- template<typename _Clock, typename _WaitTraits>
- void
- basic_waitable_timer<_Clock, _WaitTraits>::wait(error_code&)
- {
- _M_ex.dispatch([this] {
- while (clock_type::now() < _M_expiry)
- this_thread::sleep_for(traits_type::to_wait_duration(_M_expiry));
- }, allocator<void>{});
- }
-
- /// @}
-
- } // namespace v1
- } // namespace net
- } // namespace experimental
- _GLIBCXX_END_NAMESPACE_VERSION
- } // namespace std
-
- #endif // C++14
-
- #endif // _GLIBCXX_EXPERIMENTAL_TIMER
|