Home | History | Annotate | Line # | Download | only in experimental
      1      1.1  mrg // <experimental/timer> -*- C++ -*-
      2      1.1  mrg 
      3  1.1.1.4  mrg // Copyright (C) 2015-2024 Free Software Foundation, Inc.
      4      1.1  mrg //
      5      1.1  mrg // This file is part of the GNU ISO C++ Library.  This library is free
      6      1.1  mrg // software; you can redistribute it and/or modify it under the
      7      1.1  mrg // terms of the GNU General Public License as published by the
      8      1.1  mrg // Free Software Foundation; either version 3, or (at your option)
      9      1.1  mrg // any later version.
     10      1.1  mrg 
     11      1.1  mrg // This library is distributed in the hope that it will be useful,
     12      1.1  mrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13      1.1  mrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14      1.1  mrg // GNU General Public License for more details.
     15      1.1  mrg 
     16      1.1  mrg // Under Section 7 of GPL version 3, you are granted additional
     17      1.1  mrg // permissions described in the GCC Runtime Library Exception, version
     18      1.1  mrg // 3.1, as published by the Free Software Foundation.
     19      1.1  mrg 
     20      1.1  mrg // You should have received a copy of the GNU General Public License and
     21      1.1  mrg // a copy of the GCC Runtime Library Exception along with this program;
     22      1.1  mrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23      1.1  mrg // <http://www.gnu.org/licenses/>.
     24      1.1  mrg 
     25      1.1  mrg /** @file experimental/timer
     26      1.1  mrg  *  This is a TS C++ Library header.
     27  1.1.1.2  mrg  *  @ingroup networking-ts
     28      1.1  mrg  */
     29      1.1  mrg 
     30      1.1  mrg #ifndef _GLIBCXX_EXPERIMENTAL_TIMER
     31      1.1  mrg #define _GLIBCXX_EXPERIMENTAL_TIMER 1
     32      1.1  mrg 
     33      1.1  mrg #pragma GCC system_header
     34      1.1  mrg 
     35  1.1.1.4  mrg #include <bits/requires_hosted.h> // experimental is currently omitted
     36  1.1.1.4  mrg 
     37      1.1  mrg #if __cplusplus >= 201402L
     38      1.1  mrg 
     39  1.1.1.3  mrg #include <bits/chrono.h>
     40      1.1  mrg #include <system_error>
     41      1.1  mrg #include <thread>
     42      1.1  mrg #include <experimental/netfwd>
     43      1.1  mrg #include <experimental/io_context>
     44      1.1  mrg #include <experimental/bits/net.h>
     45      1.1  mrg 
     46      1.1  mrg namespace std _GLIBCXX_VISIBILITY(default)
     47      1.1  mrg {
     48      1.1  mrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
     49      1.1  mrg namespace experimental
     50      1.1  mrg {
     51      1.1  mrg namespace net
     52      1.1  mrg {
     53      1.1  mrg inline namespace v1
     54      1.1  mrg {
     55      1.1  mrg 
     56  1.1.1.2  mrg   /** @addtogroup networking-ts
     57  1.1.1.2  mrg    *  @{
     58      1.1  mrg    */
     59      1.1  mrg 
     60      1.1  mrg   template<typename _Clock>
     61      1.1  mrg     struct wait_traits
     62      1.1  mrg     {
     63      1.1  mrg       static typename _Clock::duration
     64      1.1  mrg       to_wait_duration(const typename _Clock::duration& __d)
     65      1.1  mrg       { return __d; }
     66      1.1  mrg 
     67      1.1  mrg       static typename _Clock::duration
     68      1.1  mrg       to_wait_duration(const typename _Clock::time_point& __t)
     69      1.1  mrg       {
     70      1.1  mrg 	auto __now = _Clock::now();
     71      1.1  mrg 	auto __diff = __t - __now;
     72      1.1  mrg 	if (__diff > _Clock::duration::max())
     73      1.1  mrg 	  return _Clock::duration::max();
     74      1.1  mrg 	if (__diff < _Clock::duration::min())
     75      1.1  mrg 	  return _Clock::duration::min();
     76      1.1  mrg 	return __diff;
     77      1.1  mrg       }
     78      1.1  mrg     };
     79      1.1  mrg 
     80      1.1  mrg   template<typename _Clock, typename _WaitTraits>
     81      1.1  mrg     class basic_waitable_timer
     82      1.1  mrg     {
     83      1.1  mrg     public:
     84      1.1  mrg       // types:
     85      1.1  mrg 
     86  1.1.1.3  mrg       using executor_type = io_context::executor_type;
     87  1.1.1.3  mrg       using clock_type = _Clock;
     88  1.1.1.3  mrg       using duration = typename clock_type::duration;
     89  1.1.1.3  mrg       using time_point = typename clock_type::time_point;
     90  1.1.1.3  mrg       using traits_type = _WaitTraits;
     91      1.1  mrg 
     92      1.1  mrg       // construct / copy / destroy:
     93      1.1  mrg 
     94      1.1  mrg       explicit
     95      1.1  mrg       basic_waitable_timer(io_context& __ctx)
     96      1.1  mrg       : _M_ex(__ctx.get_executor()), _M_expiry()
     97      1.1  mrg       { }
     98      1.1  mrg 
     99      1.1  mrg       basic_waitable_timer(io_context& __ctx, const time_point& __t)
    100      1.1  mrg       : _M_ex(__ctx.get_executor()), _M_expiry(__t)
    101      1.1  mrg       { }
    102      1.1  mrg 
    103      1.1  mrg       basic_waitable_timer(io_context& __ctx, const duration& __d)
    104      1.1  mrg       : _M_ex(__ctx.get_executor()), _M_expiry(_Clock::now() + __d)
    105      1.1  mrg       { }
    106      1.1  mrg 
    107      1.1  mrg       basic_waitable_timer(const basic_waitable_timer&) = delete;
    108      1.1  mrg 
    109      1.1  mrg       basic_waitable_timer(basic_waitable_timer&& __rhs)
    110      1.1  mrg       : _M_ex(std::move(__rhs._M_ex)), _M_expiry(__rhs._M_expiry)
    111      1.1  mrg       {
    112      1.1  mrg 	_M_key.swap(__rhs._M_key);
    113      1.1  mrg 	__rhs._M_expiry = time_point{};
    114      1.1  mrg       }
    115      1.1  mrg 
    116      1.1  mrg       ~basic_waitable_timer() { cancel(); }
    117      1.1  mrg 
    118      1.1  mrg       basic_waitable_timer& operator=(const basic_waitable_timer&) = delete;
    119      1.1  mrg 
    120      1.1  mrg       basic_waitable_timer&
    121      1.1  mrg       operator=(basic_waitable_timer&& __rhs)
    122      1.1  mrg       {
    123      1.1  mrg 	if (this == std::addressof(__rhs))
    124      1.1  mrg 	  return *this;
    125      1.1  mrg 	cancel();
    126      1.1  mrg 	_M_ex = std::move(__rhs._M_ex);
    127      1.1  mrg 	_M_expiry = __rhs._M_expiry;
    128      1.1  mrg 	__rhs._M_expiry = time_point{};
    129      1.1  mrg 	_M_key.swap(__rhs._M_key);
    130      1.1  mrg 	return *this;
    131      1.1  mrg       }
    132      1.1  mrg 
    133      1.1  mrg       // basic_waitable_timer operations:
    134      1.1  mrg 
    135      1.1  mrg       executor_type get_executor() noexcept { return _M_ex; }
    136      1.1  mrg 
    137      1.1  mrg       size_t cancel() { return _M_ex.context().cancel(*this); }
    138      1.1  mrg       size_t cancel_one() { return _M_ex.context().cancel_one(*this); }
    139      1.1  mrg 
    140      1.1  mrg       time_point expiry() const { return _M_expiry; }
    141      1.1  mrg 
    142      1.1  mrg       size_t expires_at(const time_point& __t)
    143      1.1  mrg       {
    144      1.1  mrg 	size_t __cancelled = cancel();
    145      1.1  mrg 	_M_expiry = __t;
    146      1.1  mrg 	return __cancelled;
    147      1.1  mrg       }
    148      1.1  mrg 
    149      1.1  mrg       size_t expires_after(const duration& __d)
    150      1.1  mrg       { return expires_at(_Clock::now() + __d); }
    151      1.1  mrg 
    152      1.1  mrg       void wait();
    153      1.1  mrg       void wait(error_code& __ec);
    154      1.1  mrg 
    155      1.1  mrg       template<typename _CompletionToken>
    156      1.1  mrg 	__deduced_t<_CompletionToken, void(error_code)>
    157      1.1  mrg 	async_wait(_CompletionToken&& __token)
    158      1.1  mrg 	{
    159      1.1  mrg 	  async_completion<_CompletionToken, void(error_code)> __init(__token);
    160      1.1  mrg 	  _M_ex.context().async_wait(*this,
    161      1.1  mrg 				     std::move(__init.completion_handler));
    162      1.1  mrg 	  return __init.result.get();
    163      1.1  mrg 	}
    164      1.1  mrg 
    165      1.1  mrg     private:
    166      1.1  mrg       executor_type _M_ex;
    167      1.1  mrg       time_point _M_expiry;
    168      1.1  mrg 
    169      1.1  mrg       struct _Key { };  // TODO move _M_expiry into here?
    170      1.1  mrg       unique_ptr<_Key> _M_key{new _Key};
    171      1.1  mrg 
    172      1.1  mrg       friend class io_context;
    173      1.1  mrg     };
    174      1.1  mrg 
    175  1.1.1.3  mrg   using system_timer = basic_waitable_timer<chrono::system_clock>;
    176  1.1.1.3  mrg   using steady_timer = basic_waitable_timer<chrono::steady_clock>;
    177  1.1.1.3  mrg   using high_resolution_timer
    178  1.1.1.3  mrg     = basic_waitable_timer<chrono::high_resolution_clock>;
    179      1.1  mrg 
    180      1.1  mrg   template<typename _Clock, typename _WaitTraits>
    181      1.1  mrg     void
    182      1.1  mrg     basic_waitable_timer<_Clock, _WaitTraits>::wait()
    183      1.1  mrg     {
    184      1.1  mrg       _M_ex.dispatch([this] {
    185      1.1  mrg 	  while (clock_type::now() < _M_expiry)
    186      1.1  mrg 	    this_thread::sleep_for(traits_type::to_wait_duration(_M_expiry));
    187      1.1  mrg       }, allocator<void>{});
    188      1.1  mrg     }
    189      1.1  mrg 
    190      1.1  mrg   template<typename _Clock, typename _WaitTraits>
    191      1.1  mrg     void
    192      1.1  mrg     basic_waitable_timer<_Clock, _WaitTraits>::wait(error_code&)
    193      1.1  mrg     {
    194      1.1  mrg       _M_ex.dispatch([this] {
    195      1.1  mrg 	  while (clock_type::now() < _M_expiry)
    196      1.1  mrg 	    this_thread::sleep_for(traits_type::to_wait_duration(_M_expiry));
    197      1.1  mrg       }, allocator<void>{});
    198      1.1  mrg     }
    199      1.1  mrg 
    200      1.1  mrg   /// @}
    201      1.1  mrg 
    202      1.1  mrg } // namespace v1
    203      1.1  mrg } // namespace net
    204      1.1  mrg } // namespace experimental
    205      1.1  mrg _GLIBCXX_END_NAMESPACE_VERSION
    206      1.1  mrg } // namespace std
    207      1.1  mrg 
    208      1.1  mrg #endif // C++14
    209      1.1  mrg 
    210      1.1  mrg #endif // _GLIBCXX_EXPERIMENTAL_TIMER
    211