Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 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 "device/serial/data_source_sender.h" | |
| 6 | |
| 7 #include <limits> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/message_loop/message_loop.h" | |
| 11 #include "device/serial/async_waiter.h" | |
| 12 | |
| 13 namespace device { | |
| 14 | |
| 15 class DataSourceSender::PendingSend { | |
| 16 public: | |
| 17 PendingSend(DataSourceSender* sender, const ReadyCallback& callback); | |
| 18 void GetData(void* data, uint32_t num_bytes); | |
| 19 | |
| 20 private: | |
| 21 class Buffer; | |
| 22 void Done(uint32_t bytes_produced); | |
| 23 void DoneWithError(uint32_t bytes_produced, int32_t error); | |
| 24 | |
| 25 DataSourceSender* sender_; | |
| 26 ReadyCallback callback_; | |
| 27 bool buffer_in_use_; | |
| 28 }; | |
| 29 | |
| 30 class DataSourceSender::PendingSend::Buffer : public WritableBuffer { | |
| 31 public: | |
| 32 Buffer(scoped_refptr<DataSourceSender> sender, | |
| 33 PendingSend* send, | |
| 34 char* buffer, | |
| 35 uint32_t buffer_size); | |
| 36 virtual ~Buffer(); | |
| 37 virtual char* GetData() OVERRIDE; | |
| 38 virtual uint32_t GetSize() OVERRIDE; | |
| 39 virtual void Done(uint32_t bytes_produced) OVERRIDE; | |
| 40 virtual void DoneWithError(uint32_t bytes_produced, int32_t error) OVERRIDE; | |
| 41 | |
| 42 private: | |
| 43 scoped_refptr<DataSourceSender> sender_; | |
| 44 PendingSend* send_; | |
| 45 char* buffer_; | |
| 46 uint32_t buffer_size_; | |
| 47 }; | |
| 48 | |
| 49 DataSourceSender::DataSourceSender(const ReadyCallback& ready_callback, | |
| 50 const ErrorCallback& error_callback) | |
| 51 : ready_callback_(ready_callback), | |
| 52 error_callback_(error_callback), | |
| 53 bytes_sent_(0), | |
| 54 shut_down_(false) { | |
| 55 DCHECK(!ready_callback.is_null() && !error_callback.is_null()); | |
| 56 } | |
| 57 | |
| 58 void DataSourceSender::ShutDown() { | |
| 59 shut_down_ = true; | |
| 60 waiter_.reset(); | |
|
raymes
2014/08/06 06:41:53
I guess we could reset send_ here too?
Also consid
Sam McNally
2014/08/06 08:28:14
We can't reset pending_send_ in case it has buffer
| |
| 61 } | |
| 62 | |
| 63 DataSourceSender::~DataSourceSender() { | |
| 64 DCHECK(shut_down_); | |
| 65 } | |
| 66 | |
| 67 void DataSourceSender::Init(mojo::ScopedDataPipeProducerHandle handle) { | |
| 68 if (send_ || handle_.is_valid()) | |
|
raymes
2014/08/06 06:41:53
send_ -> pending_send_
I guess this case should n
Sam McNally
2014/08/06 08:28:14
Done.
| |
| 69 return; | |
| 70 | |
| 71 handle_ = handle.Pass(); | |
| 72 send_.reset(new PendingSend(this, ready_callback_)); | |
| 73 StartWaiting(); | |
| 74 } | |
| 75 | |
| 76 void DataSourceSender::Resume() { | |
| 77 if (send_ || !handle_.is_valid()) | |
|
raymes
2014/08/06 06:41:53
-Can the handle_ ever go from being valid to inval
Sam McNally
2014/08/06 08:28:14
It could get called before Init().
| |
| 78 return; | |
| 79 | |
| 80 send_.reset(new PendingSend(this, ready_callback_)); | |
| 81 StartWaiting(); | |
| 82 } | |
| 83 | |
| 84 void DataSourceSender::OnConnectionError() { | |
| 85 DispatchFatalError(); | |
| 86 } | |
| 87 | |
| 88 void DataSourceSender::StartWaiting() { | |
| 89 DCHECK(send_); | |
|
raymes
2014/08/06 06:41:53
Also !waiter_ should be true here?
Sam McNally
2014/08/06 08:28:14
Done.
| |
| 90 waiter_.reset( | |
| 91 new AsyncWaiter(handle_.get(), | |
| 92 MOJO_HANDLE_SIGNAL_WRITABLE, | |
| 93 base::Bind(&DataSourceSender::OnDoneWaiting, this))); | |
| 94 } | |
| 95 | |
| 96 void DataSourceSender::OnDoneWaiting(MojoResult result) { | |
| 97 DCHECK(send_ && !shut_down_); | |
| 98 if (!HandleMojoResult(result)) | |
| 99 return; | |
|
raymes
2014/08/06 06:41:53
I think you can get rid of the HandleMojoResult fu
Sam McNally
2014/08/06 08:28:14
Done.
| |
| 100 void* data = NULL; | |
| 101 uint32_t num_bytes = std::numeric_limits<uint32_t>::max(); | |
| 102 result = mojo::BeginWriteDataRaw( | |
| 103 handle_.get(), &data, &num_bytes, MOJO_READ_DATA_FLAG_NONE); | |
| 104 if (!HandleMojoResult(result)) | |
| 105 return; | |
| 106 send_->GetData(static_cast<char*>(data), num_bytes); | |
| 107 } | |
| 108 | |
| 109 void DataSourceSender::Done(uint32_t bytes_produced) { | |
| 110 DoneInternal(bytes_produced); | |
| 111 if (!shut_down_) | |
| 112 StartWaiting(); | |
| 113 } | |
| 114 | |
| 115 void DataSourceSender::DoneWithError(uint32_t bytes_produced, int32_t error) { | |
|
raymes
2014/08/06 06:41:53
Make a note in here that we don't call StartWaitin
Sam McNally
2014/08/06 08:28:15
Done.
| |
| 116 DoneInternal(bytes_produced); | |
| 117 send_.reset(); | |
| 118 if (!shut_down_) | |
| 119 client()->OnError(bytes_sent_, error); | |
| 120 } | |
| 121 | |
| 122 void DataSourceSender::DoneInternal(uint32_t bytes_produced) { | |
|
raymes
2014/08/06 06:41:53
Should we bail if we are shut_down_ on entry to th
Sam McNally
2014/08/06 08:28:15
Done.
| |
| 123 DCHECK(send_); | |
| 124 bytes_sent_ += bytes_produced; | |
| 125 MojoResult result = mojo::EndWriteDataRaw(handle_.get(), bytes_produced); | |
| 126 if (!HandleMojoResult(result)) | |
| 127 return; | |
| 128 } | |
| 129 | |
| 130 bool DataSourceSender::HandleMojoResult(MojoResult result) { | |
| 131 DCHECK(send_); | |
| 132 if (result == MOJO_RESULT_OK) | |
| 133 return true; | |
| 134 DispatchFatalError(); | |
| 135 return false; | |
| 136 } | |
| 137 | |
| 138 void DataSourceSender::DispatchFatalError() { | |
| 139 if (shut_down_) | |
| 140 return; | |
| 141 | |
| 142 ShutDown(); | |
| 143 error_callback_.Run(); | |
| 144 } | |
| 145 | |
| 146 DataSourceSender::PendingSend::PendingSend(DataSourceSender* sender, | |
| 147 const ReadyCallback& callback) | |
| 148 : sender_(sender), callback_(callback), buffer_in_use_(false) { | |
| 149 } | |
| 150 | |
| 151 void DataSourceSender::PendingSend::GetData(void* data, uint32_t num_bytes) { | |
| 152 DCHECK(!buffer_in_use_); | |
| 153 buffer_in_use_ = true; | |
| 154 callback_.Run(scoped_ptr<WritableBuffer>( | |
| 155 new Buffer(sender_, this, static_cast<char*>(data), num_bytes))); | |
| 156 } | |
| 157 | |
| 158 void DataSourceSender::PendingSend::Done(uint32_t bytes_produced) { | |
| 159 DCHECK(buffer_in_use_); | |
| 160 buffer_in_use_ = false; | |
| 161 sender_->Done(bytes_produced); | |
| 162 } | |
| 163 | |
| 164 void DataSourceSender::PendingSend::DoneWithError(uint32_t bytes_produced, | |
| 165 int32_t error) { | |
| 166 DCHECK(buffer_in_use_); | |
| 167 buffer_in_use_ = false; | |
| 168 sender_->DoneWithError(bytes_produced, error); | |
| 169 } | |
| 170 | |
| 171 DataSourceSender::PendingSend::Buffer::Buffer( | |
| 172 scoped_refptr<DataSourceSender> sender, | |
| 173 PendingSend* send, | |
| 174 char* buffer, | |
| 175 uint32_t buffer_size) | |
| 176 : sender_(sender), send_(send), buffer_(buffer), buffer_size_(buffer_size) { | |
| 177 } | |
| 178 | |
| 179 DataSourceSender::PendingSend::Buffer::~Buffer() { | |
| 180 if (sender_) | |
| 181 send_->Done(0); | |
| 182 } | |
| 183 | |
| 184 char* DataSourceSender::PendingSend::Buffer::GetData() { | |
| 185 return buffer_; | |
| 186 } | |
| 187 | |
| 188 uint32_t DataSourceSender::PendingSend::Buffer::GetSize() { | |
| 189 return buffer_size_; | |
| 190 } | |
| 191 | |
| 192 void DataSourceSender::PendingSend::Buffer::Done(uint32_t bytes_produced) { | |
| 193 DCHECK(sender_); | |
| 194 send_->Done(bytes_produced); | |
| 195 sender_ = NULL; | |
| 196 send_ = NULL; | |
| 197 buffer_ = NULL; | |
| 198 buffer_size_ = 0; | |
| 199 } | |
| 200 | |
| 201 void DataSourceSender::PendingSend::Buffer::DoneWithError( | |
| 202 uint32_t bytes_produced, | |
| 203 int32_t error) { | |
| 204 DCHECK(sender_); | |
| 205 send_->DoneWithError(bytes_produced, error); | |
| 206 sender_ = NULL; | |
| 207 send_ = NULL; | |
| 208 buffer_ = NULL; | |
| 209 buffer_size_ = 0; | |
| 210 } | |
| 211 | |
| 212 } // namespace device | |
| OLD | NEW |