summaryrefslogtreecommitdiff
path: root/NodeStateAccess/SimpleTimer.h
blob: 523f916a7b75ee4c760740cd09ee3a7b391195fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**********************************************************************************************************************
 *
 * Copyright (C) 2017 BMW AG
 *
 * Interface between NodeStateManager and IPC
 *
 * This source file is a part of the NodeStateAccess library (NSMA).
 * The architecture requires that the NodeStateManager (NSM) is independent from the CommonAPI binding.
 * Therefore, the CommonAPI communication is handled inside of this library.
 * The library offers the NSM an interface to use objects generated via CommonAPI.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 **********************************************************************************************************************/

#ifndef NODESTATEACCESS_SIMPLETIMER_H_
#define NODESTATEACCESS_SIMPLETIMER_H_

#include <functional>
#include <chrono>
#include <future>
#include <cstdio>
#include <iostream>
#include "Watchdog.hpp"

class SimpleTimer
{
private:
   std::mutex mMutex;
   std::condition_variable mCondVar;
   std::condition_variable mCondVarJoin;
   bool joined = false;
public:
   std::shared_ptr<SimpleTimer> self;
   volatile uint timerLock;
   template<class callable, class ... arguments>
      SimpleTimer(int timeOut, int timerLocks, callable&& f, arguments&&... args)
      {
         std::function<typename std::result_of<callable(arguments...)>::type()> task(std::bind(std::forward<callable>(f), std::forward<arguments>(args)...));
         timerLock = timerLocks;

         std::thread([this, timeOut, task]()
         {
            NSMTriggerWatchdog(NsmWatchdogState_Active);
            std::unique_lock<std::mutex> lock(mMutex);

            while (timerLock > 0)
            {
               NSMTriggerWatchdog(NsmWatchdogState_Sleep);
               if (std::cv_status::timeout == mCondVar.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::milliseconds(timeOut)))
               {
                  NSMTriggerWatchdog(NsmWatchdogState_Active);
                  break;
               }
               NSMTriggerWatchdog(NsmWatchdogState_Active);
            }

            if(timerLock > 0)
            {
               lock.unlock();
               task();
               lock.lock();
            }
            NSMUnregisterWatchdog();

            joined = true;
            mCondVarJoin.notify_all();
            lock.unlock();

            /* Set own pointer to NULL - timer can be automatically deleted from now on */
            self = NULL;
         }).detach();
      };

   ~SimpleTimer();

   /**
    * SimpleTimer starts a thread which executes a callback after timeOut milliseconds.
    * It is possible to cancel the execution of this callback by calling cancel.
    * The constructor is hidden. This way it is ensured that all timers are created with new.
    * After the timer has finished it will destroy itself.
    */
   template<class callable, class ... arguments>
   static std::shared_ptr<SimpleTimer> CreateTimer(int timeOut, int timerLocks, callable&& f, arguments&&... args)
   {
      std::shared_ptr<SimpleTimer> timer = std::make_shared<SimpleTimer>(timeOut, timerLocks, std::forward<callable>(f), std::forward<arguments>(args)...);
      /* Save timer in timer itself so it will only be cleaned when thread has finished*/
      timer->self = timer;
      return timer;
   }

   /**
    * This function decrements the timerLocks by one. timerLocks has been initialized in CreateTimer.
    * When this locks have reached zero the timer is considered as canceled/deprecated
    * and the specified task will not be executed anymore.
    */
   void cancelTimer();
   void stopTimer();
   void joinTimer();

};

#endif /* NODESTATEACCESS_SIMPLETIMER_H_ */