| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/system/local_message_pipe_endpoint.h" | 5 #include "mojo/system/local_message_pipe_endpoint.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "mojo/system/dispatcher.h" |
| 10 #include "mojo/system/message_in_transit.h" | 11 #include "mojo/system/message_in_transit.h" |
| 11 | 12 |
| 12 namespace mojo { | 13 namespace mojo { |
| 13 namespace system { | 14 namespace system { |
| 14 | 15 |
| 16 LocalMessagePipeEndpoint::MessageQueueEntry::MessageQueueEntry() |
| 17 : message(NULL) { |
| 18 } |
| 19 |
| 20 // See comment in header file. |
| 21 LocalMessagePipeEndpoint::MessageQueueEntry::MessageQueueEntry( |
| 22 const MessageQueueEntry& other) |
| 23 : message(NULL) { |
| 24 DCHECK(!other.message); |
| 25 DCHECK(other.dispatchers.empty()); |
| 26 } |
| 27 |
| 28 LocalMessagePipeEndpoint::MessageQueueEntry::~MessageQueueEntry() { |
| 29 if (message) |
| 30 message->Destroy(); |
| 31 } |
| 32 |
| 15 LocalMessagePipeEndpoint::LocalMessagePipeEndpoint() | 33 LocalMessagePipeEndpoint::LocalMessagePipeEndpoint() |
| 16 : is_open_(true), | 34 : is_open_(true), |
| 17 is_peer_open_(true) { | 35 is_peer_open_(true) { |
| 18 } | 36 } |
| 19 | 37 |
| 20 LocalMessagePipeEndpoint::~LocalMessagePipeEndpoint() { | 38 LocalMessagePipeEndpoint::~LocalMessagePipeEndpoint() { |
| 21 DCHECK(!is_open_); | 39 DCHECK(!is_open_); |
| 22 } | 40 } |
| 23 | 41 |
| 24 void LocalMessagePipeEndpoint::Close() { | 42 void LocalMessagePipeEndpoint::Close() { |
| 25 DCHECK(is_open_); | 43 DCHECK(is_open_); |
| 26 is_open_ = false; | 44 is_open_ = false; |
| 27 for (std::deque<MessageInTransit*>::iterator it = message_queue_.begin(); | |
| 28 it != message_queue_.end(); | |
| 29 ++it) { | |
| 30 (*it)->Destroy(); | |
| 31 } | |
| 32 message_queue_.clear(); | 45 message_queue_.clear(); |
| 33 } | 46 } |
| 34 | 47 |
| 35 bool LocalMessagePipeEndpoint::OnPeerClose() { | 48 bool LocalMessagePipeEndpoint::OnPeerClose() { |
| 36 DCHECK(is_open_); | 49 DCHECK(is_open_); |
| 37 DCHECK(is_peer_open_); | 50 DCHECK(is_peer_open_); |
| 38 | 51 |
| 39 MojoWaitFlags old_satisfied_flags = SatisfiedFlags(); | 52 MojoWaitFlags old_satisfied_flags = SatisfiedFlags(); |
| 40 MojoWaitFlags old_satisfiable_flags = SatisfiableFlags(); | 53 MojoWaitFlags old_satisfiable_flags = SatisfiableFlags(); |
| 41 is_peer_open_ = false; | 54 is_peer_open_ = false; |
| 42 MojoWaitFlags new_satisfied_flags = SatisfiedFlags(); | 55 MojoWaitFlags new_satisfied_flags = SatisfiedFlags(); |
| 43 MojoWaitFlags new_satisfiable_flags = SatisfiableFlags(); | 56 MojoWaitFlags new_satisfiable_flags = SatisfiableFlags(); |
| 44 | 57 |
| 45 if (new_satisfied_flags != old_satisfied_flags || | 58 if (new_satisfied_flags != old_satisfied_flags || |
| 46 new_satisfiable_flags != old_satisfiable_flags) { | 59 new_satisfiable_flags != old_satisfiable_flags) { |
| 47 waiter_list_.AwakeWaitersForStateChange(new_satisfied_flags, | 60 waiter_list_.AwakeWaitersForStateChange(new_satisfied_flags, |
| 48 new_satisfiable_flags); | 61 new_satisfiable_flags); |
| 49 } | 62 } |
| 50 | 63 |
| 51 return true; | 64 return true; |
| 52 } | 65 } |
| 53 | 66 |
| 54 MojoResult LocalMessagePipeEndpoint::EnqueueMessage( | 67 MojoResult LocalMessagePipeEndpoint::CanEnqueueMessage( |
| 68 const MessageInTransit* /*message*/, |
| 69 const std::vector<Dispatcher*>* dispatchers) { |
| 70 // TODO(vtl) |
| 71 if (dispatchers) { |
| 72 NOTIMPLEMENTED(); |
| 73 return MOJO_RESULT_UNIMPLEMENTED; |
| 74 } |
| 75 return MOJO_RESULT_OK; |
| 76 } |
| 77 |
| 78 void LocalMessagePipeEndpoint::EnqueueMessage( |
| 55 MessageInTransit* message, | 79 MessageInTransit* message, |
| 56 const std::vector<Dispatcher*>* dispatchers) { | 80 std::vector<scoped_refptr<Dispatcher> >* dispatchers) { |
| 57 DCHECK(is_open_); | 81 DCHECK(is_open_); |
| 58 DCHECK(is_peer_open_); | 82 DCHECK(is_peer_open_); |
| 59 | 83 |
| 60 // TODO(vtl) | 84 // TODO(vtl) |
| 61 if (dispatchers) { | 85 DCHECK(!dispatchers || dispatchers->empty()); |
| 62 message->Destroy(); | |
| 63 return MOJO_RESULT_UNIMPLEMENTED; | |
| 64 } | |
| 65 | 86 |
| 66 bool was_empty = message_queue_.empty(); | 87 bool was_empty = message_queue_.empty(); |
| 67 message_queue_.push_back(message); | 88 message_queue_.push_back(MessageQueueEntry()); |
| 89 message_queue_.back().message = message; |
| 90 if (dispatchers) |
| 91 message_queue_.back().dispatchers.swap(*dispatchers); |
| 68 if (was_empty) { | 92 if (was_empty) { |
| 69 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(), | 93 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(), |
| 70 SatisfiableFlags()); | 94 SatisfiableFlags()); |
| 71 } | 95 } |
| 72 | |
| 73 return MOJO_RESULT_OK; | |
| 74 } | 96 } |
| 75 | 97 |
| 76 void LocalMessagePipeEndpoint::CancelAllWaiters() { | 98 void LocalMessagePipeEndpoint::CancelAllWaiters() { |
| 77 DCHECK(is_open_); | 99 DCHECK(is_open_); |
| 78 waiter_list_.CancelAllWaiters(); | 100 waiter_list_.CancelAllWaiters(); |
| 79 } | 101 } |
| 80 | 102 |
| 81 // TODO(vtl): Support receiving handles. | 103 // TODO(vtl): Support receiving handles. |
| 82 MojoResult LocalMessagePipeEndpoint::ReadMessage( | 104 MojoResult LocalMessagePipeEndpoint::ReadMessage( |
| 83 void* bytes, uint32_t* num_bytes, | 105 void* bytes, uint32_t* num_bytes, |
| 84 uint32_t max_num_dispatchers, | 106 uint32_t max_num_dispatchers, |
| 85 std::vector<scoped_refptr<Dispatcher> >* dispatchers, | 107 std::vector<scoped_refptr<Dispatcher> >* dispatchers, |
| 86 MojoReadMessageFlags flags) { | 108 MojoReadMessageFlags flags) { |
| 87 DCHECK(is_open_); | 109 DCHECK(is_open_); |
| 88 | 110 |
| 89 const uint32_t max_bytes = num_bytes ? *num_bytes : 0; | 111 const uint32_t max_bytes = num_bytes ? *num_bytes : 0; |
| 90 // TODO(vtl): We'll need this later: | |
| 91 // const uint32_t max_handles = num_handles ? *num_handles : 0; | |
| 92 | 112 |
| 93 if (message_queue_.empty()) { | 113 if (message_queue_.empty()) { |
| 94 return is_peer_open_ ? MOJO_RESULT_NOT_FOUND : | 114 return is_peer_open_ ? MOJO_RESULT_NOT_FOUND : |
| 95 MOJO_RESULT_FAILED_PRECONDITION; | 115 MOJO_RESULT_FAILED_PRECONDITION; |
| 96 } | 116 } |
| 97 | 117 |
| 98 // TODO(vtl): If |flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD|, we could pop | 118 // TODO(vtl): If |flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD|, we could pop |
| 99 // and release the lock immediately. | 119 // and release the lock immediately. |
| 100 bool not_enough_space = false; | 120 bool not_enough_space = false; |
| 101 MessageInTransit* const message = message_queue_.front(); | 121 MessageInTransit* const message = message_queue_.front().message; |
| 102 if (num_bytes) | 122 if (num_bytes) |
| 103 *num_bytes = message->data_size(); | 123 *num_bytes = message->data_size(); |
| 104 if (message->data_size() <= max_bytes) | 124 if (message->data_size() <= max_bytes) |
| 105 memcpy(bytes, message->data(), message->data_size()); | 125 memcpy(bytes, message->data(), message->data_size()); |
| 106 else | 126 else |
| 107 not_enough_space = true; | 127 not_enough_space = true; |
| 108 | 128 |
| 109 if (!not_enough_space || (flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)) { | 129 if (!not_enough_space || (flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)) { |
| 110 message_queue_.pop_front(); | 130 message_queue_.pop_front(); |
| 111 message->Destroy(); | |
| 112 | 131 |
| 113 // Now it's empty, thus no longer readable. | 132 // Now it's empty, thus no longer readable. |
| 114 if (message_queue_.empty()) { | 133 if (message_queue_.empty()) { |
| 115 // It's currently not possible to wait for non-readability, but we should | 134 // It's currently not possible to wait for non-readability, but we should |
| 116 // do the state change anyway. | 135 // do the state change anyway. |
| 117 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(), | 136 waiter_list_.AwakeWaitersForStateChange(SatisfiedFlags(), |
| 118 SatisfiableFlags()); | 137 SatisfiableFlags()); |
| 119 } | 138 } |
| 120 } | 139 } |
| 121 | 140 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 MojoWaitFlags satisfiable_flags = 0; | 176 MojoWaitFlags satisfiable_flags = 0; |
| 158 if (!message_queue_.empty() || is_peer_open_) | 177 if (!message_queue_.empty() || is_peer_open_) |
| 159 satisfiable_flags |= MOJO_WAIT_FLAG_READABLE; | 178 satisfiable_flags |= MOJO_WAIT_FLAG_READABLE; |
| 160 if (is_peer_open_) | 179 if (is_peer_open_) |
| 161 satisfiable_flags |= MOJO_WAIT_FLAG_WRITABLE; | 180 satisfiable_flags |= MOJO_WAIT_FLAG_WRITABLE; |
| 162 return satisfiable_flags; | 181 return satisfiable_flags; |
| 163 } | 182 } |
| 164 | 183 |
| 165 } // namespace system | 184 } // namespace system |
| 166 } // namespace mojo | 185 } // namespace mojo |
| OLD | NEW |