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 void LocalMessagePipeEndpoint::Close() {
33 message_queue_.Clear();
36 void LocalMessagePipeEndpoint::OnPeerClose() {
38 DCHECK(is_peer_open_);
40 MojoWaitFlags old_satisfied_flags = SatisfiedFlags();
41 MojoWaitFlags old_satisfiable_flags = SatisfiableFlags();
42 is_peer_open_ = false;
43 MojoWaitFlags new_satisfied_flags = SatisfiedFlags();
44 MojoWaitFlags new_satisfiable_flags = SatisfiableFlags();
46 if (new_satisfied_flags != old_satisfied_flags ||
47 new_satisfiable_flags != old_satisfiable_flags) {
48 waiter_list_.AwakeWaitersForStateChange(new_satisfied_flags,
49 new_satisfiable_flags);
53 void LocalMessagePipeEndpoint::EnqueueMessage(
54 scoped_ptr<MessageInTransit> message) {
56 DCHECK(is_peer_open_);
58 bool was_empty = message_queue_.IsEmpty();
59 message_queue_.AddMessage(message.Pass());
61 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(),
66 void LocalMessagePipeEndpoint::CancelAllWaiters() {
68 waiter_list_.CancelAllWaiters();
71 MojoResult LocalMessagePipeEndpoint::ReadMessage(
72 void* bytes, uint32_t* num_bytes,
73 std::vector<scoped_refptr<Dispatcher> >* dispatchers,
74 uint32_t* num_dispatchers,
75 MojoReadMessageFlags flags) {
77 DCHECK(!dispatchers || dispatchers->empty());
79 const uint32_t max_bytes = num_bytes ? *num_bytes : 0;
80 const uint32_t max_num_dispatchers = num_dispatchers ? *num_dispatchers : 0;
82 if (message_queue_.IsEmpty()) {
83 return is_peer_open_ ? MOJO_RESULT_SHOULD_WAIT :
84 MOJO_RESULT_FAILED_PRECONDITION;
87 // TODO(vtl): If |flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD|, we could pop
88 // and release the lock immediately.
89 bool enough_space = true;
90 MessageInTransit* message = message_queue_.PeekMessage();
92 *num_bytes = message->num_bytes();
93 if (message->num_bytes() <= max_bytes)
94 memcpy(bytes, message->bytes(), message->num_bytes());
98 if (std::vector<scoped_refptr<Dispatcher> >* queued_dispatchers =
99 message->dispatchers()) {
101 *num_dispatchers = static_cast<uint32_t>(queued_dispatchers->size());
103 if (queued_dispatchers->empty()) {
105 } else if (queued_dispatchers->size() <= max_num_dispatchers) {
107 dispatchers->swap(*queued_dispatchers);
109 enough_space = false;
114 *num_dispatchers = 0;
119 if (enough_space || (flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)) {
120 message_queue_.DiscardMessage();
122 // Now it's empty, thus no longer readable.
123 if (message_queue_.IsEmpty()) {
124 // It's currently not possible to wait for non-readability, but we should
125 // do the state change anyway.
126 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(),
132 return MOJO_RESULT_RESOURCE_EXHAUSTED;
134 return MOJO_RESULT_OK;
137 MojoResult LocalMessagePipeEndpoint::AddWaiter(Waiter* waiter,
139 MojoResult wake_result) {
142 if ((flags & SatisfiedFlags()))
143 return MOJO_RESULT_ALREADY_EXISTS;
144 if (!(flags & SatisfiableFlags()))
145 return MOJO_RESULT_FAILED_PRECONDITION;
147 waiter_list_.AddWaiter(waiter, flags, wake_result);
148 return MOJO_RESULT_OK;
151 void LocalMessagePipeEndpoint::RemoveWaiter(Waiter* waiter) {
153 waiter_list_.RemoveWaiter(waiter);
156 MojoWaitFlags LocalMessagePipeEndpoint::SatisfiedFlags() {
157 MojoWaitFlags satisfied_flags = 0;
158 if (!message_queue_.IsEmpty())
159 satisfied_flags |= MOJO_WAIT_FLAG_READABLE;
161 satisfied_flags |= MOJO_WAIT_FLAG_WRITABLE;
162 return satisfied_flags;
165 MojoWaitFlags LocalMessagePipeEndpoint::SatisfiableFlags() {
166 MojoWaitFlags satisfiable_flags = 0;
167 if (!message_queue_.IsEmpty() || is_peer_open_)
168 satisfiable_flags |= MOJO_WAIT_FLAG_READABLE;
170 satisfiable_flags |= MOJO_WAIT_FLAG_WRITABLE;
171 return satisfiable_flags;
174 } // namespace system