serial_worker.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. #ifndef NET_DNS_SERIAL_WORKER_H_
  5. #define NET_DNS_SERIAL_WORKER_H_
  6. #include <memory>
  7. #include "base/callback.h"
  8. #include "base/compiler_specific.h"
  9. #include "base/memory/weak_ptr.h"
  10. #include "base/sequence_checker.h"
  11. #include "base/task/task_traits.h"
  12. #include "base/timer/timer.h"
  13. #include "net/base/backoff_entry.h"
  14. #include "net/base/net_export.h"
  15. namespace net {
  16. // `SerialWorker` executes a job on `ThreadPool` serially -- **one at a time**.
  17. // On `WorkNow()`, a `WorkItem` is created using `CreateWorkItem()` and sent to
  18. // the `ThreadPool`. There, a call to `DoWork()` is made. On completion of work,
  19. // `OnWorkFinished()` is called on the origin thread (if the `SerialWorker` is
  20. // still alive), passing back the `WorkItem` to allow retrieving any results or
  21. // passed objects. If `WorkNow()` is called (1 or more times) while a `WorkItem`
  22. // is already under way, after completion of the work and before any call is
  23. // made to `OnWorkFinished()` the same `WorkItem` will be passed back to the
  24. // `ThreadPool`, and `DoWork()` will be called once more.
  25. //
  26. // If |OnWorkFinished| returns a failure and |max_number_of_retries|
  27. // is non-zero, retries will be scheduled according to the |backoff_policy|.
  28. // A default backoff policy is used if one is not provided.
  29. //
  30. // This behavior is designed for updating a result after some trigger, for
  31. // example reading a file once FilePathWatcher indicates it changed.
  32. //
  33. // Derived classes should store results of work in the `WorkItem` and retrieve
  34. // results from it when passed back to `OnWorkFinished()`. The `SerialWorker` is
  35. // guaranteed to only run one `WorkItem` at a time, always passing it back to
  36. // `OnWorkFinished()` before calling `CreateWorkItem()` again. Therefore, a
  37. // derived class may safely pass objects between `WorkItem`s, or even reuse the
  38. // same `WorkItem`, to allow storing helper objects directly in the `WorkItem`.
  39. // However, it is not guaranteed that the `SerialWorker` will remain alive while
  40. // the `WorkItem` runs. Therefore, the `WorkItem` should never access any memory
  41. // owned by the `SerialWorker` or derived class.
  42. class NET_EXPORT_PRIVATE SerialWorker {
  43. public:
  44. // A work item that will be passed to and run on the `ThreadPool` (potentially
  45. // multiple times if the `SerialWorker` needs to run again immediately) and
  46. // then passed back to the origin thread on completion. Expected usage is to
  47. // store any parameters, results, and helper objects in the `WorkItem` and
  48. // read results from it when passed back to the origin thread.
  49. //
  50. // `SerialWorker` calls `FollowupWork()` *on the origin thread* after calling
  51. // `DoWork()` on the `ThreadPool` to asynchronously handle any work that must
  52. // be part of the serialization but that cannot run on a worker thread.
  53. class NET_EXPORT_PRIVATE WorkItem {
  54. public:
  55. virtual ~WorkItem() = default;
  56. virtual void DoWork() = 0;
  57. virtual void FollowupWork(base::OnceClosure closure);
  58. };
  59. explicit SerialWorker(
  60. int max_number_of_retries = 0,
  61. const net::BackoffEntry::Policy* backoff_policy = nullptr);
  62. SerialWorker(const SerialWorker&) = delete;
  63. SerialWorker& operator=(const SerialWorker&) = delete;
  64. // Unless already scheduled, post |DoWork| to ThreadPool.
  65. // Made virtual to allow mocking.
  66. virtual void WorkNow();
  67. // Stop scheduling jobs.
  68. void Cancel();
  69. bool IsCancelled() const { return state_ == State::kCancelled; }
  70. // Allows tests to inspect the current backoff/retry state.
  71. const BackoffEntry& GetBackoffEntryForTesting() const;
  72. const base::OneShotTimer& GetRetryTimerForTesting() const;
  73. protected:
  74. // protected to allow sub-classing, but prevent deleting
  75. virtual ~SerialWorker();
  76. // Create a new WorkItem to be passed to and run on the ThreadPool.
  77. virtual std::unique_ptr<WorkItem> CreateWorkItem() = 0;
  78. // Executed on origin thread after `WorkItem` completes.
  79. // Must return true on success.
  80. virtual bool OnWorkFinished(std::unique_ptr<WorkItem> work_item) = 0;
  81. base::WeakPtr<SerialWorker> AsWeakPtr();
  82. // Used to verify that the constructor, WorkNow(), Cancel() and
  83. // OnWorkJobFinished() are called on the same sequence.
  84. SEQUENCE_CHECKER(sequence_checker_);
  85. private:
  86. enum class State {
  87. kCancelled = -1,
  88. kIdle = 0,
  89. kWorking, // |DoWorkJob| posted to ThreadPool, until |OnWorkJobFinished|
  90. kPending, // |WorkNow| while WORKING, must re-do work
  91. };
  92. void WorkNowInternal();
  93. // Called on the origin thread after `WorkItem::DoWork()` completes.
  94. void OnDoWorkFinished(std::unique_ptr<WorkItem> work_item);
  95. // Called on the origin thread after `WorkItem::FollowupWork()` completes.
  96. void OnFollowupWorkFinished(std::unique_ptr<WorkItem> work_item);
  97. void RerunWork(std::unique_ptr<WorkItem> work_item);
  98. State state_ = State::kIdle;
  99. // Max retries and backoff entry to control timing.
  100. const int max_number_of_retries_;
  101. BackoffEntry backoff_entry_;
  102. base::OneShotTimer retry_timer_;
  103. base::WeakPtrFactory<SerialWorker> weak_factory_{this};
  104. };
  105. } // namespace net
  106. #endif // NET_DNS_SERIAL_WORKER_H_