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.
5 #include "mojo/system/local_message_pipe_endpoint.h"
9 #include "base/logging.h"
10 #include "mojo/system/dispatcher.h"
11 #include "mojo/system/message_in_transit.h"
16 LocalMessagePipeEndpoint::LocalMessagePipeEndpoint()
21 LocalMessagePipeEndpoint::~LocalMessagePipeEndpoint() {
23 DCHECK(message_queue_.IsEmpty()); // Should be implied by not being open.
26 MessagePipeEndpoint::Type LocalMessagePipeEndpoint::GetType() const {
30 bool LocalMessagePipeEndpoint::OnPeerClose() {
32 DCHECK(is_peer_open_);
34 MojoWaitFlags old_satisfied_flags = SatisfiedFlags();
35 MojoWaitFlags old_satisfiable_flags = SatisfiableFlags();
36 is_peer_open_ = false;
37 MojoWaitFlags new_satisfied_flags = SatisfiedFlags();
38 MojoWaitFlags new_satisfiable_flags = SatisfiableFlags();
40 if (new_satisfied_flags != old_satisfied_flags ||
41 new_satisfiable_flags != old_satisfiable_flags) {
42 waiter_list_.AwakeWaitersForStateChange(new_satisfied_flags,
43 new_satisfiable_flags);
49 void LocalMessagePipeEndpoint::EnqueueMessage(
50 scoped_ptr<MessageInTransit> message) {
52 DCHECK(is_peer_open_);
54 bool was_empty = message_queue_.IsEmpty();
55 message_queue_.AddMessage(message.Pass());
57 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(),
62 void LocalMessagePipeEndpoint::Close() {
65 message_queue_.Clear();
68 void LocalMessagePipeEndpoint::CancelAllWaiters() {
70 waiter_list_.CancelAllWaiters();
73 MojoResult LocalMessagePipeEndpoint::ReadMessage(void* bytes,
75 DispatcherVector* dispatchers,
76 uint32_t* num_dispatchers,
77 MojoReadMessageFlags flags) {
79 DCHECK(!dispatchers || dispatchers->empty());
81 const uint32_t max_bytes = num_bytes ? *num_bytes : 0;
82 const uint32_t max_num_dispatchers = num_dispatchers ? *num_dispatchers : 0;
84 if (message_queue_.IsEmpty()) {
85 return is_peer_open_ ? MOJO_RESULT_SHOULD_WAIT :
86 MOJO_RESULT_FAILED_PRECONDITION;
89 // TODO(vtl): If |flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD|, we could pop
90 // and release the lock immediately.
91 bool enough_space = true;
92 MessageInTransit* message = message_queue_.PeekMessage();
94 *num_bytes = message->num_bytes();
95 if (message->num_bytes() <= max_bytes)
96 memcpy(bytes, message->bytes(), message->num_bytes());
100 if (DispatcherVector* queued_dispatchers = message->dispatchers()) {
102 *num_dispatchers = static_cast<uint32_t>(queued_dispatchers->size());
104 if (queued_dispatchers->empty()) {
106 } else if (queued_dispatchers->size() <= max_num_dispatchers) {
108 dispatchers->swap(*queued_dispatchers);
110 enough_space = false;
115 *num_dispatchers = 0;
120 if (enough_space || (flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)) {
121 message_queue_.DiscardMessage();
123 // Now it's empty, thus no longer readable.
124 if (message_queue_.IsEmpty()) {
125 // It's currently not possible to wait for non-readability, but we should
126 // do the state change anyway.
127 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(),
133 return MOJO_RESULT_RESOURCE_EXHAUSTED;
135 return MOJO_RESULT_OK;
138 MojoResult LocalMessagePipeEndpoint::AddWaiter(Waiter* waiter,
140 MojoResult wake_result) {
143 if ((flags & SatisfiedFlags()))
144 return MOJO_RESULT_ALREADY_EXISTS;
145 if (!(flags & SatisfiableFlags()))
146 return MOJO_RESULT_FAILED_PRECONDITION;
148 waiter_list_.AddWaiter(waiter, flags, wake_result);
149 return MOJO_RESULT_OK;
152 void LocalMessagePipeEndpoint::RemoveWaiter(Waiter* waiter) {
154 waiter_list_.RemoveWaiter(waiter);
157 MojoWaitFlags LocalMessagePipeEndpoint::SatisfiedFlags() {
158 MojoWaitFlags satisfied_flags = 0;
159 if (!message_queue_.IsEmpty())
160 satisfied_flags |= MOJO_WAIT_FLAG_READABLE;
162 satisfied_flags |= MOJO_WAIT_FLAG_WRITABLE;
163 return satisfied_flags;
166 MojoWaitFlags LocalMessagePipeEndpoint::SatisfiableFlags() {
167 MojoWaitFlags satisfiable_flags = 0;
168 if (!message_queue_.IsEmpty() || is_peer_open_)
169 satisfiable_flags |= MOJO_WAIT_FLAG_READABLE;
171 satisfiable_flags |= MOJO_WAIT_FLAG_WRITABLE;
172 return satisfiable_flags;
175 } // namespace system