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

Side by Side Diff: net/base/file_stream_win.cc

Issue 8156: Switch MessagePumpForIO to use completion ports on Windows.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « chrome/common/ipc_sync_channel_unittest.cc ('k') | net/disk_cache/cache_util_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the 2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file. 3 // LICENSE file.
4 4
5 #include "net/base/file_stream.h" 5 #include "net/base/file_stream.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; 43 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
44 return ERR_FAILED; 44 return ERR_FAILED;
45 } 45 }
46 } 46 }
47 47
48 // FileStream::AsyncContext ---------------------------------------------- 48 // FileStream::AsyncContext ----------------------------------------------
49 49
50 class FileStream::AsyncContext : public MessageLoopForIO::IOHandler { 50 class FileStream::AsyncContext : public MessageLoopForIO::IOHandler {
51 public: 51 public:
52 AsyncContext(FileStream* owner) 52 AsyncContext(FileStream* owner)
53 : owner_(owner), overlapped_(), callback_(NULL) { 53 : owner_(owner), context_(), callback_(NULL) {
54 overlapped_.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 54 context_.handler = this;
55 } 55 }
56 56 ~AsyncContext();
57 ~AsyncContext() {
58 if (callback_)
59 MessageLoopForIO::current()->RegisterIOContext(&overlapped_, NULL);
60 CloseHandle(overlapped_.hEvent);
61 }
62 57
63 void IOCompletionIsPending(CompletionCallback* callback); 58 void IOCompletionIsPending(CompletionCallback* callback);
64 59
65 OVERLAPPED* overlapped() { return &overlapped_; } 60 OVERLAPPED* overlapped() { return &context_.overlapped; }
66 CompletionCallback* callback() const { return callback_; } 61 CompletionCallback* callback() const { return callback_; }
67 62
68 private: 63 private:
69 // MessageLoopForIO::IOHandler implementation: 64 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
70 virtual void OnIOCompleted(OVERLAPPED* context, DWORD num_bytes, 65 DWORD bytes_read, DWORD error);
71 DWORD error);
72 66
73 FileStream* owner_; 67 FileStream* owner_;
74 OVERLAPPED overlapped_; 68 MessageLoopForIO::IOContext context_;
75 CompletionCallback* callback_; 69 CompletionCallback* callback_;
76 }; 70 };
77 71
72 FileStream::AsyncContext::~AsyncContext() {
73 bool waited = false;
74 base::Time start = base::Time::Now();
75 while (callback_) {
76 waited = true;
77 MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this);
78 }
79 if (waited) {
80 // We want to see if we block the message loop for too long.
81 UMA_HISTOGRAM_TIMES(L"AsyncIO.FileStreamClose", base::Time::Now() - start);
82 }
83 }
84
78 void FileStream::AsyncContext::IOCompletionIsPending( 85 void FileStream::AsyncContext::IOCompletionIsPending(
79 CompletionCallback* callback) { 86 CompletionCallback* callback) {
80 DCHECK(!callback_); 87 DCHECK(!callback_);
81 callback_ = callback; 88 callback_ = callback;
82
83 MessageLoopForIO::current()->RegisterIOContext(&overlapped_, this);
84 } 89 }
85 90
86 void FileStream::AsyncContext::OnIOCompleted(OVERLAPPED* context, 91 void FileStream::AsyncContext::OnIOCompleted(
87 DWORD num_bytes, 92 MessageLoopForIO::IOContext* context, DWORD bytes_read, DWORD error) {
88 DWORD error) { 93 DCHECK(&context_ == context);
89 DCHECK(&overlapped_ == context);
90 DCHECK(callback_); 94 DCHECK(callback_);
91 95
92 MessageLoopForIO::current()->RegisterIOContext(&overlapped_, NULL); 96 int result = static_cast<int>(bytes_read);
93
94 HANDLE handle = owner_->file_;
95
96 int result = static_cast<int>(num_bytes);
97 if (error && error != ERROR_HANDLE_EOF) 97 if (error && error != ERROR_HANDLE_EOF)
98 result = MapErrorCode(error); 98 result = MapErrorCode(error);
99 99
100 if (num_bytes) 100 if (bytes_read)
101 IncrementOffset(&overlapped_, num_bytes); 101 IncrementOffset(&context->overlapped, bytes_read);
102 102
103 CompletionCallback* temp = NULL; 103 CompletionCallback* temp = NULL;
104 std::swap(temp, callback_); 104 std::swap(temp, callback_);
105 temp->Run(result); 105 temp->Run(result);
106 } 106 }
107 107
108 // FileStream ------------------------------------------------------------ 108 // FileStream ------------------------------------------------------------
109 109
110 FileStream::FileStream() : file_(INVALID_HANDLE_VALUE) { 110 FileStream::FileStream() : file_(INVALID_HANDLE_VALUE) {
111 } 111 }
112 112
113 FileStream::~FileStream() { 113 FileStream::~FileStream() {
114 Close(); 114 Close();
115 } 115 }
116 116
117 void FileStream::Close() { 117 void FileStream::Close() {
118 if (file_ != INVALID_HANDLE_VALUE)
119 CancelIo(file_);
120
121 async_context_.reset();
118 if (file_ != INVALID_HANDLE_VALUE) { 122 if (file_ != INVALID_HANDLE_VALUE) {
119 CloseHandle(file_); 123 CloseHandle(file_);
120 file_ = INVALID_HANDLE_VALUE; 124 file_ = INVALID_HANDLE_VALUE;
121 } 125 }
122 async_context_.reset();
123 } 126 }
124 127
125 int FileStream::Open(const std::wstring& path, int open_flags) { 128 int FileStream::Open(const std::wstring& path, int open_flags) {
126 if (IsOpen()) { 129 if (IsOpen()) {
127 DLOG(FATAL) << "File is already open!"; 130 DLOG(FATAL) << "File is already open!";
128 return ERR_UNEXPECTED; 131 return ERR_UNEXPECTED;
129 } 132 }
130 133
131 open_flags_ = open_flags; 134 open_flags_ = open_flags;
132 file_ = base::CreatePlatformFile(path, open_flags_, NULL); 135 file_ = base::CreatePlatformFile(path, open_flags_, NULL);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 DWORD error = GetLastError(); 207 DWORD error = GetLastError();
205 if (async_context_.get() && error == ERROR_IO_PENDING) { 208 if (async_context_.get() && error == ERROR_IO_PENDING) {
206 async_context_->IOCompletionIsPending(callback); 209 async_context_->IOCompletionIsPending(callback);
207 rv = ERR_IO_PENDING; 210 rv = ERR_IO_PENDING;
208 } else if (error == ERROR_HANDLE_EOF) { 211 } else if (error == ERROR_HANDLE_EOF) {
209 rv = 0; // Report EOF by returning 0 bytes read. 212 rv = 0; // Report EOF by returning 0 bytes read.
210 } else { 213 } else {
211 LOG(WARNING) << "ReadFile failed: " << error; 214 LOG(WARNING) << "ReadFile failed: " << error;
212 rv = MapErrorCode(error); 215 rv = MapErrorCode(error);
213 } 216 }
217 } else if (overlapped) {
218 async_context_->IOCompletionIsPending(callback);
219 rv = ERR_IO_PENDING;
214 } else { 220 } else {
215 if (overlapped)
216 IncrementOffset(overlapped, bytes_read);
217 rv = static_cast<int>(bytes_read); 221 rv = static_cast<int>(bytes_read);
218 } 222 }
219 return rv; 223 return rv;
220 } 224 }
221 225
222 int FileStream::Write( 226 int FileStream::Write(
223 const char* buf, int buf_len, CompletionCallback* callback) { 227 const char* buf, int buf_len, CompletionCallback* callback) {
224 if (!IsOpen()) 228 if (!IsOpen())
225 return ERR_UNEXPECTED; 229 return ERR_UNEXPECTED;
226 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 230 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
227 231
228 OVERLAPPED* overlapped = NULL; 232 OVERLAPPED* overlapped = NULL;
229 if (async_context_.get()) { 233 if (async_context_.get()) {
230 DCHECK(!async_context_->callback()); 234 DCHECK(!async_context_->callback());
231 overlapped = async_context_->overlapped(); 235 overlapped = async_context_->overlapped();
232 } 236 }
233 237
234 int rv; 238 int rv;
235 DWORD bytes_written; 239 DWORD bytes_written;
236 if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) { 240 if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) {
237 DWORD error = GetLastError(); 241 DWORD error = GetLastError();
238 if (async_context_.get() && error == ERROR_IO_PENDING) { 242 if (async_context_.get() && error == ERROR_IO_PENDING) {
239 async_context_->IOCompletionIsPending(callback); 243 async_context_->IOCompletionIsPending(callback);
240 rv = ERR_IO_PENDING; 244 rv = ERR_IO_PENDING;
241 } else { 245 } else {
242 LOG(WARNING) << "WriteFile failed: " << error; 246 LOG(WARNING) << "WriteFile failed: " << error;
243 rv = MapErrorCode(error); 247 rv = MapErrorCode(error);
244 } 248 }
249 } else if (overlapped) {
250 async_context_->IOCompletionIsPending(callback);
251 rv = ERR_IO_PENDING;
245 } else { 252 } else {
246 if (overlapped)
247 IncrementOffset(overlapped, bytes_written);
248 rv = static_cast<int>(bytes_written); 253 rv = static_cast<int>(bytes_written);
249 } 254 }
250 return rv; 255 return rv;
251 } 256 }
252 257
253 } // namespace net 258 } // namespace net
254 259
OLDNEW
« no previous file with comments | « chrome/common/ipc_sync_channel_unittest.cc ('k') | net/disk_cache/cache_util_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698