1// Copyright 2015 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef LIBBRILLO_BRILLO_MESSAGE_LOOPS_GLIB_MESSAGE_LOOP_H_
6#define LIBBRILLO_BRILLO_MESSAGE_LOOPS_GLIB_MESSAGE_LOOP_H_
7
8#include <map>
9#include <memory>
10
11#include <base/location.h>
12#include <base/time/time.h>
13#include <glib.h>
14
15#include <brillo/brillo_export.h>
16#include <brillo/message_loops/message_loop.h>
17
18namespace brillo {
19
20class BRILLO_EXPORT GlibMessageLoop : public MessageLoop {
21 public:
22  GlibMessageLoop();
23  ~GlibMessageLoop() override;
24
25  // MessageLoop overrides.
26  TaskId PostDelayedTask(const tracked_objects::Location& from_here,
27                         const base::Closure& task,
28                         base::TimeDelta delay) override;
29  using MessageLoop::PostDelayedTask;
30  TaskId WatchFileDescriptor(const tracked_objects::Location& from_here,
31                             int fd,
32                             WatchMode mode,
33                             bool persistent,
34                             const base::Closure& task) override;
35  using MessageLoop::WatchFileDescriptor;
36  bool CancelTask(TaskId task_id) override;
37  bool RunOnce(bool may_block) override;
38  void Run() override;
39  void BreakLoop() override;
40
41 private:
42  // Called by the GLib's main loop when is time to call the callback scheduled
43  // with Post*Task(). The pointer to the callback passed when scheduling it is
44  // passed to this function as a gpointer on |user_data|.
45  static gboolean OnRanPostedTask(gpointer user_data);
46
47  // Called by the GLib's main loop when the watched source |source| is
48  // ready to perform the operation given in |condition| without blocking.
49  static gboolean OnWatchedFdReady(GIOChannel *source,
50                                   GIOCondition condition,
51                                   gpointer user_data);
52
53  // Called by the GLib's main loop when the scheduled callback is removed due
54  // to it being executed or canceled.
55  static void DestroyPostedTask(gpointer user_data);
56
57  // Return a new unused task_id.
58  TaskId NextTaskId();
59
60  GMainLoop* loop_;
61
62  struct ScheduledTask {
63    // A pointer to this GlibMessageLoop so we can remove the Task from the
64    // glib callback.
65    GlibMessageLoop* loop;
66    tracked_objects::Location location;
67
68    MessageLoop::TaskId task_id;
69    guint source_id;
70    bool persistent;
71    base::Closure closure;
72  };
73
74  std::map<MessageLoop::TaskId, ScheduledTask*> tasks_;
75
76  MessageLoop::TaskId last_id_ = kTaskIdNull;
77
78  DISALLOW_COPY_AND_ASSIGN(GlibMessageLoop);
79};
80
81}  // namespace brillo
82
83#endif  // LIBBRILLO_BRILLO_MESSAGE_LOOPS_GLIB_MESSAGE_LOOP_H_
84