aboutsummaryrefslogtreecommitdiff
path: root/util/operation_loop.h
blob: ddb7846f4beef1322771ead2e648a3d70dfc34d6 (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
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UTIL_OPERATION_LOOP_H_
#define UTIL_OPERATION_LOOP_H_

#include <atomic>
#include <condition_variable>
#include <functional>
#include <vector>

#include "platform/api/time.h"
#include "platform/base/macros.h"

namespace openscreen {

class OperationLoop {
 public:
  using OperationWithTimeout = std::function<void(Clock::duration)>;

  // Creates a new OperationLoop from a variable number of operations. The
  // provided functions will be called repeatedly, at a minimum interval equal
  // to min_loop_execution_time, and are expected to exit after the time period
  // provided to their call has passed. This is because some operations may not
  // be safe to be interrupted from this class.
  // NOTE: If n operations are provided with operation timeout T, each iteration
  // of the operation loop may take as long as n * T, and will not exit after
  // min_loop_execution_time has elapsed. In order to avoid this behavior, the
  // caller can set min_loop_execution_time = n * T.
  //
  // operations = Functions to execute repeatedly. All functions are expected to
  //              be valid the duration of this object's lifetime.
  // timeout = Timeout for each individual function above.
  // min_loop_execution_time = Minimum time that OperationLoop should wait
  //                           before successive calls to members of the
  //                           provided operations vector.
  OperationLoop(std::vector<OperationWithTimeout> operations,
                Clock::duration timeout,
                Clock::duration min_loop_execution_time);

  // Runs the PerformAllOperations function in a loop until the below
  // RequestStopSoon function is called.
  void RunUntilStopped();

  // Signals for the RunUntilStopped loop to cease running.
  void RequestStopSoon();

  OSP_DISALLOW_COPY_AND_ASSIGN(OperationLoop);

 private:
  // Performs all operations which have been provided to this instance.
  void PerformAllOperations();

  const Clock::duration perform_all_operations_min_execution_time_;

  const Clock::duration operation_timeout_;

  // Used to wait in PerformAllOperations() if not enough time has elapsed.
  std::condition_variable perform_all_operations_waiter_;

  // Mutex used by the above condition_variable.
  std::mutex wait_mutex_;

  // Represents whether this instance is currently "running".
  std::atomic_bool is_running_{false};

  // Operations currently being run by this object.
  const std::vector<OperationWithTimeout> operations_;
};

}  // namespace openscreen

#endif  // UTIL_OPERATION_LOOP_H_