1 /* Copyright 2016, Ableton AG, Berlin. All rights reserved.
2  *
3  *  This program is free software: you can redistribute it and/or modify
4  *  it under the terms of the GNU General Public License as published by
5  *  the Free Software Foundation, either version 2 of the License, or
6  *  (at your option) any later version.
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  *  If you would like to incorporate Link into a proprietary software application,
17  *  please contact <link-devs@ableton.com>.
18  */
19 
20 #pragma once
21 
22 #include <chrono>
23 #include <functional>
24 
25 namespace ableton
26 {
27 namespace util
28 {
29 namespace test
30 {
31 
32 struct Timer
33 {
34   using ErrorCode = int;
35   using TimePoint = std::chrono::system_clock::time_point;
36 
37   // Initialize timer with an arbitrary large value to simulate the
38   // time_since_epoch of a real clock.
Timerableton::util::test::Timer39   Timer()
40     : mNow{std::chrono::milliseconds{123456789}}
41   {
42   }
43 
expires_atableton::util::test::Timer44   void expires_at(std::chrono::system_clock::time_point t)
45   {
46     cancel();
47     mFireAt = std::move(t);
48   }
49 
50   template <typename T, typename Rep>
expires_from_nowableton::util::test::Timer51   void expires_from_now(std::chrono::duration<T, Rep> duration)
52   {
53     cancel();
54     mFireAt = now() + duration;
55   }
56 
cancelableton::util::test::Timer57   ErrorCode cancel()
58   {
59     if (mHandler)
60     {
61       mHandler(1); // call existing handler with truthy error code
62     }
63     mHandler = nullptr;
64     return 0;
65   }
66 
67   template <typename Handler>
async_waitableton::util::test::Timer68   void async_wait(Handler handler)
69   {
70     mHandler = [handler](ErrorCode ec) { handler(ec); };
71   }
72 
nowableton::util::test::Timer73   std::chrono::system_clock::time_point now() const
74   {
75     return mNow;
76   }
77 
78   template <typename T, typename Rep>
advanceableton::util::test::Timer79   void advance(std::chrono::duration<T, Rep> duration)
80   {
81     mNow += duration;
82     if (mHandler && mFireAt < mNow)
83     {
84       mHandler(0);
85       mHandler = nullptr;
86     }
87   }
88 
89   std::function<void(ErrorCode)> mHandler;
90   std::chrono::system_clock::time_point mFireAt;
91   std::chrono::system_clock::time_point mNow;
92 };
93 
94 } // namespace test
95 } // namespace util
96 } // namespace ableton
97