| 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 // TODO(vtl): I currently potentially overflow in doing index calculations. | 5 // TODO(vtl): I currently potentially overflow in doing index calculations. |
| 6 // E.g., |start_index_| and |current_num_bytes_| fit into a |uint32_t|, but | 6 // E.g., |start_index_| and |current_num_bytes_| fit into a |uint32_t|, but |
| 7 // their sum may not. This is bad and poses a security risk. (We're currently | 7 // their sum may not. This is bad and poses a security risk. (We're currently |
| 8 // saved by the limit on capacity -- the maximum size of the buffer, checked in | 8 // saved by the limit on capacity -- the maximum size of the buffer, checked in |
| 9 // |DataPipe::ValidateOptions()|, is currently sufficiently small. | 9 // |DataPipe::ValidateOptions()|, is currently sufficiently small. |
| 10 | 10 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 // If the consumer is still open and we still have data, we have to keep the | 35 // If the consumer is still open and we still have data, we have to keep the |
| 36 // buffer around. Currently, we won't free it even if it empties later. (We | 36 // buffer around. Currently, we won't free it even if it empties later. (We |
| 37 // could do this -- requiring a check on every read -- but that seems to be | 37 // could do this -- requiring a check on every read -- but that seems to be |
| 38 // optimizing for the uncommon case.) | 38 // optimizing for the uncommon case.) |
| 39 if (!consumer_open_no_lock() || !current_num_bytes_) { | 39 if (!consumer_open_no_lock() || !current_num_bytes_) { |
| 40 // Note: There can only be a two-phase *read* (by the consumer) if we still | 40 // Note: There can only be a two-phase *read* (by the consumer) if we still |
| 41 // have data. | 41 // have data. |
| 42 DCHECK(!consumer_in_two_phase_read_no_lock()); | 42 DCHECK(!consumer_in_two_phase_read_no_lock()); |
| 43 DestroyBufferNoLock(); | 43 DestroyBufferNoLock(); |
| 44 } | 44 } |
| 45 AwakeConsumerWaitersForStateChangeNoLock(); | |
| 46 } | 45 } |
| 47 | 46 |
| 48 MojoResult LocalDataPipe::ProducerWriteDataImplNoLock(const void* elements, | 47 MojoResult LocalDataPipe::ProducerWriteDataImplNoLock(const void* elements, |
| 49 uint32_t* num_bytes, | 48 uint32_t* num_bytes, |
| 50 bool all_or_none) { | 49 bool all_or_none) { |
| 51 DCHECK_EQ(*num_bytes % element_num_bytes(), 0u); | 50 DCHECK_EQ(*num_bytes % element_num_bytes(), 0u); |
| 52 DCHECK_GT(*num_bytes, 0u); | 51 DCHECK_GT(*num_bytes, 0u); |
| 53 DCHECK(consumer_open_no_lock()); | 52 DCHECK(consumer_open_no_lock()); |
| 54 | 53 |
| 55 size_t num_bytes_to_write = 0; | 54 size_t num_bytes_to_write = 0; |
| 56 if (may_discard()) { | 55 if (may_discard()) { |
| 57 if (all_or_none && *num_bytes > capacity_num_bytes()) | 56 if (all_or_none && *num_bytes > capacity_num_bytes()) |
| 58 return MOJO_RESULT_OUT_OF_RANGE; | 57 return MOJO_RESULT_OUT_OF_RANGE; |
| 59 | 58 |
| 60 num_bytes_to_write = std::min(static_cast<size_t>(*num_bytes), | 59 num_bytes_to_write = std::min(static_cast<size_t>(*num_bytes), |
| 61 capacity_num_bytes()); | 60 capacity_num_bytes()); |
| 62 if (num_bytes_to_write > capacity_num_bytes() - current_num_bytes_) { | 61 if (num_bytes_to_write > capacity_num_bytes() - current_num_bytes_) { |
| 63 // Discard as much as needed (discard oldest first). | 62 // Discard as much as needed (discard oldest first). |
| 64 size_t num_bytes_to_discard = | 63 MarkDataAsConsumedNoLock( |
| 65 num_bytes_to_write - (capacity_num_bytes() - current_num_bytes_); | 64 num_bytes_to_write - (capacity_num_bytes() - current_num_bytes_)); |
| 66 start_index_ += num_bytes_to_discard; | 65 // No need to wake up write waiters, since we're definitely going to leave |
| 67 start_index_ %= capacity_num_bytes(); | 66 // the buffer full. |
| 68 current_num_bytes_ -= num_bytes_to_discard; | |
| 69 } | 67 } |
| 70 } else { | 68 } else { |
| 71 if (all_or_none && *num_bytes > capacity_num_bytes() - current_num_bytes_) { | 69 if (all_or_none && *num_bytes > capacity_num_bytes() - current_num_bytes_) { |
| 72 // Don't return "should wait" since you can't wait for a specified amount | 70 // Don't return "should wait" since you can't wait for a specified amount |
| 73 // of data. | 71 // of data. |
| 74 return MOJO_RESULT_OUT_OF_RANGE; | 72 return MOJO_RESULT_OUT_OF_RANGE; |
| 75 } | 73 } |
| 76 | 74 |
| 77 num_bytes_to_write = std::min(static_cast<size_t>(*num_bytes), | 75 num_bytes_to_write = std::min(static_cast<size_t>(*num_bytes), |
| 78 capacity_num_bytes() - current_num_bytes_); | 76 capacity_num_bytes() - current_num_bytes_); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 89 EnsureBufferNoLock(); | 87 EnsureBufferNoLock(); |
| 90 memcpy(buffer_.get() + first_write_index, elements, num_bytes_to_write_first); | 88 memcpy(buffer_.get() + first_write_index, elements, num_bytes_to_write_first); |
| 91 | 89 |
| 92 if (num_bytes_to_write_first < num_bytes_to_write) { | 90 if (num_bytes_to_write_first < num_bytes_to_write) { |
| 93 // The "second write index" is zero. | 91 // The "second write index" is zero. |
| 94 memcpy(buffer_.get(), | 92 memcpy(buffer_.get(), |
| 95 static_cast<const char*>(elements) + num_bytes_to_write_first, | 93 static_cast<const char*>(elements) + num_bytes_to_write_first, |
| 96 num_bytes_to_write - num_bytes_to_write_first); | 94 num_bytes_to_write - num_bytes_to_write_first); |
| 97 } | 95 } |
| 98 | 96 |
| 99 bool was_empty = (current_num_bytes_ == 0); | |
| 100 | |
| 101 current_num_bytes_ += num_bytes_to_write; | 97 current_num_bytes_ += num_bytes_to_write; |
| 102 DCHECK_LE(current_num_bytes_, capacity_num_bytes()); | 98 DCHECK_LE(current_num_bytes_, capacity_num_bytes()); |
| 103 | |
| 104 if (was_empty && num_bytes_to_write > 0) | |
| 105 AwakeConsumerWaitersForStateChangeNoLock(); | |
| 106 | |
| 107 *num_bytes = static_cast<uint32_t>(num_bytes_to_write); | 99 *num_bytes = static_cast<uint32_t>(num_bytes_to_write); |
| 108 return MOJO_RESULT_OK; | 100 return MOJO_RESULT_OK; |
| 109 } | 101 } |
| 110 | 102 |
| 111 MojoResult LocalDataPipe::ProducerBeginWriteDataImplNoLock( | 103 MojoResult LocalDataPipe::ProducerBeginWriteDataImplNoLock( |
| 112 void** buffer, | 104 void** buffer, |
| 113 uint32_t* buffer_num_bytes, | 105 uint32_t* buffer_num_bytes, |
| 114 bool all_or_none) { | 106 bool all_or_none) { |
| 115 DCHECK(consumer_open_no_lock()); | 107 DCHECK(consumer_open_no_lock()); |
| 116 | 108 |
| 109 // The index we need to start writing at. |
| 110 size_t write_index = |
| 111 (start_index_ + current_num_bytes_) % capacity_num_bytes(); |
| 112 |
| 117 size_t max_num_bytes_to_write = GetMaxNumBytesToWriteNoLock(); | 113 size_t max_num_bytes_to_write = GetMaxNumBytesToWriteNoLock(); |
| 118 if (all_or_none && *buffer_num_bytes > max_num_bytes_to_write) { | 114 if (all_or_none && *buffer_num_bytes > max_num_bytes_to_write) { |
| 119 // Don't return "should wait" since you can't wait for a specified amount of | 115 // In "may discard" mode, we can always write from the write index to the |
| 120 // data. | 116 // end of the buffer. |
| 121 return MOJO_RESULT_OUT_OF_RANGE; | 117 if (may_discard() && |
| 118 *buffer_num_bytes <= capacity_num_bytes() - write_index) { |
| 119 // To do so, we need to discard an appropriate amount of data. |
| 120 // We should only reach here if the start index is after the write index! |
| 121 DCHECK_GE(start_index_, write_index); |
| 122 DCHECK_GT(*buffer_num_bytes - max_num_bytes_to_write, 0u); |
| 123 MarkDataAsConsumedNoLock(*buffer_num_bytes - max_num_bytes_to_write); |
| 124 max_num_bytes_to_write = *buffer_num_bytes; |
| 125 } else { |
| 126 // Don't return "should wait" since you can't wait for a specified amount |
| 127 // of data. |
| 128 return MOJO_RESULT_OUT_OF_RANGE; |
| 129 } |
| 122 } | 130 } |
| 123 | 131 |
| 124 // Don't go into a two-phase write if there's no room. | 132 // Don't go into a two-phase write if there's no room. |
| 125 if (max_num_bytes_to_write == 0) | 133 if (max_num_bytes_to_write == 0) |
| 126 return MOJO_RESULT_SHOULD_WAIT; | 134 return MOJO_RESULT_SHOULD_WAIT; |
| 127 | 135 |
| 128 size_t write_index = | |
| 129 (start_index_ + current_num_bytes_) % capacity_num_bytes(); | |
| 130 EnsureBufferNoLock(); | 136 EnsureBufferNoLock(); |
| 131 *buffer = buffer_.get() + write_index; | 137 *buffer = buffer_.get() + write_index; |
| 132 *buffer_num_bytes = static_cast<uint32_t>(max_num_bytes_to_write); | 138 *buffer_num_bytes = static_cast<uint32_t>(max_num_bytes_to_write); |
| 133 set_producer_two_phase_max_num_bytes_written_no_lock( | 139 set_producer_two_phase_max_num_bytes_written_no_lock( |
| 134 static_cast<uint32_t>(max_num_bytes_to_write)); | 140 static_cast<uint32_t>(max_num_bytes_to_write)); |
| 135 return MOJO_RESULT_OK; | 141 return MOJO_RESULT_OK; |
| 136 } | 142 } |
| 137 | 143 |
| 138 MojoResult LocalDataPipe::ProducerEndWriteDataImplNoLock( | 144 MojoResult LocalDataPipe::ProducerEndWriteDataImplNoLock( |
| 139 uint32_t num_bytes_written) { | 145 uint32_t num_bytes_written) { |
| 140 if (num_bytes_written > producer_two_phase_max_num_bytes_written_no_lock()) { | 146 if (num_bytes_written > producer_two_phase_max_num_bytes_written_no_lock()) { |
| 141 // Note: The two-phase write ends here even on failure. | 147 // Note: The two-phase write ends here even on failure. |
| 142 set_producer_two_phase_max_num_bytes_written_no_lock(0); | 148 set_producer_two_phase_max_num_bytes_written_no_lock(0); |
| 143 return MOJO_RESULT_INVALID_ARGUMENT; | 149 return MOJO_RESULT_INVALID_ARGUMENT; |
| 144 } | 150 } |
| 145 | 151 |
| 146 bool was_empty = (current_num_bytes_ == 0); | |
| 147 | |
| 148 current_num_bytes_ += num_bytes_written; | 152 current_num_bytes_ += num_bytes_written; |
| 149 DCHECK_LE(current_num_bytes_, capacity_num_bytes()); | 153 DCHECK_LE(current_num_bytes_, capacity_num_bytes()); |
| 150 set_producer_two_phase_max_num_bytes_written_no_lock(0); | 154 set_producer_two_phase_max_num_bytes_written_no_lock(0); |
| 151 | |
| 152 if (was_empty && num_bytes_written > 0) | |
| 153 AwakeConsumerWaitersForStateChangeNoLock(); | |
| 154 | |
| 155 return MOJO_RESULT_OK; | 155 return MOJO_RESULT_OK; |
| 156 } | 156 } |
| 157 | 157 |
| 158 MojoWaitFlags LocalDataPipe::ProducerSatisfiedFlagsNoLock() { | 158 MojoWaitFlags LocalDataPipe::ProducerSatisfiedFlagsNoLock() { |
| 159 MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE; | 159 MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE; |
| 160 if (consumer_open_no_lock() && current_num_bytes_ < capacity_num_bytes()) | 160 if (consumer_open_no_lock() && |
| 161 (may_discard() || current_num_bytes_ < capacity_num_bytes()) && |
| 162 !producer_in_two_phase_write_no_lock()) |
| 161 rv |= MOJO_WAIT_FLAG_WRITABLE; | 163 rv |= MOJO_WAIT_FLAG_WRITABLE; |
| 162 return rv; | 164 return rv; |
| 163 } | 165 } |
| 164 | 166 |
| 165 MojoWaitFlags LocalDataPipe::ProducerSatisfiableFlagsNoLock() { | 167 MojoWaitFlags LocalDataPipe::ProducerSatisfiableFlagsNoLock() { |
| 166 MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE; | 168 MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE; |
| 167 if (consumer_open_no_lock()) | 169 if (consumer_open_no_lock()) |
| 168 rv |= MOJO_WAIT_FLAG_WRITABLE; | 170 rv |= MOJO_WAIT_FLAG_WRITABLE; |
| 169 return rv; | 171 return rv; |
| 170 } | 172 } |
| 171 | 173 |
| 172 void LocalDataPipe::ConsumerCloseImplNoLock() { | 174 void LocalDataPipe::ConsumerCloseImplNoLock() { |
| 173 // If the producer is around and in a two-phase write, we have to keep the | 175 // If the producer is around and in a two-phase write, we have to keep the |
| 174 // buffer around. (We then don't free it until the producer is closed. This | 176 // buffer around. (We then don't free it until the producer is closed. This |
| 175 // could be rectified, but again seems like optimizing for the uncommon case.) | 177 // could be rectified, but again seems like optimizing for the uncommon case.) |
| 176 if (!producer_open_no_lock() || !producer_in_two_phase_write_no_lock()) | 178 if (!producer_open_no_lock() || !producer_in_two_phase_write_no_lock()) |
| 177 DestroyBufferNoLock(); | 179 DestroyBufferNoLock(); |
| 178 current_num_bytes_ = 0; | 180 current_num_bytes_ = 0; |
| 179 AwakeProducerWaitersForStateChangeNoLock(); | |
| 180 } | 181 } |
| 181 | 182 |
| 182 MojoResult LocalDataPipe::ConsumerReadDataImplNoLock(void* elements, | 183 MojoResult LocalDataPipe::ConsumerReadDataImplNoLock(void* elements, |
| 183 uint32_t* num_bytes, | 184 uint32_t* num_bytes, |
| 184 bool all_or_none) { | 185 bool all_or_none) { |
| 185 DCHECK_EQ(*num_bytes % element_num_bytes(), 0u); | 186 DCHECK_EQ(*num_bytes % element_num_bytes(), 0u); |
| 186 DCHECK_GT(*num_bytes, 0u); | 187 DCHECK_GT(*num_bytes, 0u); |
| 187 | 188 |
| 188 if (all_or_none && *num_bytes > current_num_bytes_) { | 189 if (all_or_none && *num_bytes > current_num_bytes_) { |
| 189 // Don't return "should wait" since you can't wait for a specified amount of | 190 // Don't return "should wait" since you can't wait for a specified amount of |
| (...skipping 14 matching lines...) Expand all Loading... |
| 204 std::min(num_bytes_to_read, GetMaxNumBytesToReadNoLock()); | 205 std::min(num_bytes_to_read, GetMaxNumBytesToReadNoLock()); |
| 205 memcpy(elements, buffer_.get() + start_index_, num_bytes_to_read_first); | 206 memcpy(elements, buffer_.get() + start_index_, num_bytes_to_read_first); |
| 206 | 207 |
| 207 if (num_bytes_to_read_first < num_bytes_to_read) { | 208 if (num_bytes_to_read_first < num_bytes_to_read) { |
| 208 // The "second read index" is zero. | 209 // The "second read index" is zero. |
| 209 memcpy(static_cast<char*>(elements) + num_bytes_to_read_first, | 210 memcpy(static_cast<char*>(elements) + num_bytes_to_read_first, |
| 210 buffer_.get(), | 211 buffer_.get(), |
| 211 num_bytes_to_read - num_bytes_to_read_first); | 212 num_bytes_to_read - num_bytes_to_read_first); |
| 212 } | 213 } |
| 213 | 214 |
| 214 bool was_full = (current_num_bytes_ == capacity_num_bytes()); | 215 MarkDataAsConsumedNoLock(num_bytes_to_read); |
| 215 | |
| 216 start_index_ += num_bytes_to_read; | |
| 217 start_index_ %= capacity_num_bytes(); | |
| 218 current_num_bytes_ -= num_bytes_to_read; | |
| 219 | |
| 220 if (was_full && num_bytes_to_read > 0) | |
| 221 AwakeProducerWaitersForStateChangeNoLock(); | |
| 222 | |
| 223 *num_bytes = static_cast<uint32_t>(num_bytes_to_read); | 216 *num_bytes = static_cast<uint32_t>(num_bytes_to_read); |
| 224 return MOJO_RESULT_OK; | 217 return MOJO_RESULT_OK; |
| 225 } | 218 } |
| 226 | 219 |
| 227 MojoResult LocalDataPipe::ConsumerDiscardDataImplNoLock(uint32_t* num_bytes, | 220 MojoResult LocalDataPipe::ConsumerDiscardDataImplNoLock(uint32_t* num_bytes, |
| 228 bool all_or_none) { | 221 bool all_or_none) { |
| 229 DCHECK_EQ(*num_bytes % element_num_bytes(), 0u); | 222 DCHECK_EQ(*num_bytes % element_num_bytes(), 0u); |
| 230 DCHECK_GT(*num_bytes, 0u); | 223 DCHECK_GT(*num_bytes, 0u); |
| 231 | 224 |
| 232 if (all_or_none && *num_bytes > current_num_bytes_) { | 225 if (all_or_none && *num_bytes > current_num_bytes_) { |
| 233 // Don't return "should wait" since you can't wait for a specified amount of | 226 // Don't return "should wait" since you can't wait for a specified amount of |
| 234 // data. | 227 // data. |
| 235 return producer_open_no_lock() ? MOJO_RESULT_OUT_OF_RANGE : | 228 return producer_open_no_lock() ? MOJO_RESULT_OUT_OF_RANGE : |
| 236 MOJO_RESULT_FAILED_PRECONDITION; | 229 MOJO_RESULT_FAILED_PRECONDITION; |
| 237 } | 230 } |
| 238 | 231 |
| 239 // Be consistent with other operations; error if no data available. | 232 // Be consistent with other operations; error if no data available. |
| 240 if (current_num_bytes_ == 0) { | 233 if (current_num_bytes_ == 0) { |
| 241 return producer_open_no_lock() ? MOJO_RESULT_SHOULD_WAIT : | 234 return producer_open_no_lock() ? MOJO_RESULT_SHOULD_WAIT : |
| 242 MOJO_RESULT_FAILED_PRECONDITION; | 235 MOJO_RESULT_FAILED_PRECONDITION; |
| 243 } | 236 } |
| 244 | 237 |
| 245 bool was_full = (current_num_bytes_ == capacity_num_bytes()); | |
| 246 | |
| 247 size_t num_bytes_to_discard = | 238 size_t num_bytes_to_discard = |
| 248 std::min(static_cast<size_t>(*num_bytes), current_num_bytes_); | 239 std::min(static_cast<size_t>(*num_bytes), current_num_bytes_); |
| 249 start_index_ = (start_index_ + num_bytes_to_discard) % capacity_num_bytes(); | 240 MarkDataAsConsumedNoLock(num_bytes_to_discard); |
| 250 current_num_bytes_ -= num_bytes_to_discard; | |
| 251 | |
| 252 if (was_full && num_bytes_to_discard > 0) | |
| 253 AwakeProducerWaitersForStateChangeNoLock(); | |
| 254 | |
| 255 *num_bytes = static_cast<uint32_t>(num_bytes_to_discard); | 241 *num_bytes = static_cast<uint32_t>(num_bytes_to_discard); |
| 256 return MOJO_RESULT_OK; | 242 return MOJO_RESULT_OK; |
| 257 } | 243 } |
| 258 | 244 |
| 259 MojoResult LocalDataPipe::ConsumerQueryDataImplNoLock(uint32_t* num_bytes) { | 245 MojoResult LocalDataPipe::ConsumerQueryDataImplNoLock(uint32_t* num_bytes) { |
| 260 // Note: This cast is safe, since the capacity fits into a |uint32_t|. | 246 // Note: This cast is safe, since the capacity fits into a |uint32_t|. |
| 261 *num_bytes = static_cast<uint32_t>(current_num_bytes_); | 247 *num_bytes = static_cast<uint32_t>(current_num_bytes_); |
| 262 return MOJO_RESULT_OK; | 248 return MOJO_RESULT_OK; |
| 263 } | 249 } |
| 264 | 250 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 288 } | 274 } |
| 289 | 275 |
| 290 MojoResult LocalDataPipe::ConsumerEndReadDataImplNoLock( | 276 MojoResult LocalDataPipe::ConsumerEndReadDataImplNoLock( |
| 291 uint32_t num_bytes_read) { | 277 uint32_t num_bytes_read) { |
| 292 if (num_bytes_read > consumer_two_phase_max_num_bytes_read_no_lock()) { | 278 if (num_bytes_read > consumer_two_phase_max_num_bytes_read_no_lock()) { |
| 293 // Note: The two-phase read ends here even on failure. | 279 // Note: The two-phase read ends here even on failure. |
| 294 set_consumer_two_phase_max_num_bytes_read_no_lock(0); | 280 set_consumer_two_phase_max_num_bytes_read_no_lock(0); |
| 295 return MOJO_RESULT_INVALID_ARGUMENT; | 281 return MOJO_RESULT_INVALID_ARGUMENT; |
| 296 } | 282 } |
| 297 | 283 |
| 298 bool was_full = (current_num_bytes_ == capacity_num_bytes()); | 284 DCHECK_LE(start_index_ + num_bytes_read, capacity_num_bytes()); |
| 299 | 285 MarkDataAsConsumedNoLock(num_bytes_read); |
| 300 start_index_ += num_bytes_read; | |
| 301 DCHECK_LE(start_index_, capacity_num_bytes()); | |
| 302 start_index_ %= capacity_num_bytes(); | |
| 303 DCHECK_LE(num_bytes_read, current_num_bytes_); | |
| 304 current_num_bytes_ -= num_bytes_read; | |
| 305 set_consumer_two_phase_max_num_bytes_read_no_lock(0); | 286 set_consumer_two_phase_max_num_bytes_read_no_lock(0); |
| 306 | |
| 307 if (was_full && num_bytes_read > 0) | |
| 308 AwakeProducerWaitersForStateChangeNoLock(); | |
| 309 | |
| 310 return MOJO_RESULT_OK; | 287 return MOJO_RESULT_OK; |
| 311 } | 288 } |
| 312 | 289 |
| 313 MojoWaitFlags LocalDataPipe::ConsumerSatisfiedFlagsNoLock() { | 290 MojoWaitFlags LocalDataPipe::ConsumerSatisfiedFlagsNoLock() { |
| 314 MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE; | 291 MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE; |
| 315 if (current_num_bytes_ > 0) | 292 if (current_num_bytes_ > 0 && !consumer_in_two_phase_read_no_lock()) |
| 316 rv |= MOJO_WAIT_FLAG_READABLE; | 293 rv |= MOJO_WAIT_FLAG_READABLE; |
| 317 return rv; | 294 return rv; |
| 318 } | 295 } |
| 319 | 296 |
| 320 MojoWaitFlags LocalDataPipe::ConsumerSatisfiableFlagsNoLock() { | 297 MojoWaitFlags LocalDataPipe::ConsumerSatisfiableFlagsNoLock() { |
| 321 MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE; | 298 MojoWaitFlags rv = MOJO_WAIT_FLAG_NONE; |
| 322 if (current_num_bytes_ > 0 || producer_open_no_lock()) | 299 if (current_num_bytes_ > 0 || producer_open_no_lock()) |
| 323 rv |= MOJO_WAIT_FLAG_READABLE; | 300 rv |= MOJO_WAIT_FLAG_READABLE; |
| 324 return rv; | 301 return rv; |
| 325 } | 302 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 353 } | 330 } |
| 354 return capacity_num_bytes() - next_index; | 331 return capacity_num_bytes() - next_index; |
| 355 } | 332 } |
| 356 | 333 |
| 357 size_t LocalDataPipe::GetMaxNumBytesToReadNoLock() { | 334 size_t LocalDataPipe::GetMaxNumBytesToReadNoLock() { |
| 358 if (start_index_ + current_num_bytes_ > capacity_num_bytes()) | 335 if (start_index_ + current_num_bytes_ > capacity_num_bytes()) |
| 359 return capacity_num_bytes() - start_index_; | 336 return capacity_num_bytes() - start_index_; |
| 360 return current_num_bytes_; | 337 return current_num_bytes_; |
| 361 } | 338 } |
| 362 | 339 |
| 340 void LocalDataPipe::MarkDataAsConsumedNoLock(size_t num_bytes) { |
| 341 DCHECK_LE(num_bytes, current_num_bytes_); |
| 342 start_index_ += num_bytes; |
| 343 start_index_ %= capacity_num_bytes(); |
| 344 current_num_bytes_ -= num_bytes; |
| 345 } |
| 346 |
| 363 } // namespace system | 347 } // namespace system |
| 364 } // namespace mojo | 348 } // namespace mojo |
| OLD | NEW |