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

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

Issue 9949011: Make FileStream::Seek async and add FileStream::SeekSync for sync operation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed comments Created 8 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « net/base/file_stream_win.h ('k') | net/base/mock_file_stream.h » ('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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "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/file_path.h" 9 #include "base/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread_restrictions.h" 14 #include "base/threading/thread_restrictions.h"
14 #include "base/threading/worker_pool.h" 15 #include "base/threading/worker_pool.h"
15 #include "net/base/file_stream_metrics.h" 16 #include "net/base/file_stream_metrics.h"
16 #include "net/base/file_stream_net_log_parameters.h" 17 #include "net/base/file_stream_net_log_parameters.h"
17 #include "net/base/io_buffer.h" 18 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h" 19 #include "net/base/net_errors.h"
19 20
20 namespace net { 21 namespace net {
21 22
22 // Ensure that we can just use our Whence values directly. 23 // Ensure that we can just use our Whence values directly.
23 COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin); 24 COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin);
24 COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current); 25 COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current);
25 COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end); 26 COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end);
26 27
27 static void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { 28 namespace {
29
30 void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) {
28 overlapped->Offset = offset.LowPart; 31 overlapped->Offset = offset.LowPart;
29 overlapped->OffsetHigh = offset.HighPart; 32 overlapped->OffsetHigh = offset.HighPart;
30 } 33 }
31 34
32 static void IncrementOffset(OVERLAPPED* overlapped, DWORD count) { 35 void IncrementOffset(OVERLAPPED* overlapped, DWORD count) {
33 LARGE_INTEGER offset; 36 LARGE_INTEGER offset;
34 offset.LowPart = overlapped->Offset; 37 offset.LowPart = overlapped->Offset;
35 offset.HighPart = overlapped->OffsetHigh; 38 offset.HighPart = overlapped->OffsetHigh;
36 offset.QuadPart += static_cast<LONGLONG>(count); 39 offset.QuadPart += static_cast<LONGLONG>(count);
37 SetOffset(overlapped, offset); 40 SetOffset(overlapped, offset);
38 } 41 }
39 42
40 namespace {
41
42 int RecordAndMapError(int error, 43 int RecordAndMapError(int error,
43 FileErrorSource source, 44 FileErrorSource source,
44 bool record_uma, 45 bool record_uma,
45 const net::BoundNetLog& bound_net_log) { 46 const net::BoundNetLog& bound_net_log) {
46 net::Error net_error = MapSystemError(error); 47 net::Error net_error = MapSystemError(error);
47 48
48 bound_net_log.AddEvent( 49 bound_net_log.AddEvent(
49 net::NetLog::TYPE_FILE_STREAM_ERROR, 50 net::NetLog::TYPE_FILE_STREAM_ERROR,
50 make_scoped_refptr( 51 make_scoped_refptr(
51 new FileStreamErrorParameters(GetFileErrorSourceName(source), 52 new FileStreamErrorParameters(GetFileErrorSourceName(source),
(...skipping 25 matching lines...) Expand all
77 LOG(WARNING) << "Failed to open file: " << error; 78 LOG(WARNING) << "Failed to open file: " << error;
78 *result = RecordAndMapError(error, 79 *result = RecordAndMapError(error,
79 FILE_ERROR_SOURCE_OPEN, 80 FILE_ERROR_SOURCE_OPEN,
80 record_uma, 81 record_uma,
81 bound_net_log); 82 bound_net_log);
82 bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); 83 bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL);
83 return; 84 return;
84 } 85 }
85 } 86 }
86 87
87 // Opens a file using OpenFile() and signals the completion.
88 void OpenFileAndSignal(const FilePath& path,
89 int open_flags,
90 bool record_uma,
91 base::PlatformFile* file,
92 int* result,
93 base::WaitableEvent* on_io_complete,
94 const net::BoundNetLog& bound_net_log) {
95 OpenFile(path, open_flags, record_uma, file, result, bound_net_log);
96 on_io_complete->Signal();
97 }
98
99 // Closes a file with some network logging. 88 // Closes a file with some network logging.
100 void CloseFile(base::PlatformFile file, 89 void CloseFile(base::PlatformFile file,
101 const net::BoundNetLog& bound_net_log) { 90 const net::BoundNetLog& bound_net_log) {
102 bound_net_log.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL); 91 bound_net_log.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL);
103 if (file == base::kInvalidPlatformFileValue) 92 if (file == base::kInvalidPlatformFileValue)
104 return; 93 return;
105 94
106 CancelIo(file); 95 CancelIo(file);
107 96
108 if (!base::ClosePlatformFile(file)) 97 if (!base::ClosePlatformFile(file))
109 NOTREACHED(); 98 NOTREACHED();
110 bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); 99 bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL);
111 } 100 }
112 101
113 // Closes a file with CloseFile() and signals the completion. 102 // Closes a file with CloseFile() and signals the completion.
114 void CloseFileAndSignal(base::PlatformFile* file, 103 void CloseFileAndSignal(base::PlatformFile* file,
115 base::WaitableEvent* on_io_complete, 104 base::WaitableEvent* on_io_complete,
116 const net::BoundNetLog& bound_net_log) { 105 const net::BoundNetLog& bound_net_log) {
117 CloseFile(*file, bound_net_log); 106 CloseFile(*file, bound_net_log);
118 *file = base::kInvalidPlatformFileValue; 107 *file = base::kInvalidPlatformFileValue;
119 on_io_complete->Signal(); 108 on_io_complete->Signal();
120 } 109 }
121 110
111 // Invokes a given closure and signals the completion.
112 void InvokeAndSignal(const base::Closure& closure,
113 base::WaitableEvent* on_io_complete) {
114 closure.Run();
115 on_io_complete->Signal();
116 }
117
122 } // namespace 118 } // namespace
123 119
124 // FileStreamWin::AsyncContext ---------------------------------------------- 120 // FileStreamWin::AsyncContext ----------------------------------------------
125 121
126 class FileStreamWin::AsyncContext : public MessageLoopForIO::IOHandler { 122 class FileStreamWin::AsyncContext : public MessageLoopForIO::IOHandler {
127 public: 123 public:
128 explicit AsyncContext(const net::BoundNetLog& bound_net_log) 124 explicit AsyncContext(const net::BoundNetLog& bound_net_log)
129 : context_(), is_closing_(false), 125 : context_(), is_closing_(false),
130 record_uma_(false), bound_net_log_(bound_net_log), 126 record_uma_(false), bound_net_log_(bound_net_log),
131 error_source_(FILE_ERROR_SOURCE_COUNT) { 127 error_source_(FILE_ERROR_SOURCE_COUNT) {
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 } 259 }
264 } else { 260 } else {
265 CloseSync(); 261 CloseSync();
266 } 262 }
267 } 263 }
268 264
269 bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); 265 bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL);
270 } 266 }
271 267
272 void FileStreamWin::Close(const CompletionCallback& callback) { 268 void FileStreamWin::Close(const CompletionCallback& callback) {
273 DCHECK(callback_.is_null());
274 callback_ = callback;
275
276 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); 269 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
277 270 DCHECK(!weak_ptr_factory_.HasWeakPtrs());
278 DCHECK(!on_io_complete_.get()); 271 DCHECK(!on_io_complete_.get());
279 on_io_complete_.reset(new base::WaitableEvent( 272 on_io_complete_.reset(new base::WaitableEvent(
280 false /* manual_reset */, false /* initially_signaled */)); 273 false /* manual_reset */, false /* initially_signaled */));
281 274
282 // Passing &file_ to a thread pool looks unsafe but it's safe here as the 275 // Passing &file_ to a thread pool looks unsafe but it's safe here as the
283 // destructor ensures that the close operation is complete with 276 // destructor ensures that the close operation is complete with
284 // WaitForIOCompletion(). See also the destructor. 277 // WaitForIOCompletion(). See also the destructor.
285 const bool posted = base::WorkerPool::PostTaskAndReply( 278 const bool posted = base::WorkerPool::PostTaskAndReply(
286 FROM_HERE, 279 FROM_HERE,
287 base::Bind(&CloseFileAndSignal, &file_, on_io_complete_.get(), 280 base::Bind(&CloseFileAndSignal, &file_, on_io_complete_.get(),
288 bound_net_log_), 281 bound_net_log_),
289 base::Bind(&FileStreamWin::OnClosed, weak_ptr_factory_.GetWeakPtr()), 282 base::Bind(&FileStreamWin::OnClosed,
283 weak_ptr_factory_.GetWeakPtr(),
284 callback),
290 true /* task_is_slow */); 285 true /* task_is_slow */);
291 DCHECK(posted); 286 DCHECK(posted);
292 } 287 }
293 288
294 void FileStreamWin::CloseSync() { 289 void FileStreamWin::CloseSync() {
295 // The logic here is similar to CloseFile() but async_context_.reset() is 290 // The logic here is similar to CloseFile() but async_context_.reset() is
296 // caled in this function. 291 // caled in this function.
297 292
298 // Block until the in-flight open operation is complete. 293 // Block until the in-flight open operation is complete.
299 // TODO(satorux): Replace this with a DCHECK(open_flags & ASYNC) once this 294 // TODO(satorux): Replace this with a DCHECK(open_flags & ASYNC) once this
(...skipping 16 matching lines...) Expand all
316 } 311 }
317 } 312 }
318 313
319 int FileStreamWin::Open(const FilePath& path, int open_flags, 314 int FileStreamWin::Open(const FilePath& path, int open_flags,
320 const CompletionCallback& callback) { 315 const CompletionCallback& callback) {
321 if (IsOpen()) { 316 if (IsOpen()) {
322 DLOG(FATAL) << "File is already open!"; 317 DLOG(FATAL) << "File is already open!";
323 return ERR_UNEXPECTED; 318 return ERR_UNEXPECTED;
324 } 319 }
325 320
326 DCHECK(callback_.is_null());
327 callback_ = callback;
328
329 open_flags_ = open_flags; 321 open_flags_ = open_flags;
330 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); 322 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
331 323 DCHECK(!weak_ptr_factory_.HasWeakPtrs());
332 DCHECK(!on_io_complete_.get()); 324 DCHECK(!on_io_complete_.get());
333 on_io_complete_.reset(new base::WaitableEvent( 325 on_io_complete_.reset(new base::WaitableEvent(
334 false /* manual_reset */, false /* initially_signaled */)); 326 false /* manual_reset */, false /* initially_signaled */));
335 327
336 // Passing &file_ to a thread pool looks unsafe but it's safe here as the 328 // Passing &file_ to a thread pool looks unsafe but it's safe here as the
337 // destructor ensures that the open operation is complete with 329 // destructor ensures that the open operation is complete with
338 // WaitForIOCompletion(). See also the destructor. 330 // WaitForIOCompletion(). See also the destructor.
339 int* result = new int(OK); 331 int* result = new int(OK);
340 const bool posted = base::WorkerPool::PostTaskAndReply( 332 const bool posted = base::WorkerPool::PostTaskAndReply(
341 FROM_HERE, 333 FROM_HERE,
342 base::Bind(&OpenFileAndSignal, 334 base::Bind(&InvokeAndSignal,
343 path, open_flags, record_uma_, &file_, result, 335 base::Bind(&OpenFile, path, open_flags, record_uma_, &file_,
344 on_io_complete_.get(), bound_net_log_), 336 result, bound_net_log_),
337 on_io_complete_.get()),
345 base::Bind(&FileStreamWin::OnOpened, 338 base::Bind(&FileStreamWin::OnOpened,
346 weak_ptr_factory_.GetWeakPtr(), 339 weak_ptr_factory_.GetWeakPtr(),
347 base::Owned(result)), 340 callback, base::Owned(result)),
348 true /* task_is_slow */); 341 true /* task_is_slow */);
349 DCHECK(posted); 342 DCHECK(posted);
350 return ERR_IO_PENDING; 343 return ERR_IO_PENDING;
351 } 344 }
352 345
353 int FileStreamWin::OpenSync(const FilePath& path, int open_flags) { 346 int FileStreamWin::OpenSync(const FilePath& path, int open_flags) {
354 if (IsOpen()) { 347 if (IsOpen()) {
355 DLOG(FATAL) << "File is already open!"; 348 DLOG(FATAL) << "File is already open!";
356 return ERR_UNEXPECTED; 349 return ERR_UNEXPECTED;
357 } 350 }
(...skipping 15 matching lines...) Expand all
373 async_context_.get()); 366 async_context_.get());
374 } 367 }
375 368
376 return OK; 369 return OK;
377 } 370 }
378 371
379 bool FileStreamWin::IsOpen() const { 372 bool FileStreamWin::IsOpen() const {
380 return file_ != base::kInvalidPlatformFileValue; 373 return file_ != base::kInvalidPlatformFileValue;
381 } 374 }
382 375
383 int64 FileStreamWin::Seek(Whence whence, int64 offset) { 376 int FileStreamWin::Seek(Whence whence, int64 offset,
377 const Int64CompletionCallback& callback) {
378 if (!IsOpen())
379 return ERR_UNEXPECTED;
380
381 // Make sure we're async and we have no other in-flight async operations.
382 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
383 DCHECK(!weak_ptr_factory_.HasWeakPtrs());
384 DCHECK(!on_io_complete_.get());
385
386 int64* result = new int64(-1);
387 on_io_complete_.reset(new base::WaitableEvent(
388 false /* manual_reset */, false /* initially_signaled */));
389
390 const bool posted = base::WorkerPool::PostTaskAndReply(
391 FROM_HERE,
392 base::Bind(&InvokeAndSignal,
393 // Unretained should be fine as we wait signal on
willchan no longer on Chromium 2012/04/10 06:48:33 Nit: s/we wait signal on/we wait for a signal on/
394 // on_io_complete_ at the destructor.
395 base::Bind(&FileStreamWin::SeekFile, base::Unretained(this),
396 whence, offset, result),
397 on_io_complete_.get()),
398 base::Bind(&FileStreamWin::OnSeeked,
399 weak_ptr_factory_.GetWeakPtr(),
400 callback, base::Owned(result)),
401 true /* task is slow */);
402 DCHECK(posted);
403 return ERR_IO_PENDING;
404 }
405
406 int64 FileStreamWin::SeekSync(Whence whence, int64 offset) {
384 if (!IsOpen()) 407 if (!IsOpen())
385 return ERR_UNEXPECTED; 408 return ERR_UNEXPECTED;
386 409
387 DCHECK(!async_context_.get() || async_context_->callback().is_null()); 410 DCHECK(!async_context_.get() || async_context_->callback().is_null());
388 411 int64 result = -1;
389 LARGE_INTEGER distance, result; 412 SeekFile(whence, offset, &result);
390 distance.QuadPart = offset; 413 return result;
391 DWORD move_method = static_cast<DWORD>(whence);
392 if (!SetFilePointerEx(file_, distance, &result, move_method)) {
393 DWORD error = GetLastError();
394 LOG(WARNING) << "SetFilePointerEx failed: " << error;
395 return RecordAndMapError(error,
396 FILE_ERROR_SOURCE_SEEK,
397 record_uma_,
398 bound_net_log_);
399 }
400 if (async_context_.get()) {
401 async_context_->set_error_source(FILE_ERROR_SOURCE_SEEK);
402 SetOffset(async_context_->overlapped(), result);
403 }
404 return result.QuadPart;
405 } 414 }
406 415
407 int64 FileStreamWin::Available() { 416 int64 FileStreamWin::Available() {
408 base::ThreadRestrictions::AssertIOAllowed(); 417 base::ThreadRestrictions::AssertIOAllowed();
409 418
410 if (!IsOpen()) 419 if (!IsOpen())
411 return ERR_UNEXPECTED; 420 return ERR_UNEXPECTED;
412 421
413 int64 cur_pos = Seek(FROM_CURRENT, 0); 422 int64 cur_pos = SeekSync(FROM_CURRENT, 0);
414 if (cur_pos < 0) 423 if (cur_pos < 0)
415 return cur_pos; 424 return cur_pos;
416 425
417 LARGE_INTEGER file_size; 426 LARGE_INTEGER file_size;
418 if (!GetFileSizeEx(file_, &file_size)) { 427 if (!GetFileSizeEx(file_, &file_size)) {
419 DWORD error = GetLastError(); 428 DWORD error = GetLastError();
420 LOG(WARNING) << "GetFileSizeEx failed: " << error; 429 LOG(WARNING) << "GetFileSizeEx failed: " << error;
421 return RecordAndMapError(error, 430 return RecordAndMapError(error,
422 FILE_ERROR_SOURCE_GET_SIZE, 431 FILE_ERROR_SOURCE_GET_SIZE,
423 record_uma_, 432 record_uma_,
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 int64 FileStreamWin::Truncate(int64 bytes) { 610 int64 FileStreamWin::Truncate(int64 bytes) {
602 base::ThreadRestrictions::AssertIOAllowed(); 611 base::ThreadRestrictions::AssertIOAllowed();
603 612
604 if (!IsOpen()) 613 if (!IsOpen())
605 return ERR_UNEXPECTED; 614 return ERR_UNEXPECTED;
606 615
607 // We'd better be open for writing. 616 // We'd better be open for writing.
608 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 617 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
609 618
610 // Seek to the position to truncate from. 619 // Seek to the position to truncate from.
611 int64 seek_position = Seek(FROM_BEGIN, bytes); 620 int64 seek_position = SeekSync(FROM_BEGIN, bytes);
612 if (seek_position != bytes) 621 if (seek_position != bytes)
613 return ERR_UNEXPECTED; 622 return ERR_UNEXPECTED;
614 623
615 // And truncate the file. 624 // And truncate the file.
616 BOOL result = SetEndOfFile(file_); 625 BOOL result = SetEndOfFile(file_);
617 if (!result) { 626 if (!result) {
618 DWORD error = GetLastError(); 627 DWORD error = GetLastError();
619 LOG(WARNING) << "SetEndOfFile failed: " << error; 628 LOG(WARNING) << "SetEndOfFile failed: " << error;
620 return RecordAndMapError(error, 629 return RecordAndMapError(error,
621 FILE_ERROR_SOURCE_SET_EOF, 630 FILE_ERROR_SOURCE_SET_EOF,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 net::NetLog::TYPE_FILE_STREAM_SOURCE, 664 net::NetLog::TYPE_FILE_STREAM_SOURCE,
656 make_scoped_refptr( 665 make_scoped_refptr(
657 new net::NetLogSourceParameter("source_dependency", 666 new net::NetLogSourceParameter("source_dependency",
658 bound_net_log_.source()))); 667 bound_net_log_.source())));
659 } 668 }
660 669
661 base::PlatformFile FileStreamWin::GetPlatformFileForTesting() { 670 base::PlatformFile FileStreamWin::GetPlatformFileForTesting() {
662 return file_; 671 return file_;
663 } 672 }
664 673
665 void FileStreamWin::OnClosed() { 674 void FileStreamWin::OnClosed(const CompletionCallback& callback) {
666 file_ = base::kInvalidPlatformFileValue; 675 file_ = base::kInvalidPlatformFileValue;
667 676
668 CompletionCallback temp = callback_; 677 // Reset this before Run() as Run() may issue a new async operation.
669 callback_.Reset(); 678 ResetOnIOComplete();
670 679 callback.Run(OK);
671 // Reset this before Run(). Run() should not issue a new async operation
672 // here, but just to keep it consistent with OnOpened().
673 on_io_complete_.reset();
674 temp.Run(OK);
675 } 680 }
676 681
677 void FileStreamWin::OnOpened(int* result) { 682 void FileStreamWin::SeekFile(Whence whence, int64 offset, int64* result) {
683 LARGE_INTEGER distance, res;
684 distance.QuadPart = offset;
685 DWORD move_method = static_cast<DWORD>(whence);
686 if (!SetFilePointerEx(file_, distance, &res, move_method)) {
687 DWORD error = GetLastError();
688 LOG(WARNING) << "SetFilePointerEx failed: " << error;
689 *result = RecordAndMapError(error,
690 FILE_ERROR_SOURCE_SEEK,
691 record_uma_,
692 bound_net_log_);
693 return;
694 }
695 if (async_context_.get()) {
696 async_context_->set_error_source(FILE_ERROR_SOURCE_SEEK);
697 SetOffset(async_context_->overlapped(), res);
698 }
699 *result = res.QuadPart;
700 }
701
702 void FileStreamWin::OnOpened(const CompletionCallback& callback, int* result) {
678 if (*result == OK) { 703 if (*result == OK) {
679 async_context_.reset(new AsyncContext(bound_net_log_)); 704 async_context_.reset(new AsyncContext(bound_net_log_));
680 if (record_uma_) 705 if (record_uma_)
681 async_context_->EnableErrorStatistics(); 706 async_context_->EnableErrorStatistics();
682 MessageLoopForIO::current()->RegisterIOHandler(file_, 707 MessageLoopForIO::current()->RegisterIOHandler(file_,
683 async_context_.get()); 708 async_context_.get());
684 } 709 }
685 710
686 CompletionCallback temp = callback_; 711 // Reset this before Run() as Run() may issue a new async operation.
687 callback_.Reset(); 712 ResetOnIOComplete();
713 callback.Run(*result);
714 }
688 715
716 void FileStreamWin::OnSeeked(
717 const Int64CompletionCallback& callback,
718 int64* result) {
689 // Reset this before Run() as Run() may issue a new async operation. 719 // Reset this before Run() as Run() may issue a new async operation.
720 ResetOnIOComplete();
721 callback.Run(*result);
722 }
723
724 void FileStreamWin::ResetOnIOComplete() {
690 on_io_complete_.reset(); 725 on_io_complete_.reset();
691 temp.Run(*result); 726 weak_ptr_factory_.InvalidateWeakPtrs();
692 } 727 }
693 728
694 void FileStreamWin::WaitForIOCompletion() { 729 void FileStreamWin::WaitForIOCompletion() {
695 if (on_io_complete_.get()) { 730 if (on_io_complete_.get()) {
696 on_io_complete_->Wait(); 731 on_io_complete_->Wait();
697 on_io_complete_.reset(); 732 on_io_complete_.reset();
698 } 733 }
699 } 734 }
700 735
701 } // namespace net 736 } // namespace net
OLDNEW
« no previous file with comments | « net/base/file_stream_win.h ('k') | net/base/mock_file_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698