OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "mojo/system/local_message_pipe_endpoint.h" |
| 6 |
| 7 #include <string.h> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/stl_util.h" |
| 11 #include "mojo/system/message_in_transit.h" |
| 12 |
| 13 namespace mojo { |
| 14 namespace system { |
| 15 |
| 16 LocalMessagePipeEndpoint::LocalMessagePipeEndpoint() |
| 17 : is_open_(true), |
| 18 is_peer_open_(true) { |
| 19 } |
| 20 |
| 21 LocalMessagePipeEndpoint::~LocalMessagePipeEndpoint() { |
| 22 DCHECK(!is_open_); |
| 23 } |
| 24 |
| 25 void LocalMessagePipeEndpoint::OnPeerClose() { |
| 26 DCHECK(is_open_); |
| 27 DCHECK(is_peer_open_); |
| 28 |
| 29 MojoWaitFlags old_satisfied_flags = SatisfiedFlags(); |
| 30 MojoWaitFlags old_satisfiable_flags = SatisfiableFlags(); |
| 31 is_peer_open_ = false; |
| 32 MojoWaitFlags new_satisfied_flags = SatisfiedFlags(); |
| 33 MojoWaitFlags new_satisfiable_flags = SatisfiableFlags(); |
| 34 |
| 35 if (new_satisfied_flags != old_satisfied_flags || |
| 36 new_satisfiable_flags != old_satisfiable_flags) { |
| 37 waiter_list_.AwakeWaitersForStateChange(new_satisfied_flags, |
| 38 new_satisfiable_flags); |
| 39 } |
| 40 } |
| 41 |
| 42 MojoResult LocalMessagePipeEndpoint::EnqueueMessage( |
| 43 const void* bytes, uint32_t num_bytes, |
| 44 const MojoHandle* handles, uint32_t num_handles, |
| 45 MojoWriteMessageFlags /*flags*/) { |
| 46 DCHECK(is_open_); |
| 47 DCHECK(is_peer_open_); |
| 48 |
| 49 bool was_empty = message_queue_.empty(); |
| 50 |
| 51 // TODO(vtl): Eventually (with C++11), this should be an |emplace_back()|. |
| 52 message_queue_.push_back(MessageInTransit::Create(bytes, num_bytes)); |
| 53 // TODO(vtl): Support sending handles. |
| 54 |
| 55 if (was_empty) { |
| 56 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(), |
| 57 SatisfiableFlags()); |
| 58 } |
| 59 |
| 60 return MOJO_RESULT_OK; |
| 61 } |
| 62 |
| 63 void LocalMessagePipeEndpoint::CancelAllWaiters() { |
| 64 DCHECK(is_open_); |
| 65 waiter_list_.CancelAllWaiters(); |
| 66 } |
| 67 |
| 68 void LocalMessagePipeEndpoint::Close() { |
| 69 DCHECK(is_open_); |
| 70 is_open_ = false; |
| 71 STLDeleteElements(&message_queue_); |
| 72 } |
| 73 |
| 74 MojoResult LocalMessagePipeEndpoint::ReadMessage( |
| 75 void* bytes, uint32_t* num_bytes, |
| 76 MojoHandle* handles, uint32_t* num_handles, |
| 77 MojoReadMessageFlags flags) { |
| 78 DCHECK(is_open_); |
| 79 |
| 80 const uint32_t max_bytes = num_bytes ? *num_bytes : 0; |
| 81 // TODO(vtl): We'll need this later: |
| 82 // const uint32_t max_handles = num_handles ? *num_handles : 0; |
| 83 |
| 84 if (message_queue_.empty()) |
| 85 return MOJO_RESULT_NOT_FOUND; |
| 86 |
| 87 // TODO(vtl): If |flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD|, we could pop |
| 88 // and release the lock immediately. |
| 89 bool not_enough_space = false; |
| 90 MessageInTransit* const message = message_queue_.front(); |
| 91 if (num_bytes) |
| 92 *num_bytes = message->data_size(); |
| 93 if (message->data_size() <= max_bytes) |
| 94 memcpy(bytes, message->data(), message->data_size()); |
| 95 else |
| 96 not_enough_space = true; |
| 97 |
| 98 // TODO(vtl): Support receiving handles. |
| 99 if (num_handles) |
| 100 *num_handles = 0; |
| 101 |
| 102 if (!not_enough_space || (flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)) { |
| 103 message_queue_.pop_front(); |
| 104 message->Destroy(); |
| 105 |
| 106 // Now it's empty, thus no longer readable. |
| 107 if (message_queue_.empty()) { |
| 108 // It's currently not possible to wait for non-readability, but we should |
| 109 // do the state change anyway. |
| 110 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(), |
| 111 SatisfiableFlags()); |
| 112 } |
| 113 } |
| 114 |
| 115 if (not_enough_space) |
| 116 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 117 |
| 118 return MOJO_RESULT_OK; |
| 119 } |
| 120 |
| 121 MojoResult LocalMessagePipeEndpoint::AddWaiter(Waiter* waiter, |
| 122 MojoWaitFlags flags, |
| 123 MojoResult wake_result) { |
| 124 DCHECK(is_open_); |
| 125 |
| 126 if ((flags & SatisfiedFlags())) |
| 127 return MOJO_RESULT_ALREADY_EXISTS; |
| 128 if (!(flags & SatisfiableFlags())) |
| 129 return MOJO_RESULT_FAILED_PRECONDITION; |
| 130 |
| 131 waiter_list_.AddWaiter(waiter, flags, wake_result); |
| 132 return MOJO_RESULT_OK; |
| 133 } |
| 134 |
| 135 void LocalMessagePipeEndpoint::RemoveWaiter(Waiter* waiter) { |
| 136 DCHECK(is_open_); |
| 137 waiter_list_.RemoveWaiter(waiter); |
| 138 } |
| 139 |
| 140 MojoWaitFlags LocalMessagePipeEndpoint::SatisfiedFlags() { |
| 141 MojoWaitFlags satisfied_flags = 0; |
| 142 if (!message_queue_.empty()) |
| 143 satisfied_flags |= MOJO_WAIT_FLAG_READABLE; |
| 144 if (is_peer_open_) |
| 145 satisfied_flags |= MOJO_WAIT_FLAG_WRITABLE; |
| 146 return satisfied_flags; |
| 147 } |
| 148 |
| 149 MojoWaitFlags LocalMessagePipeEndpoint::SatisfiableFlags() { |
| 150 MojoWaitFlags satisfiable_flags = 0; |
| 151 if (!message_queue_.empty() || is_peer_open_) |
| 152 satisfiable_flags |= MOJO_WAIT_FLAG_READABLE; |
| 153 if (is_peer_open_) |
| 154 satisfiable_flags |= MOJO_WAIT_FLAG_WRITABLE; |
| 155 return satisfiable_flags; |
| 156 } |
| 157 |
| 158 } // namespace system |
| 159 } // namespace mojo |
| 160 |
OLD | NEW |