aboutsummaryrefslogtreecommitdiff
path: root/examples/provider/event_task_runner.h
blob: a7889504786f5811be1cdcc5b570a2b32e385520 (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
// Copyright 2015 The Weave 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 LIBWEAVE_EXAMPLES_PROVIDER_EVENT_TASK_RUNNER_H_
#define LIBWEAVE_EXAMPLES_PROVIDER_EVENT_TASK_RUNNER_H_

#include <queue>
#include <map>
#include <utility>
#include <vector>

#include <event2/event.h>
#include <weave/provider/task_runner.h>

#include "examples/provider/event_deleter.h"

namespace weave {
namespace examples {

// Simple task runner implemented with libevent message loop.
class EventTaskRunner : public provider::TaskRunner {
 public:
  void PostDelayedTask(const tracked_objects::Location& from_here,
                       const base::Closure& task,
                       base::TimeDelta delay) override;

  // Defines the types of I/O completion events that the
  // application can register to receive on a file descriptor.
  enum IOEvent : int16_t {
    kReadable = 0x01,
    kWriteable = 0x02,
    kClosed = 0x04,
    kReadableWriteable = kReadable | kWriteable,
    kReadableOrClosed = kReadable | kClosed,
    kAll = kReadableOrClosed | kWriteable,
  };

  // Callback type for I/O completion events.
  // Arguments:
  //  fd -      file descriptor that triggered the event
  //  what -    combination of IOEvent flags indicating
  //            which event(s) occurred
  //  sender -  reference to the EventTaskRunner that
  //            called the IoCompletionCallback
  using IoCompletionCallback =
      base::Callback<void(int fd, int16_t what, EventTaskRunner* sender)>;

  // Adds a handler for the specified IO completion events on a file
  // descriptor. The 'what' parameter is a combination of IOEvent flags.
  // Only one callback is allowed per file descriptor; calling this function
  // with an fd that has already been registered will replace the previous
  // callback with the new one.
  void AddIoCompletionTask(int fd,
                           int16_t what,
                           const IoCompletionCallback& task);

  // Remove the callback associated with this fd and stop listening for
  // events related to it.
  void RemoveIoCompletionTask(int fd);

  event_base* GetEventBase() const { return base_.get(); }

  void Run();

 private:
  void ReScheduleEvent(base::TimeDelta delay);
  static void EventHandler(int, int16_t, void* runner);
  static void FreeEvent(event* evnt);
  void Process();

  static void FdEventHandler(int fd, int16_t what, void* runner);
  void ProcessFd(int fd, int16_t what);

  using QueueItem = std::pair<std::pair<base::Time, size_t>, base::Closure>;

  struct Greater {
    bool operator()(const QueueItem& a, const QueueItem& b) const {
      return a.first > b.first;
    }
  };

  size_t counter_{0};  // Keeps order of tasks with the same time.

  std::priority_queue<QueueItem,
                      std::vector<QueueItem>,
                      EventTaskRunner::Greater>
      queue_;

  EventPtr<event_base> base_{event_base_new()};

  EventPtr<event> task_event_{
      event_new(base_.get(), -1, EV_TIMEOUT, &EventHandler, this)};

  std::map<int, std::pair<EventPtr<event>, IoCompletionCallback>> fd_task_map_;
};

}  // namespace examples
}  // namespace weave

#endif  // LIBWEAVE_EXAMPLES_PROVIDER_EVENT_TASK_RUNNER_H_