• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium 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 MOJO_PUBLIC_CPP_BINDINGS_SYNC_HANDLE_REGISTRY_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_SYNC_HANDLE_REGISTRY_H_
7 
8 #include <map>
9 
10 #include "base/callback.h"
11 #include "base/containers/stack_container.h"
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/sequence_checker.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "mojo/public/cpp/bindings/bindings_export.h"
17 #include "mojo/public/cpp/system/core.h"
18 #include "mojo/public/cpp/system/wait_set.h"
19 
20 namespace mojo {
21 
22 // SyncHandleRegistry is a sequence-local storage to register handles that want
23 // to be watched together.
24 //
25 // This class is thread unsafe.
26 class MOJO_CPP_BINDINGS_EXPORT SyncHandleRegistry
27     : public base::RefCounted<SyncHandleRegistry> {
28  public:
29   // Returns a sequence-local object.
30   static scoped_refptr<SyncHandleRegistry> current();
31 
32   using HandleCallback = base::Callback<void(MojoResult)>;
33 
34   // Registers a |Handle| to be watched for |handle_signals|. If any such
35   // signals are satisfied during a Wait(), the Wait() is woken up and
36   // |callback| is run.
37   bool RegisterHandle(const Handle& handle,
38                       MojoHandleSignals handle_signals,
39                       const HandleCallback& callback);
40 
41   void UnregisterHandle(const Handle& handle);
42 
43   // Registers a |base::WaitableEvent| which can be used to wake up
44   // Wait() before any handle signals. |event| is not owned, and if it signals
45   // during Wait(), |callback| is invoked.  Note that |event| may be registered
46   // multiple times with different callbacks.
47   void RegisterEvent(base::WaitableEvent* event, const base::Closure& callback);
48 
49   // Unregisters a specific |event|+|callback| pair.
50   void UnregisterEvent(base::WaitableEvent* event,
51                        const base::Closure& callback);
52 
53   // Waits on all the registered handles and events and runs callbacks
54   // synchronously for any that become ready.
55   // The method:
56   //   - returns true when any element of |should_stop| is set to true;
57   //   - returns false when any error occurs.
58   bool Wait(const bool* should_stop[], size_t count);
59 
60  private:
61   friend class base::RefCounted<SyncHandleRegistry>;
62 
63   using EventCallbackList = base::StackVector<base::Closure, 1>;
64   using EventMap = std::map<base::WaitableEvent*, EventCallbackList>;
65 
66   SyncHandleRegistry();
67   ~SyncHandleRegistry();
68 
69   void RemoveInvalidEventCallbacks();
70 
71   WaitSet wait_set_;
72   std::map<Handle, HandleCallback> handles_;
73   EventMap events_;
74 
75   // |true| iff this registry is currently dispatching event callbacks in
76   // Wait(). Used to allow for safe event registration/unregistration from event
77   // callbacks.
78   bool is_dispatching_event_callbacks_ = false;
79 
80   // Indicates if one or more event callbacks was unregistered during the most
81   // recent event callback dispatch.
82   bool remove_invalid_event_callbacks_after_dispatch_ = false;
83 
84   SEQUENCE_CHECKER(sequence_checker_);
85 
86   DISALLOW_COPY_AND_ASSIGN(SyncHandleRegistry);
87 };
88 
89 }  // namespace mojo
90 
91 #endif  // MOJO_PUBLIC_CPP_BINDINGS_SYNC_HANDLE_REGISTRY_H_
92