1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2015 The Chromium Authors. All rights reserved.
2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be
3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file.
4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#ifndef MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_
6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#define MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_
7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdint.h>
9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <deque>
11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <memory>
12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <unordered_map>
13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <utility>
14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/macros.h"
16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/synchronization/lock.h"
17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/awakable_list.h"
18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/dispatcher.h"
19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/system_impl_export.h"
20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo {
22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace edk {
23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass MOJO_SYSTEM_IMPL_EXPORT WaitSetDispatcher : public Dispatcher {
25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public:
26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  WaitSetDispatcher();
27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Dispatcher:
29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  Type GetType() const override;
30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult Close() override;
31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult AddWaitingDispatcher(const scoped_refptr<Dispatcher>& dispatcher,
32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                  MojoHandleSignals signals,
33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                  uintptr_t context) override;
34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult RemoveWaitingDispatcher(
35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      const scoped_refptr<Dispatcher>& dispatcher) override;
36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult GetReadyDispatchers(uint32_t* count,
37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                 DispatcherVector* dispatchers,
38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                 MojoResult* results,
39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                 uintptr_t* contexts) override;
40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  HandleSignalsState GetHandleSignalsState() const override;
41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult AddAwakable(Awakable* awakable,
42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         MojoHandleSignals signals,
43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         uintptr_t context,
44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         HandleSignalsState* signals_state) override;
45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void RemoveAwakable(Awakable* awakable,
46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                      HandleSignalsState* signals_state) override;
47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  bool BeginTransit() override;
48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private:
50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Internal implementation of Awakable.
51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  class Waiter;
52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  struct WaitState {
54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    WaitState();
55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    WaitState(const WaitState& other);
56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    ~WaitState();
57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    scoped_refptr<Dispatcher> dispatcher;
59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    MojoHandleSignals signals;
60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    uintptr_t context;
61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  };
62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  ~WaitSetDispatcher() override;
64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  HandleSignalsState GetHandleSignalsStateNoLock() const;
66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Signal that the dispatcher indexed by |context| has been woken up with
68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // |result| and is now ready.
69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void WakeDispatcher(MojoResult result, uintptr_t context);
70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Guards |is_closed_|, |waiting_dispatchers_|, and |waiter_|.
72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  //
73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // TODO: Consider removing this.
74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  mutable base::Lock lock_;
75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  bool is_closed_ = false;
76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Map of dispatchers being waited on. Key is a Dispatcher* casted to a
78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // uintptr_t, and should be treated as an opaque value and not casted back.
79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  std::unordered_map<uintptr_t, WaitState> waiting_dispatchers_;
80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Separate lock that can be locked without locking |lock_|.
82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  mutable base::Lock awoken_lock_;
83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // List of dispatchers that have been woken up. Any dispatcher in this queue
84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // will NOT currently be waited on.
85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  std::deque<std::pair<uintptr_t, MojoResult>> awoken_queue_;
86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // List of dispatchers that have been woken up and retrieved.
87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  std::deque<uintptr_t> processed_dispatchers_;
88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Separate lock that can be locked without locking |lock_|.
90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  base::Lock awakable_lock_;
91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // List of dispatchers being waited on.
92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  AwakableList awakable_list_;
93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Waiter used to wait on dispatchers.
95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  std::unique_ptr<Waiter> waiter_;
96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DISALLOW_COPY_AND_ASSIGN(WaitSetDispatcher);
98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez};
99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace edk
101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace mojo
102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif  // MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_
104