Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(343)

Side by Side Diff: content/child/shared_memory_data_consumer_handle.cc

Issue 1118233002: Introduce SharedMemoryDataConsumerHandle. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@data-received-with-ack
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 "content/child/shared_memory_data_consumer_handle.h"
6
7 #include <algorithm>
8 #include <deque>
9 #include <vector>
10
11 #include "content/public/child/fixed_received_data.h"
12
13 namespace content {
14
15 using Result = blink::WebDataConsumerHandle::Result;
16
17 class SharedMemoryDataConsumerHandle::Context final
18 : public base::RefCountedThreadSafe<Context> {
19 public:
20 Context()
21 : result_(Ok),
22 first_offset_(0),
23 client_(nullptr),
24 is_reader_active_(true) {}
25
26 bool IsEmpty() const { return queue_.empty(); }
27 void Clear() {
28 for (RequestPeer::ReceivedData* data : queue_) {
29 delete data;
30 }
31 queue_.clear();
32 first_offset_ = 0;
33 client_ = nullptr;
34 }
35 RequestPeer::ReceivedData* Top() { return queue_.front(); }
36 void Push(scoped_ptr<RequestPeer::ReceivedData> data) {
37 queue_.push_back(data.release());
38 }
39 size_t first_offset() const { return first_offset_; }
40 Result result() const { return result_; }
41 void set_result(Result r) { result_ = r; }
42 Client* client() { return client_; }
43 void set_client(Client* client) { client_ = client; }
44 bool is_reader_active() const { return is_reader_active_; }
45 void set_is_reader_active(bool b) { is_reader_active_ = b; }
46 void Consume(size_t s) {
47 first_offset_ += s;
48 RequestPeer::ReceivedData* top = Top();
49 if (static_cast<size_t>(top->length()) <= first_offset_) {
50 delete top;
51 queue_.pop_front();
52 first_offset_ = 0;
53 }
54 }
55
56 private:
57 friend class base::RefCountedThreadSafe<Context>;
58 ~Context() {
59 // This is necessary because the queue stores raw pointers.
60 Clear();
61 }
62
63 // |result_| stores the ultimate state of this handle if it has. Otherwise,
64 // |Ok| is set.
65 Result result_;
66 // TODO(yhirano): Use std::deque<scoped_ptr<ReceivedData>> once it is allowed.
67 std::deque<RequestPeer::ReceivedData*> queue_;
68 size_t first_offset_;
69 Client* client_;
70 bool is_reader_active_;
71
72 DISALLOW_COPY_AND_ASSIGN(Context);
73 };
74
75 SharedMemoryDataConsumerHandle::Writer::Writer(
76 const scoped_refptr<Context>& context,
77 BackpressureMode mode)
78 : context_(context), mode_(mode) {
79 }
80
81 SharedMemoryDataConsumerHandle::Writer::~Writer() {
82 Close();
83 }
84
85 void SharedMemoryDataConsumerHandle::Writer::AddData(
86 scoped_ptr<RequestPeer::ReceivedData> data) {
87 if (!data->length()) {
88 // We omit empty data.
89 return;
90 }
91
92 if (!context_->is_reader_active()) {
93 // No one is interested in the data.
94 return;
95 }
96
97 bool needs_notification = context_->client() && context_->IsEmpty();
98 scoped_ptr<RequestPeer::ReceivedData> data_to_pass;
99 if (mode_ == kApplyBackpressure) {
100 data_to_pass = data.Pass();
101 } else {
102 data_to_pass = make_scoped_ptr(new FixedReceivedData(data.get()));
103 }
104 context_->Push(data_to_pass.Pass());
105
106 if (needs_notification)
107 context_->client()->didGetReadable();
108 }
109
110 void SharedMemoryDataConsumerHandle::Writer::Close() {
111 if (context_->result() == Ok) {
112 context_->set_result(Done);
113 if (context_->client() && context_->IsEmpty())
114 context_->client()->didGetReadable();
115 }
116 }
117
118 SharedMemoryDataConsumerHandle::SharedMemoryDataConsumerHandle(
119 BackpressureMode mode,
120 scoped_ptr<Writer>* writer)
121 : context_(new Context) {
122 writer->reset(new Writer(context_, mode));
123 }
124
125 SharedMemoryDataConsumerHandle::~SharedMemoryDataConsumerHandle() {
126 context_->set_is_reader_active(false);
127 context_->Clear();
128 }
129
130 Result SharedMemoryDataConsumerHandle::read(void* data,
131 size_t size,
132 Flags flags,
133 size_t* read_size_to_return) {
134 size_t total_read_size = 0;
135 *read_size_to_return = 0;
136 if (context_->result() != Ok && context_->result() != Done)
137 return context_->result();
138
139 while (!context_->IsEmpty() && total_read_size < size) {
140 const auto& top = context_->Top();
141 size_t readable = top->length() - context_->first_offset();
142 size_t writable = size - total_read_size;
143 size_t read_size = std::min(readable, writable);
144 const char* begin = top->payload() + context_->first_offset();
145 std::copy(begin, begin + read_size,
146 static_cast<char*>(data) + total_read_size);
147 total_read_size += read_size;
148 context_->Consume(read_size);
149 }
150 *read_size_to_return = total_read_size;
151 return total_read_size ? Ok : context_->result() == Done ? Done : ShouldWait;
152 }
153
154 Result SharedMemoryDataConsumerHandle::beginRead(const void** buffer,
155 Flags flags,
156 size_t* available) {
157 *buffer = nullptr;
158 *available = 0;
159
160 if (context_->result() != Ok && context_->result() != Done)
161 return context_->result();
162
163 if (context_->IsEmpty())
164 return context_->result() == Done ? Done : ShouldWait;
165
166 const auto& top = context_->Top();
167 *buffer = top->payload() + context_->first_offset();
168 *available = top->length() - context_->first_offset();
169
170 return Ok;
171 }
172
173 Result SharedMemoryDataConsumerHandle::endRead(size_t read_size) {
174 if (context_->IsEmpty())
175 return UnexpectedError;
176
177 context_->Consume(read_size);
178 return Ok;
179 }
180
181 void SharedMemoryDataConsumerHandle::registerClient(Client* client) {
182 context_->set_client(client);
183
184 if (!context_->IsEmpty())
185 client->didGetReadable();
186 }
187
188 void SharedMemoryDataConsumerHandle::unregisterClient() {
189 context_->set_client(nullptr);
190 }
191
192 } // namespace content
OLDNEW
« no previous file with comments | « content/child/shared_memory_data_consumer_handle.h ('k') | content/child/shared_memory_data_consumer_handle_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698