// 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/data_pipe_consumer_dispatcher.h" #include "base/logging.h" #include "mojo/system/data_pipe.h" #include "mojo/system/memory.h" namespace mojo { namespace system { DataPipeConsumerDispatcher::DataPipeConsumerDispatcher() { } void DataPipeConsumerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) { DCHECK(data_pipe.get()); data_pipe_ = data_pipe; } DataPipeConsumerDispatcher::~DataPipeConsumerDispatcher() { // |Close()|/|CloseImplNoLock()| should have taken care of the pipe. DCHECK(!data_pipe_.get()); } void DataPipeConsumerDispatcher::CancelAllWaitersNoLock() { lock().AssertAcquired(); data_pipe_->ConsumerCancelAllWaiters(); } MojoResult DataPipeConsumerDispatcher::CloseImplNoLock() { lock().AssertAcquired(); data_pipe_->ConsumerClose(); data_pipe_ = NULL; return MOJO_RESULT_OK; } MojoResult DataPipeConsumerDispatcher::ReadDataImplNoLock( void* elements, uint32_t* num_elements, MojoReadDataFlags flags) { lock().AssertAcquired(); if (!VerifyUserPointer<uint32_t>(num_elements, 1)) return MOJO_RESULT_INVALID_ARGUMENT; // These flags are mutally exclusive. if ((flags & MOJO_READ_DATA_FLAG_DISCARD) && (flags & MOJO_READ_DATA_FLAG_QUERY)) return MOJO_RESULT_INVALID_ARGUMENT; if ((flags & MOJO_READ_DATA_FLAG_DISCARD) || (flags & MOJO_READ_DATA_FLAG_QUERY)) { DVLOG_IF(2, elements) << "Discard/query mode: ignoring non-null |elements|"; elements = NULL; // Null it out for safety. } else { // Only verify |elements| if we're neither discarding nor querying. if (!VerifyUserPointerForSize(elements, data_pipe_->element_size(), *num_elements)) return MOJO_RESULT_INVALID_ARGUMENT; } return data_pipe_->ConsumerReadData(elements, num_elements, flags); } MojoResult DataPipeConsumerDispatcher::BeginReadDataImplNoLock( const void** buffer, uint32_t* buffer_num_elements, MojoReadDataFlags flags) { lock().AssertAcquired(); if (!VerifyUserPointer<const void*>(buffer, 1)) return MOJO_RESULT_INVALID_ARGUMENT; if (!VerifyUserPointer<uint32_t>(buffer_num_elements, 1)) return MOJO_RESULT_INVALID_ARGUMENT; // These flags may not be used in two-phase mode. if ((flags & MOJO_READ_DATA_FLAG_DISCARD) || (flags & MOJO_READ_DATA_FLAG_QUERY)) return MOJO_RESULT_INVALID_ARGUMENT; return data_pipe_->ConsumerBeginReadData(buffer, buffer_num_elements, flags); } MojoResult DataPipeConsumerDispatcher::EndReadDataImplNoLock( uint32_t num_elements_read) { lock().AssertAcquired(); return data_pipe_->ConsumerEndReadData(num_elements_read); } MojoResult DataPipeConsumerDispatcher::AddWaiterImplNoLock( Waiter* waiter, MojoWaitFlags flags, MojoResult wake_result) { lock().AssertAcquired(); return data_pipe_->ConsumerAddWaiter(waiter, flags, wake_result); } void DataPipeConsumerDispatcher::RemoveWaiterImplNoLock(Waiter* waiter) { lock().AssertAcquired(); data_pipe_->ConsumerRemoveWaiter(waiter); } scoped_refptr<Dispatcher> DataPipeConsumerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { lock().AssertAcquired(); scoped_refptr<DataPipeConsumerDispatcher> rv = new DataPipeConsumerDispatcher(); rv->Init(data_pipe_); data_pipe_ = NULL; return scoped_refptr<Dispatcher>(rv.get()); } } // namespace system } // namespace mojo