diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-17 19:32:18 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-17 19:32:18 +0000 |
commit | 28a4aae3b3134867687584eb6ea5d2f131b74f15 (patch) | |
tree | c76a9fbd03ad3985b3645593dc34611f2aa3576b /net | |
parent | df86e0fd8f414d97b631e0cd511d6ef3c763b393 (diff) | |
download | chromium_src-28a4aae3b3134867687584eb6ea5d2f131b74f15.zip chromium_src-28a4aae3b3134867687584eb6ea5d2f131b74f15.tar.gz chromium_src-28a4aae3b3134867687584eb6ea5d2f131b74f15.tar.bz2 |
Disk cache: Cleanup file_posix so that it uses the latest
version of InFlightIO & Co.
BUG=55629
TEST=current tests.
Review URL: http://codereview.chromium.org/4956001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66497 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/disk_cache/file_posix.cc | 233 |
1 files changed, 74 insertions, 159 deletions
diff --git a/net/disk_cache/file_posix.cc b/net/disk_cache/file_posix.cc index a8d74ae..1870c0b 100644 --- a/net/disk_cache/file_posix.cc +++ b/net/disk_cache/file_posix.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,61 +6,27 @@ #include <fcntl.h> -#include <set> - #include "base/logging.h" -#include "base/message_loop.h" -#include "base/singleton.h" -#include "base/waitable_event.h" #include "base/worker_pool.h" #include "net/disk_cache/disk_cache.h" +#include "net/disk_cache/in_flight_io.h" namespace { -class InFlightIO; - // This class represents a single asynchronous IO operation while it is being // bounced between threads. -class BackgroundIO : public base::RefCountedThreadSafe<BackgroundIO> { +class FileBackgroundIO : public disk_cache::BackgroundIO { public: // Other than the actual parameters for the IO operation (including the // |callback| that must be notified at the end), we need the controller that // is keeping track of all operations. When done, we notify the controller // (we do NOT invoke the callback), in the worker thead that completed the // operation. - BackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len, - size_t offset, disk_cache::FileIOCallback* callback, - InFlightIO* controller) - : io_completed_(true, false), callback_(callback), file_(file), buf_(buf), - buf_len_(buf_len), offset_(offset), controller_(controller), - bytes_(0) {} - - // Read and Write are the operations that can be performed asynchronously. - // The actual parameters for the operation are setup in the constructor of - // the object. Both methods should be called from a worker thread, by posting - // a task to the WorkerPool (they are RunnableMethods). When finished, - // controller->OnIOComplete() is called. - void Read(); - void Write(); - - // This method signals the controller that this operation is finished, in the - // original thread (presumably the IO-Thread). In practice, this is a - // RunableMethod that allows cancellation. - void OnIOSignalled(); - - // Allows the cancellation of the task to notify the controller (step number 7 - // in the diagram below). In practice, if the controller waits for the - // operation to finish it doesn't have to wait for the final task to be - // processed by the message loop so calling this method prevents its delivery. - // Note that this method is not intended to cancel the actual IO operation or - // to prevent the first notification to take place (OnIOComplete). - void Cancel(); - - // Retrieves the number of bytes transfered. - int Result(); - - base::WaitableEvent* io_completed() { - return &io_completed_; + FileBackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len, + size_t offset, disk_cache::FileIOCallback* callback, + disk_cache::InFlightIO* controller) + : disk_cache::BackgroundIO(controller), callback_(callback), file_(file), + buf_(buf), buf_len_(buf_len), offset_(offset) { } disk_cache::FileIOCallback* callback() { @@ -71,49 +37,33 @@ class BackgroundIO : public base::RefCountedThreadSafe<BackgroundIO> { return file_; } + // Read and Write are the operations that can be performed asynchronously. + // The actual parameters for the operation are setup in the constructor of + // the object. Both methods should be called from a worker thread, by posting + // a task to the WorkerPool (they are RunnableMethods). When finished, + // controller->OnIOComplete() is called. + void Read(); + void Write(); + private: - friend class base::RefCountedThreadSafe<BackgroundIO>; - ~BackgroundIO() {} + ~FileBackgroundIO() {} - // An event to signal when the operation completes, and the user callback that - // has to be invoked. These members are accessed directly by the controller. - base::WaitableEvent io_completed_; disk_cache::FileIOCallback* callback_; disk_cache::File* file_; const void* buf_; size_t buf_len_; size_t offset_; - InFlightIO* controller_; // The controller that tracks all operations. - int bytes_; // Final operation result. - DISALLOW_COPY_AND_ASSIGN(BackgroundIO); + DISALLOW_COPY_AND_ASSIGN(FileBackgroundIO); }; -// This class keeps track of every asynchronous IO operation. A single instance -// of this class is meant to be used to start an asynchronous operation (using -// PostRead/PostWrite). This class will post the operation to a worker thread, -// hanlde the notification when the operation finishes and perform the callback -// on the same thread that was used to start the operation. -// -// The regular sequence of calls is: -// Thread_1 Worker_thread -// 1. InFlightIO::PostRead() -// 2. -> PostTask -> -// 3. BackgroundIO::Read() -// 4. IO operation completes -// 5. InFlightIO::OnIOComplete() -// 6. <- PostTask <- -// 7. BackgroundIO::OnIOSignalled() -// 8. InFlightIO::InvokeCallback() -// 9. invoke callback -// -// Shutdown is a special case that is handled though WaitForPendingIO() instead -// of just waiting for step 7. -class InFlightIO { + +// The specialized controller that keeps track of current operations. +class FileInFlightIO : public disk_cache::InFlightIO { public: - InFlightIO() : callback_thread_(MessageLoop::current()) {} - ~InFlightIO() {} + FileInFlightIO() {} + ~FileInFlightIO() {} // These methods start an asynchronous operation. The arguments have the same // semantics of the File asynchronous operations, with the exception that the @@ -123,128 +73,94 @@ class InFlightIO { void PostWrite(disk_cache::File* file, const void* buf, size_t buf_len, size_t offset, disk_cache::FileIOCallback* callback); - // Blocks the current thread until all IO operations tracked by this object - // complete. - void WaitForPendingIO(); - - // Called on a worker thread when |operation| completes. - void OnIOComplete(BackgroundIO* operation); - + protected: // Invokes the users' completion callback at the end of the IO operation. - // |cancel_task| is true if the actual task posted to the thread is still + // |cancel| is true if the actual task posted to the thread is still // queued (because we are inside WaitForPendingIO), and false if said task is // the one performing the call. - void InvokeCallback(BackgroundIO* operation, bool cancel_task); + virtual void OnOperationComplete(disk_cache::BackgroundIO* operation, + bool cancel); private: - typedef std::set<scoped_refptr<BackgroundIO> > IOList; - - IOList io_list_; // List of pending io operations. - MessageLoop* callback_thread_; + DISALLOW_COPY_AND_ASSIGN(FileInFlightIO); }; // --------------------------------------------------------------------------- // Runs on a worker thread. -void BackgroundIO::Read() { +void FileBackgroundIO::Read() { if (file_->Read(const_cast<void*>(buf_), buf_len_, offset_)) { - bytes_ = static_cast<int>(buf_len_); + result_ = static_cast<int>(buf_len_); } else { - bytes_ = -1; + result_ = -1; } controller_->OnIOComplete(this); } -int BackgroundIO::Result() { - return bytes_; -} - -void BackgroundIO::Cancel() { - DCHECK(controller_); - controller_ = NULL; -} - // Runs on a worker thread. -void BackgroundIO::Write() { +void FileBackgroundIO::Write() { bool rv = file_->Write(buf_, buf_len_, offset_); - bytes_ = rv ? static_cast<int>(buf_len_) : -1; + result_ = rv ? static_cast<int>(buf_len_) : -1; controller_->OnIOComplete(this); } -// Runs on the IO thread. -void BackgroundIO::OnIOSignalled() { - if (controller_) - controller_->InvokeCallback(this, false); -} - // --------------------------------------------------------------------------- -void InFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len, +void FileInFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len, size_t offset, disk_cache::FileIOCallback *callback) { - scoped_refptr<BackgroundIO> operation( - new BackgroundIO(file, buf, buf_len, offset, callback, this)); - io_list_.insert(operation); - file->AddRef(); // Balanced on InvokeCallback() - - if (!callback_thread_) - callback_thread_ = MessageLoop::current(); + scoped_refptr<FileBackgroundIO> operation( + new FileBackgroundIO(file, buf, buf_len, offset, callback, this)); + file->AddRef(); // Balanced on OnOperationComplete() WorkerPool::PostTask(FROM_HERE, - NewRunnableMethod(operation.get(), &BackgroundIO::Read), - true); + NewRunnableMethod(operation.get(), &FileBackgroundIO::Read), true); + OnOperationPosted(operation); } -void InFlightIO::PostWrite(disk_cache::File* file, const void* buf, +void FileInFlightIO::PostWrite(disk_cache::File* file, const void* buf, size_t buf_len, size_t offset, disk_cache::FileIOCallback* callback) { - scoped_refptr<BackgroundIO> operation( - new BackgroundIO(file, buf, buf_len, offset, callback, this)); - io_list_.insert(operation); - file->AddRef(); // Balanced on InvokeCallback() - - if (!callback_thread_) - callback_thread_ = MessageLoop::current(); + scoped_refptr<FileBackgroundIO> operation( + new FileBackgroundIO(file, buf, buf_len, offset, callback, this)); + file->AddRef(); // Balanced on OnOperationComplete() WorkerPool::PostTask(FROM_HERE, - NewRunnableMethod(operation.get(), &BackgroundIO::Write), - true); -} - -void InFlightIO::WaitForPendingIO() { - while (!io_list_.empty()) { - // Block the current thread until all pending IO completes. - IOList::iterator it = io_list_.begin(); - InvokeCallback(*it, true); - } - // Unit tests can use different threads. - callback_thread_ = NULL; -} - -// Runs on a worker thread. -void InFlightIO::OnIOComplete(BackgroundIO* operation) { - callback_thread_->PostTask(FROM_HERE, - NewRunnableMethod(operation, - &BackgroundIO::OnIOSignalled)); - operation->io_completed()->Signal(); + NewRunnableMethod(operation.get(), &FileBackgroundIO::Write), true); + OnOperationPosted(operation); } // Runs on the IO thread. -void InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) { - operation->io_completed()->Wait(); - - if (cancel_task) - operation->Cancel(); +void FileInFlightIO::OnOperationComplete(disk_cache::BackgroundIO* operation, + bool cancel) { + FileBackgroundIO* op = static_cast<FileBackgroundIO*>(operation); - disk_cache::FileIOCallback* callback = operation->callback(); - int bytes = operation->Result(); + disk_cache::FileIOCallback* callback = op->callback(); + int bytes = operation->result(); // Release the references acquired in PostRead / PostWrite. - operation->file()->Release(); - io_list_.erase(make_scoped_refptr(operation)); + op->file()->Release(); callback->OnFileIOComplete(bytes); } +// A static object tha will broker all async operations. +FileInFlightIO* s_file_operations = NULL; + +// Returns the current FileInFlightIO. +FileInFlightIO* GetFileInFlightIO() { + if (!s_file_operations) { + s_file_operations = new FileInFlightIO; + } + return s_file_operations; +} + +// Deletes the current FileInFlightIO. +void DeleteFileInFlightIO() { + DCHECK(s_file_operations); + delete s_file_operations; + s_file_operations = NULL; +} + } // namespace namespace disk_cache { @@ -321,8 +237,7 @@ bool File::Read(void* buffer, size_t buffer_len, size_t offset, if (buffer_len > ULONG_MAX || offset > ULONG_MAX) return false; - InFlightIO* io_operations = Singleton<InFlightIO>::get(); - io_operations->PostRead(this, buffer, buffer_len, offset, callback); + GetFileInFlightIO()->PostRead(this, buffer, buffer_len, offset, callback); *completed = false; return true; @@ -346,8 +261,7 @@ bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset, if (buffer_len > ULONG_MAX || offset > ULONG_MAX) return false; - InFlightIO* io_operations = Singleton<InFlightIO>::get(); - io_operations->PostWrite(this, buffer, buffer_len, offset, callback); + GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback); if (completed) *completed = false; @@ -370,9 +284,10 @@ size_t File::GetLength() { // Static. void File::WaitForPendingIO(int* num_pending_io) { - // We may be running unit tests so we should allow InFlightIO to reset the + // We may be running unit tests so we should allow be able to reset the // message loop. - Singleton<InFlightIO>::get()->WaitForPendingIO(); + GetFileInFlightIO()->WaitForPendingIO(); + DeleteFileInFlightIO(); } } // namespace disk_cache |