15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef NET_DISK_CACHE_BLOCKFILE_IN_FLIGHT_IO_H_ 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define NET_DISK_CACHE_BLOCKFILE_IN_FLIGHT_IO_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/memory/ref_counted.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace base { 1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class TaskRunner; 1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} // namespace base 1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace disk_cache { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InFlightIO; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class represents a single asynchronous IO operation while it is being 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bounced between threads. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BackgroundIO : public base::RefCountedThreadSafe<BackgroundIO> { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Other than the actual parameters for the IO operation (including the 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |callback| that must be notified at the end), we need the controller that 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is keeping track of all operations. When done, we notify the controller 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (we do NOT invoke the callback), in the worker thead that completed the 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operation. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit BackgroundIO(InFlightIO* controller); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method signals the controller that this operation is finished, in the 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // original thread. In practice, this is a RunableMethod that allows 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cancellation. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnIOSignalled(); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allows the cancellation of the task to notify the controller (step number 8 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the diagram below). In practice, if the controller waits for the 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operation to finish it doesn't have to wait for the final task to be 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // processed by the message loop so calling this method prevents its delivery. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that this method is not intended to cancel the actual IO operation or 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to prevent the first notification to take place (OnIOComplete). 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Cancel(); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result() { return result_; } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent* io_completed() { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &io_completed_; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~BackgroundIO(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notifies the controller about the end of the operation, from the background 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyController(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_; // Final operation result. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<BackgroundIO>; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An event to signal when the operation completes. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent io_completed_; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InFlightIO* controller_; // The controller that tracks all operations. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock controller_lock_; // A lock protecting clearing of controller_. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BackgroundIO); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class keeps track of asynchronous IO operations. A single instance 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of this class is meant to be used to start an asynchronous operation (using 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PostXX, exposed by a derived class). This class will post the operation to a 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// worker thread, hanlde the notification when the operation finishes and 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// perform the callback on the same thread that was used to start the operation. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The regular sequence of calls is: 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Thread_1 Worker_thread 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. DerivedInFlightIO::PostXX() 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. -> PostTask -> 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. InFlightIO::OnOperationPosted() 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4. DerivedBackgroundIO::XX() 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5. IO operation completes 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 6. InFlightIO::OnIOComplete() 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 7. <- PostTask <- 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 8. BackgroundIO::OnIOSignalled() 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 9. InFlightIO::InvokeCallback() 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 10. DerivedInFlightIO::OnOperationComplete() 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 11. invoke callback 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Shutdown is a special case that is handled though WaitForPendingIO() instead 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of just waiting for step 7. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InFlightIO { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InFlightIO(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~InFlightIO(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Blocks the current thread until all IO operations tracked by this object 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // complete. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void WaitForPendingIO(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Drops current pending operations without waiting for them to complete. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DropPendingIO(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called on a background thread when |operation| completes. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnIOComplete(BackgroundIO* operation); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invokes the users' completion callback at the end of the IO operation. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |cancel_task| is true if the actual task posted to the thread is still 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // queued (because we are inside WaitForPendingIO), and false if said task is 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the one performing the call. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void InvokeCallback(BackgroundIO* operation, bool cancel_task); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method is called to signal the completion of the |operation|. |cancel| 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is true if the operation is being cancelled. This method is called on the 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread that created this object. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnOperationComplete(BackgroundIO* operation, bool cancel) = 0; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signals this object that the derived class just posted the |operation| to 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be executed on a background thread. This method must be called on the same 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread used to create this object. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnOperationPosted(BackgroundIO* operation); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::set<scoped_refptr<BackgroundIO> > IOList; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOList io_list_; // List of pending, in-flight io operations. 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<base::TaskRunner> callback_task_runner_; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool running_; // True after the first posted operation completes. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool single_thread_; // True if we only have one thread. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(InFlightIO); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace disk_cache 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif // NET_DISK_CACHE_BLOCKFILE_IN_FLIGHT_IO_H_ 141