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

Side by Side Diff: mojo/services/network/public/cpp/web_socket_read_queue.cc

Issue 1148913002: Fix WebSocket{Read,Write}Queue. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 "network/public/cpp/web_socket_read_queue.h" 5 #include "network/public/cpp/web_socket_read_queue.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "third_party/mojo/src/mojo/public/cpp/environment/logging.h"
8 9
9 namespace mojo { 10 namespace mojo {
10 11
11 struct WebSocketReadQueue::Operation { 12 struct WebSocketReadQueue::Operation {
12 uint32_t num_bytes_; 13 uint32_t num_bytes_;
13 base::Callback<void(const char*)> callback_; 14 base::Callback<void(const char*)> callback_;
14 }; 15 };
15 16
16 WebSocketReadQueue::WebSocketReadQueue(DataPipeConsumerHandle handle) 17 WebSocketReadQueue::WebSocketReadQueue(DataPipeConsumerHandle handle)
17 : handle_(handle), is_waiting_(false) { 18 : handle_(handle), is_busy_(false), destructed_(nullptr) {
18 } 19 }
19 20
20 WebSocketReadQueue::~WebSocketReadQueue() { 21 WebSocketReadQueue::~WebSocketReadQueue() {
22 if (destructed_)
23 *destructed_ = true;
21 } 24 }
22 25
23 void WebSocketReadQueue::Read(uint32_t num_bytes, 26 void WebSocketReadQueue::Read(uint32_t num_bytes,
24 base::Callback<void(const char*)> callback) { 27 base::Callback<void(const char*)> callback) {
25 Operation* op = new Operation; 28 Operation* op = new Operation;
26 op->num_bytes_ = num_bytes; 29 op->num_bytes_ = num_bytes;
27 op->callback_ = callback; 30 op->callback_ = callback;
28 queue_.push_back(op); 31 queue_.push_back(op);
29 32
30 if (!is_waiting_) 33 if (is_busy_)
31 TryToRead(); 34 return;
35
36 is_busy_ = true;
37 TryToRead();
32 } 38 }
33 39
34 void WebSocketReadQueue::TryToRead() { 40 void WebSocketReadQueue::TryToRead() {
35 Operation* op = queue_[0]; 41 MOJO_DCHECK(is_busy_);
36 const void* buffer = NULL; 42 MOJO_DCHECK(!queue_.empty());
37 uint32_t bytes_read = op->num_bytes_; 43 do {
38 MojoResult result = BeginReadDataRaw( 44 Operation* op = queue_[0];
39 handle_, &buffer, &bytes_read, MOJO_READ_DATA_FLAG_ALL_OR_NONE); 45 const void* buffer = NULL;
40 if (result == MOJO_RESULT_SHOULD_WAIT) { 46 uint32_t bytes_read = op->num_bytes_;
41 EndReadDataRaw(handle_, bytes_read); 47 MojoResult result = BeginReadDataRaw(
42 Wait(); 48 handle_, &buffer, &bytes_read, MOJO_READ_DATA_FLAG_ALL_OR_NONE);
43 return; 49 if (result == MOJO_RESULT_SHOULD_WAIT) {
44 } 50 Wait();
51 return;
52 }
45 53
46 // Ensure |op| is deleted, whether or not |this| goes away. 54 // Ensure |op| is deleted, whether or not |this| goes away.
47 scoped_ptr<Operation> op_deleter(op); 55 scoped_ptr<Operation> op_deleter(op);
48 queue_.weak_erase(queue_.begin()); 56 queue_.weak_erase(queue_.begin());
49 if (result != MOJO_RESULT_OK) 57
50 return; 58 // http://crbug.com/490193 This should run callback as well. May need to
51 DataPipeConsumerHandle handle = handle_; 59 // change the callback signature.
52 op->callback_.Run(static_cast<const char*>(buffer)); // may delete |this| 60 if (result != MOJO_RESULT_OK)
53 EndReadDataRaw(handle, bytes_read); 61 return;
62
63 uint32_t num_bytes = op_deleter->num_bytes_;
64 MOJO_DCHECK(num_bytes <= bytes_read);
65 DataPipeConsumerHandle handle = handle_;
66
67 bool destructed = false;
68 destructed_ = &destructed;
jam 2015/05/20 18:23:13 checkout this pattern: https://code.google.com/p/c
yzshen1 2015/05/20 19:23:32 I agree that the pattern is cleaner. One issue is
69
70 // May delete |this|. In that case, |destructed| will be set to true.
71 // Because |is_busy_| is true during the whole process, even if Read() is
72 // called by the callback, TryToRead() won't be re-entered. So we don't have
73 // to worry about |destructed_| being re-written by nested calls.
74 op->callback_.Run(static_cast<const char*>(buffer));
75
76 destructed_ = nullptr;
77
78 EndReadDataRaw(handle, num_bytes);
79
80 if (destructed)
81 return;
82 } while (!queue_.empty());
83 is_busy_ = false;
54 } 84 }
55 85
56 void WebSocketReadQueue::Wait() { 86 void WebSocketReadQueue::Wait() {
57 is_waiting_ = true; 87 MOJO_DCHECK(is_busy_);
58 handle_watcher_.Start( 88 handle_watcher_.Start(
59 handle_, 89 handle_,
60 MOJO_HANDLE_SIGNAL_READABLE, 90 MOJO_HANDLE_SIGNAL_READABLE,
61 MOJO_DEADLINE_INDEFINITE, 91 MOJO_DEADLINE_INDEFINITE,
62 base::Bind(&WebSocketReadQueue::OnHandleReady, base::Unretained(this))); 92 base::Bind(&WebSocketReadQueue::OnHandleReady, base::Unretained(this)));
63 } 93 }
64 94
65 void WebSocketReadQueue::OnHandleReady(MojoResult result) { 95 void WebSocketReadQueue::OnHandleReady(MojoResult result) {
66 is_waiting_ = false; 96 MOJO_DCHECK(is_busy_);
67 TryToRead(); 97 TryToRead();
68 } 98 }
69 99
70 } // namespace mojo 100 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/services/network/public/cpp/web_socket_read_queue.h ('k') | mojo/services/network/public/cpp/web_socket_write_queue.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698