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 3 // found in the LICENSE file. 4 5 #ifndef NET_DNS_SERIAL_WORKER_H_ 6 #define NET_DNS_SERIAL_WORKER_H_ 7 8 #include <string> 9 10 #include "base/compiler_specific.h" 11 #include "base/memory/ref_counted.h" 12 #include "net/base/net_export.h" 13 14 // Forward declaration 15 namespace base { 16 class MessageLoopProxy; 17 } 18 19 namespace net { 20 21 // SerialWorker executes a job on WorkerPool serially -- **once at a time**. 22 // On |WorkNow|, a call to |DoWork| is scheduled on the WorkerPool. Once it 23 // completes, |OnWorkFinished| is called on the origin thread. 24 // If |WorkNow| is called (1 or more times) while |DoWork| is already under way, 25 // |DoWork| will be called once: after current |DoWork| completes, before a 26 // call to |OnWorkFinished|. 27 // 28 // This behavior is designed for updating a result after some trigger, for 29 // example reading a file once FilePathWatcher indicates it changed. 30 // 31 // Derived classes should store results of work done in |DoWork| in dedicated 32 // fields and read them in |OnWorkFinished| which is executed on the origin 33 // thread. This avoids the need to template this class. 34 // 35 // This implementation avoids locking by using the |state_| member to ensure 36 // that |DoWork| and |OnWorkFinished| cannot execute in parallel. 37 // 38 // TODO(szym): update to WorkerPool::PostTaskAndReply once available. 39 class NET_EXPORT_PRIVATE SerialWorker 40 : NON_EXPORTED_BASE(public base::RefCountedThreadSafe<SerialWorker>) { 41 public: 42 SerialWorker(); 43 44 // Unless already scheduled, post |DoWork| to WorkerPool. 45 // Made virtual to allow mocking. 46 virtual void WorkNow(); 47 48 // Stop scheduling jobs. 49 void Cancel(); 50 51 bool IsCancelled() const { return state_ == CANCELLED; } 52 53 protected: 54 friend class base::RefCountedThreadSafe<SerialWorker>; 55 // protected to allow sub-classing, but prevent deleting 56 virtual ~SerialWorker(); 57 58 // Executed on WorkerPool, at most once at a time. 59 virtual void DoWork() = 0; 60 61 // Executed on origin thread after |DoRead| completes. 62 virtual void OnWorkFinished() = 0; 63 64 base::MessageLoopProxy* loop() { return message_loop_.get(); } 65 66 private: 67 enum State { 68 CANCELLED = -1, 69 IDLE = 0, 70 WORKING, // |DoWorkJob| posted on WorkerPool, until |OnWorkJobFinished| 71 PENDING, // |WorkNow| while WORKING, must re-do work 72 WAITING, // WorkerPool is busy, |RetryWork| is posted 73 }; 74 75 // Called on the worker thread, executes |DoWork| and notifies the origin 76 // thread. 77 void DoWorkJob(); 78 79 // Called on the the origin thread after |DoWork| completes. 80 void OnWorkJobFinished(); 81 82 // Posted to message loop in case WorkerPool is busy. (state == WAITING) 83 void RetryWork(); 84 85 // Message loop for the thread of origin. 86 scoped_refptr<base::MessageLoopProxy> message_loop_; 87 88 State state_; 89 90 DISALLOW_COPY_AND_ASSIGN(SerialWorker); 91 }; 92 93 } // namespace net 94 95 #endif // NET_DNS_SERIAL_WORKER_H_ 96 97