| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "mojo/system/dispatcher.h" |
| |
| #include "base/logging.h" |
| #include "mojo/system/constants.h" |
| |
| namespace mojo { |
| namespace system { |
| |
| MojoResult Dispatcher::Close() { |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| is_closed_ = true; |
| CancelAllWaitersNoLock(); |
| return CloseImplNoLock(); |
| } |
| |
| MojoResult Dispatcher::WriteMessage(const void* bytes, |
| uint32_t num_bytes, |
| const std::vector<Dispatcher*>* dispatchers, |
| MojoWriteMessageFlags flags) { |
| DCHECK(!dispatchers || (dispatchers->size() > 0 && |
| dispatchers->size() < kMaxMessageNumHandles)); |
| |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| return WriteMessageImplNoLock(bytes, num_bytes, dispatchers, flags); |
| } |
| |
| MojoResult Dispatcher::ReadMessage( |
| void* bytes, |
| uint32_t* num_bytes, |
| std::vector<scoped_refptr<Dispatcher> >* dispatchers, |
| uint32_t* num_dispatchers, |
| MojoReadMessageFlags flags) { |
| DCHECK(!num_dispatchers || *num_dispatchers == 0 || |
| (dispatchers && dispatchers->empty())); |
| |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| return ReadMessageImplNoLock(bytes, num_bytes, dispatchers, num_dispatchers, |
| flags); |
| } |
| |
| MojoResult Dispatcher::WriteData(const void* elements, |
| uint32_t* num_elements, |
| MojoWriteDataFlags flags) { |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| return WriteDataImplNoLock(elements, num_elements, flags); |
| } |
| |
| MojoResult Dispatcher::BeginWriteData(void** buffer, |
| uint32_t* buffer_num_elements, |
| MojoWriteDataFlags flags) { |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| return BeginWriteDataImplNoLock(buffer, buffer_num_elements, flags); |
| } |
| |
| MojoResult Dispatcher::EndWriteData(uint32_t num_elements_written) { |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| return EndWriteDataImplNoLock(num_elements_written); |
| } |
| |
| MojoResult Dispatcher::ReadData(void* elements, |
| uint32_t* num_elements, |
| MojoReadDataFlags flags) { |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| return ReadDataImplNoLock(elements, num_elements, flags); |
| } |
| |
| MojoResult Dispatcher::BeginReadData(const void** buffer, |
| uint32_t* buffer_num_elements, |
| MojoReadDataFlags flags) { |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| return BeginReadDataImplNoLock(buffer, buffer_num_elements, flags); |
| } |
| |
| MojoResult Dispatcher::EndReadData(uint32_t num_elements_read) { |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| return EndReadDataImplNoLock(num_elements_read); |
| } |
| |
| MojoResult Dispatcher::AddWaiter(Waiter* waiter, |
| MojoWaitFlags flags, |
| MojoResult wake_result) { |
| DCHECK_GE(wake_result, 0); |
| |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| |
| return AddWaiterImplNoLock(waiter, flags, wake_result); |
| } |
| |
| void Dispatcher::RemoveWaiter(Waiter* waiter) { |
| base::AutoLock locker(lock_); |
| if (is_closed_) |
| return; |
| RemoveWaiterImplNoLock(waiter); |
| } |
| |
| scoped_refptr<Dispatcher> |
| Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| |
| is_closed_ = true; |
| CancelAllWaitersNoLock(); |
| return CreateEquivalentDispatcherAndCloseImplNoLock(); |
| } |
| |
| Dispatcher::Dispatcher() |
| : is_closed_(false) { |
| } |
| |
| Dispatcher::~Dispatcher() { |
| // Make sure that |Close()| was called. |
| DCHECK(is_closed_); |
| } |
| |
| void Dispatcher::CancelAllWaitersNoLock() { |
| lock_.AssertAcquired(); |
| DCHECK(is_closed_); |
| // By default, waiting isn't supported. Only dispatchers that can be waited on |
| // will do something nontrivial. |
| } |
| |
| MojoResult Dispatcher::CloseImplNoLock() { |
| lock_.AssertAcquired(); |
| DCHECK(is_closed_); |
| // This may not need to do anything. Dispatchers should override this to do |
| // any actual close-time cleanup necessary. |
| return MOJO_RESULT_OK; |
| } |
| |
| MojoResult Dispatcher::WriteMessageImplNoLock( |
| const void* bytes, |
| uint32_t num_bytes, |
| const std::vector<Dispatcher*>* dispatchers, |
| MojoWriteMessageFlags flags) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, not supported. Only needed for message pipe dispatchers. |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| } |
| |
| MojoResult Dispatcher::ReadMessageImplNoLock( |
| void* /*bytes*/, |
| uint32_t* /*num_bytes*/, |
| std::vector<scoped_refptr<Dispatcher> >* /*dispatchers*/, |
| uint32_t* /*num_dispatchers*/, |
| MojoReadMessageFlags /*flags*/) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, not supported. Only needed for message pipe dispatchers. |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| } |
| |
| MojoResult Dispatcher::WriteDataImplNoLock(const void* /*elements*/, |
| uint32_t* /*num_elements*/, |
| MojoWriteDataFlags /*flags*/) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, not supported. Only needed for data pipe dispatchers. |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| } |
| |
| MojoResult Dispatcher::BeginWriteDataImplNoLock( |
| void** /*buffer*/, |
| uint32_t* /*buffer_num_elements*/, |
| MojoWriteDataFlags /*flags*/) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, not supported. Only needed for data pipe dispatchers. |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| } |
| |
| MojoResult Dispatcher::EndWriteDataImplNoLock( |
| uint32_t /*num_elements_written*/) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, not supported. Only needed for data pipe dispatchers. |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| } |
| |
| MojoResult Dispatcher::ReadDataImplNoLock(void* /*elements*/, |
| uint32_t* /*num_elements*/, |
| MojoReadDataFlags /*flags*/) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, not supported. Only needed for data pipe dispatchers. |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| } |
| |
| MojoResult Dispatcher::BeginReadDataImplNoLock( |
| const void** /*buffer*/, |
| uint32_t* /*buffer_num_elements*/, |
| MojoReadDataFlags /*flags*/) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, not supported. Only needed for data pipe dispatchers. |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| } |
| |
| MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_elements_read*/) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, not supported. Only needed for data pipe dispatchers. |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| } |
| |
| MojoResult Dispatcher::AddWaiterImplNoLock(Waiter* /*waiter*/, |
| MojoWaitFlags /*flags*/, |
| MojoResult /*wake_result*/) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, waiting isn't supported. Only dispatchers that can be waited on |
| // will do something nontrivial. |
| return MOJO_RESULT_FAILED_PRECONDITION; |
| } |
| |
| void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/) { |
| lock_.AssertAcquired(); |
| DCHECK(!is_closed_); |
| // By default, waiting isn't supported. Only dispatchers that can be waited on |
| // will do something nontrivial. |
| } |
| |
| } // namespace system |
| } // namespace mojo |