// without accessing the handle table. These can be dumb pointers, since their
// entries in the handle table won't get removed (since they'll be marked as
// busy).
- std::vector<Dispatcher*> dispatchers(num_handles);
+ std::vector<DispatcherTransport> transports(num_handles);
// When we pass handles, we have to try to take all their dispatchers' locks
// and mark the handles as busy. If the call succeeds, we then remove the
// same handle from being sent multiple times in the same message.
entries[i]->busy = true;
- // Try to take the lock.
- if (!entries[i]->dispatcher->lock().Try()) {
+ // Try to start the transport.
+ DispatcherTransport transport =
+ Dispatcher::CoreImplAccess::TryStartTransport(
+ entries[i]->dispatcher.get());
+ if (!transport.is_valid()) {
// Unset the busy flag (since it won't be unset below).
entries[i]->busy = false;
error_result = MOJO_RESULT_BUSY;
break;
}
- // We shouldn't race with things that close dispatchers, since closing can
- // only take place either under |handle_table_lock_| or when the handle is
- // marked as busy.
- DCHECK(!entries[i]->dispatcher->is_closed_no_lock());
+ // Check if the dispatcher is busy (e.g., in a two-phase read/write).
+ // (Note that this must be done after the dispatcher's lock is acquired.)
+ if (transport.IsBusy()) {
+ // Unset the busy flag and end the transport (since it won't be done
+ // below).
+ entries[i]->busy = false;
+ transport.End();
+ error_result = MOJO_RESULT_BUSY;
+ break;
+ }
- // Hang on to the pointer to the dispatcher (which we'll need to release
- // the lock without going through the handle table).
- dispatchers[i] = entries[i]->dispatcher;
+ // Hang on to the transport (which we'll need to end the transport).
+ transports[i] = transport;
}
if (i < num_handles) {
DCHECK_NE(error_result, MOJO_RESULT_INTERNAL);
for (uint32_t j = 0; j < i; j++) {
DCHECK(entries[j]->busy);
entries[j]->busy = false;
- entries[j]->dispatcher->lock().Release();
+ transports[j].End();
}
return error_result;
}
}
- MojoResult rv = dispatcher->WriteMessage(bytes, num_bytes,
- &dispatchers,
+ MojoResult rv = dispatcher->WriteMessage(bytes, num_bytes, &transports,
flags);
// We need to release the dispatcher locks before we take the handle table
// lock.
- for (uint32_t i = 0; i < num_handles; i++) {
- dispatchers[i]->lock().AssertAcquired();
- dispatchers[i]->lock().Release();
- }
+ for (uint32_t i = 0; i < num_handles; i++)
+ transports[i].End();
if (rv == MOJO_RESULT_OK) {
base::AutoLock locker(handle_table_lock_);
// here? Currently, we'll just fill in those handles with
// |MOJO_HANDLE_INVALID| (and return success anyway).
handles[i] = AddDispatcherNoLock(dispatchers[i]);
+ LOG_IF(ERROR, handles[i] == MOJO_HANDLE_INVALID)
+ << "Failed to add dispatcher (" << dispatchers[i].get() << ")";
}
}
return dispatcher->EndReadData(num_bytes_read);
}
+MojoResult CoreImpl::CreateSharedBuffer(
+ const MojoCreateSharedBufferOptions* options,
+ uint64_t* num_bytes,
+ MojoHandle* shared_buffer_handle) {
+ // TODO(vtl)
+ NOTIMPLEMENTED();
+ return MOJO_RESULT_UNIMPLEMENTED;
+}
+
+MojoResult CoreImpl::DuplicateBufferHandle(
+ MojoHandle buffer_handle,
+ const MojoDuplicateBufferHandleOptions* options,
+ MojoHandle* new_buffer_handle) {
+ // TODO(vtl)
+ NOTIMPLEMENTED();
+ return MOJO_RESULT_UNIMPLEMENTED;
+}
+
+MojoResult CoreImpl::MapBuffer(MojoHandle buffer_handle,
+ uint64_t offset,
+ uint64_t num_bytes,
+ void** buffer,
+ MojoMapBufferFlags flags) {
+ // TODO(vtl)
+ NOTIMPLEMENTED();
+ return MOJO_RESULT_UNIMPLEMENTED;
+}
+
+MojoResult CoreImpl::UnmapBuffer(void* buffer) {
+ // TODO(vtl)
+ NOTIMPLEMENTED();
+ return MOJO_RESULT_UNIMPLEMENTED;
+}
+
scoped_refptr<Dispatcher> CoreImpl::GetDispatcher(MojoHandle handle) {
if (handle == MOJO_HANDLE_INVALID)
return NULL;
MojoHandle CoreImpl::AddDispatcherNoLock(
const scoped_refptr<Dispatcher>& dispatcher) {
- DCHECK(dispatcher.get());
handle_table_lock_.AssertAcquired();
DCHECK_NE(next_handle_, MOJO_HANDLE_INVALID);
- if (handle_table_.size() >= kMaxHandleTableSize)
+ if (!dispatcher.get() || handle_table_.size() >= kMaxHandleTableSize)
return MOJO_HANDLE_INVALID;
// TODO(vtl): Maybe we want to do something different/smarter. (Or maybe try