Home | History | Annotate | Download | only in task_scheduler
      1 // Copyright 2016 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 BASE_TASK_SCHEDULER_SEQUENCE_H_
      6 #define BASE_TASK_SCHEDULER_SEQUENCE_H_
      7 
      8 #include <stddef.h>
      9 
     10 #include "base/base_export.h"
     11 #include "base/containers/queue.h"
     12 #include "base/macros.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/optional.h"
     15 #include "base/sequence_token.h"
     16 #include "base/task_scheduler/scheduler_lock.h"
     17 #include "base/task_scheduler/sequence_sort_key.h"
     18 #include "base/task_scheduler/task.h"
     19 #include "base/threading/sequence_local_storage_map.h"
     20 
     21 namespace base {
     22 namespace internal {
     23 
     24 // A Sequence holds slots each containing up to a single Task that must be
     25 // executed in posting order.
     26 //
     27 // In comments below, an "empty Sequence" is a Sequence with no slot.
     28 //
     29 // Note: there is a known refcounted-ownership cycle in the Scheduler
     30 // architecture: Sequence -> Task -> TaskRunner -> Sequence -> ...
     31 // This is okay so long as the other owners of Sequence (PriorityQueue and
     32 // SchedulerWorker in alternation and
     33 // SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetWork()
     34 // temporarily) keep running it (and taking Tasks from it as a result). A
     35 // dangling reference cycle would only occur should they release their reference
     36 // to it while it's not empty. In other words, it is only correct for them to
     37 // release it after PopTask() returns false to indicate it was made empty by
     38 // that call (in which case the next PushTask() will return true to indicate to
     39 // the caller that the Sequence should be re-enqueued for execution).
     40 //
     41 // This class is thread-safe.
     42 class BASE_EXPORT Sequence : public RefCountedThreadSafe<Sequence> {
     43  public:
     44   Sequence();
     45 
     46   // Adds |task| in a new slot at the end of the Sequence. Returns true if the
     47   // Sequence was empty before this operation.
     48   bool PushTask(Task task);
     49 
     50   // Transfers ownership of the Task in the front slot of the Sequence to the
     51   // caller. The front slot of the Sequence will be nullptr and remain until
     52   // Pop(). Cannot be called on an empty Sequence or a Sequence whose front slot
     53   // is already nullptr.
     54   //
     55   // Because this method cannot be called on an empty Sequence, the returned
     56   // Optional<Task> is never nullptr. An Optional is used in preparation for the
     57   // merge between TaskScheduler and TaskQueueManager (in Blink).
     58   // https://crbug.com/783309
     59   Optional<Task> TakeTask();
     60 
     61   // Removes the front slot of the Sequence. The front slot must have been
     62   // emptied by TakeTask() before this is called. Cannot be called on an empty
     63   // Sequence. Returns true if the Sequence is empty after this operation.
     64   bool Pop();
     65 
     66   // Returns a SequenceSortKey representing the priority of the Sequence. Cannot
     67   // be called on an empty Sequence.
     68   SequenceSortKey GetSortKey() const;
     69 
     70   // Returns a token that uniquely identifies this Sequence.
     71   const SequenceToken& token() const { return token_; }
     72 
     73   SequenceLocalStorageMap* sequence_local_storage() {
     74     return &sequence_local_storage_;
     75   }
     76 
     77  private:
     78   friend class RefCountedThreadSafe<Sequence>;
     79   ~Sequence();
     80 
     81   const SequenceToken token_ = SequenceToken::Create();
     82 
     83   // Synchronizes access to all members.
     84   mutable SchedulerLock lock_;
     85 
     86   // Queue of tasks to execute.
     87   base::queue<Task> queue_;
     88 
     89   // Number of tasks contained in the Sequence for each priority.
     90   size_t num_tasks_per_priority_[static_cast<int>(TaskPriority::HIGHEST) + 1] =
     91       {};
     92 
     93   // Holds data stored through the SequenceLocalStorageSlot API.
     94   SequenceLocalStorageMap sequence_local_storage_;
     95 
     96   DISALLOW_COPY_AND_ASSIGN(Sequence);
     97 };
     98 
     99 }  // namespace internal
    100 }  // namespace base
    101 
    102 #endif  // BASE_TASK_SCHEDULER_SEQUENCE_H_
    103