1// Copyright 2013 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#include "mojo/system/dispatcher.h"
6
7#include "base/logging.h"
8#include "mojo/system/constants.h"
9
10namespace mojo {
11namespace system {
12
13MojoResult Dispatcher::Close() {
14  base::AutoLock locker(lock_);
15  if (is_closed_)
16    return MOJO_RESULT_INVALID_ARGUMENT;
17
18  is_closed_ = true;
19  CancelAllWaitersNoLock();
20  return CloseImplNoLock();
21}
22
23MojoResult Dispatcher::WriteMessage(const void* bytes,
24                                    uint32_t num_bytes,
25                                    const std::vector<Dispatcher*>* dispatchers,
26                                    MojoWriteMessageFlags flags) {
27  DCHECK(!dispatchers || (dispatchers->size() > 0 &&
28                          dispatchers->size() < kMaxMessageNumHandles));
29
30  base::AutoLock locker(lock_);
31  if (is_closed_)
32    return MOJO_RESULT_INVALID_ARGUMENT;
33
34  return WriteMessageImplNoLock(bytes, num_bytes, dispatchers, flags);
35}
36
37MojoResult Dispatcher::ReadMessage(
38    void* bytes,
39    uint32_t* num_bytes,
40    std::vector<scoped_refptr<Dispatcher> >* dispatchers,
41    uint32_t* num_dispatchers,
42    MojoReadMessageFlags flags) {
43  DCHECK(!num_dispatchers || *num_dispatchers == 0 ||
44         (dispatchers && dispatchers->empty()));
45
46  base::AutoLock locker(lock_);
47  if (is_closed_)
48    return MOJO_RESULT_INVALID_ARGUMENT;
49
50  return ReadMessageImplNoLock(bytes, num_bytes, dispatchers, num_dispatchers,
51                               flags);
52}
53
54MojoResult Dispatcher::WriteData(const void* elements,
55                                 uint32_t* num_elements,
56                                 MojoWriteDataFlags flags) {
57  base::AutoLock locker(lock_);
58  if (is_closed_)
59    return MOJO_RESULT_INVALID_ARGUMENT;
60
61  return WriteDataImplNoLock(elements, num_elements, flags);
62}
63
64MojoResult Dispatcher::BeginWriteData(void** buffer,
65                                      uint32_t* buffer_num_elements,
66                                      MojoWriteDataFlags flags) {
67  base::AutoLock locker(lock_);
68  if (is_closed_)
69    return MOJO_RESULT_INVALID_ARGUMENT;
70
71  return BeginWriteDataImplNoLock(buffer, buffer_num_elements, flags);
72}
73
74MojoResult Dispatcher::EndWriteData(uint32_t num_elements_written) {
75  base::AutoLock locker(lock_);
76  if (is_closed_)
77    return MOJO_RESULT_INVALID_ARGUMENT;
78
79  return EndWriteDataImplNoLock(num_elements_written);
80}
81
82MojoResult Dispatcher::ReadData(void* elements,
83                                uint32_t* num_elements,
84                                MojoReadDataFlags flags) {
85  base::AutoLock locker(lock_);
86  if (is_closed_)
87    return MOJO_RESULT_INVALID_ARGUMENT;
88
89  return ReadDataImplNoLock(elements, num_elements, flags);
90}
91
92MojoResult Dispatcher::BeginReadData(const void** buffer,
93                                     uint32_t* buffer_num_elements,
94                                     MojoReadDataFlags flags) {
95  base::AutoLock locker(lock_);
96  if (is_closed_)
97    return MOJO_RESULT_INVALID_ARGUMENT;
98
99  return BeginReadDataImplNoLock(buffer, buffer_num_elements, flags);
100}
101
102MojoResult Dispatcher::EndReadData(uint32_t num_elements_read) {
103  base::AutoLock locker(lock_);
104  if (is_closed_)
105    return MOJO_RESULT_INVALID_ARGUMENT;
106
107  return EndReadDataImplNoLock(num_elements_read);
108}
109
110MojoResult Dispatcher::AddWaiter(Waiter* waiter,
111                                 MojoWaitFlags flags,
112                                 MojoResult wake_result) {
113  DCHECK_GE(wake_result, 0);
114
115  base::AutoLock locker(lock_);
116  if (is_closed_)
117    return MOJO_RESULT_INVALID_ARGUMENT;
118
119  return AddWaiterImplNoLock(waiter, flags, wake_result);
120}
121
122void Dispatcher::RemoveWaiter(Waiter* waiter) {
123  base::AutoLock locker(lock_);
124  if (is_closed_)
125    return;
126  RemoveWaiterImplNoLock(waiter);
127}
128
129scoped_refptr<Dispatcher>
130Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
131  lock_.AssertAcquired();
132  DCHECK(!is_closed_);
133
134  is_closed_ = true;
135  CancelAllWaitersNoLock();
136  return CreateEquivalentDispatcherAndCloseImplNoLock();
137}
138
139Dispatcher::Dispatcher()
140    : is_closed_(false) {
141}
142
143Dispatcher::~Dispatcher() {
144  // Make sure that |Close()| was called.
145  DCHECK(is_closed_);
146}
147
148void Dispatcher::CancelAllWaitersNoLock() {
149  lock_.AssertAcquired();
150  DCHECK(is_closed_);
151  // By default, waiting isn't supported. Only dispatchers that can be waited on
152  // will do something nontrivial.
153}
154
155MojoResult Dispatcher::CloseImplNoLock() {
156  lock_.AssertAcquired();
157  DCHECK(is_closed_);
158  // This may not need to do anything. Dispatchers should override this to do
159  // any actual close-time cleanup necessary.
160  return MOJO_RESULT_OK;
161}
162
163MojoResult Dispatcher::WriteMessageImplNoLock(
164    const void* bytes,
165    uint32_t num_bytes,
166    const std::vector<Dispatcher*>* dispatchers,
167    MojoWriteMessageFlags flags) {
168  lock_.AssertAcquired();
169  DCHECK(!is_closed_);
170  // By default, not supported. Only needed for message pipe dispatchers.
171  return MOJO_RESULT_INVALID_ARGUMENT;
172}
173
174MojoResult Dispatcher::ReadMessageImplNoLock(
175    void* /*bytes*/,
176    uint32_t* /*num_bytes*/,
177    std::vector<scoped_refptr<Dispatcher> >* /*dispatchers*/,
178    uint32_t* /*num_dispatchers*/,
179    MojoReadMessageFlags /*flags*/) {
180  lock_.AssertAcquired();
181  DCHECK(!is_closed_);
182  // By default, not supported. Only needed for message pipe dispatchers.
183  return MOJO_RESULT_INVALID_ARGUMENT;
184}
185
186MojoResult Dispatcher::WriteDataImplNoLock(const void* /*elements*/,
187                                           uint32_t* /*num_elements*/,
188                                           MojoWriteDataFlags /*flags*/) {
189  lock_.AssertAcquired();
190  DCHECK(!is_closed_);
191  // By default, not supported. Only needed for data pipe dispatchers.
192  return MOJO_RESULT_INVALID_ARGUMENT;
193}
194
195MojoResult Dispatcher::BeginWriteDataImplNoLock(
196    void** /*buffer*/,
197    uint32_t* /*buffer_num_elements*/,
198    MojoWriteDataFlags /*flags*/) {
199  lock_.AssertAcquired();
200  DCHECK(!is_closed_);
201  // By default, not supported. Only needed for data pipe dispatchers.
202  return MOJO_RESULT_INVALID_ARGUMENT;
203}
204
205MojoResult Dispatcher::EndWriteDataImplNoLock(
206    uint32_t /*num_elements_written*/) {
207  lock_.AssertAcquired();
208  DCHECK(!is_closed_);
209  // By default, not supported. Only needed for data pipe dispatchers.
210  return MOJO_RESULT_INVALID_ARGUMENT;
211}
212
213MojoResult Dispatcher::ReadDataImplNoLock(void* /*elements*/,
214                                          uint32_t* /*num_elements*/,
215                                          MojoReadDataFlags /*flags*/) {
216  lock_.AssertAcquired();
217  DCHECK(!is_closed_);
218  // By default, not supported. Only needed for data pipe dispatchers.
219  return MOJO_RESULT_INVALID_ARGUMENT;
220}
221
222MojoResult Dispatcher::BeginReadDataImplNoLock(
223    const void** /*buffer*/,
224    uint32_t* /*buffer_num_elements*/,
225    MojoReadDataFlags /*flags*/) {
226  lock_.AssertAcquired();
227  DCHECK(!is_closed_);
228  // By default, not supported. Only needed for data pipe dispatchers.
229  return MOJO_RESULT_INVALID_ARGUMENT;
230}
231
232MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_elements_read*/) {
233  lock_.AssertAcquired();
234  DCHECK(!is_closed_);
235  // By default, not supported. Only needed for data pipe dispatchers.
236  return MOJO_RESULT_INVALID_ARGUMENT;
237}
238
239MojoResult Dispatcher::AddWaiterImplNoLock(Waiter* /*waiter*/,
240                                           MojoWaitFlags /*flags*/,
241                                           MojoResult /*wake_result*/) {
242  lock_.AssertAcquired();
243  DCHECK(!is_closed_);
244  // By default, waiting isn't supported. Only dispatchers that can be waited on
245  // will do something nontrivial.
246  return MOJO_RESULT_FAILED_PRECONDITION;
247}
248
249void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/) {
250  lock_.AssertAcquired();
251  DCHECK(!is_closed_);
252  // By default, waiting isn't supported. Only dispatchers that can be waited on
253  // will do something nontrivial.
254}
255
256}  // namespace system
257}  // namespace mojo
258