| OLD | NEW | 
|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "base/threading/sequenced_task_runner_handle.h" | 5 #include "base/threading/sequenced_task_runner_handle.h" | 
| 6 | 6 | 
| 7 #include <utility> | 7 #include <utility> | 
| 8 | 8 | 
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" | 
| 10 #include "base/logging.h" | 10 #include "base/logging.h" | 
| 11 #include "base/threading/sequenced_worker_pool.h" | 11 #include "base/threading/sequenced_worker_pool.h" | 
| 12 #include "base/threading/thread_local.h" | 12 #include "base/threading/thread_local.h" | 
| 13 #include "base/threading/thread_task_runner_handle.h" | 13 #include "base/threading/thread_task_runner_handle.h" | 
| 14 | 14 | 
| 15 namespace base { | 15 namespace base { | 
| 16 | 16 | 
| 17 namespace { | 17 namespace { | 
| 18 | 18 | 
| 19 LazyInstance<ThreadLocalPointer<SequencedTaskRunnerHandle>>::Leaky | 19 LazyInstance<ThreadLocalPointer<SequencedTaskRunnerHandle>>::Leaky | 
| 20     lazy_tls_ptr = LAZY_INSTANCE_INITIALIZER; | 20     lazy_tls_strh_ptr = LAZY_INSTANCE_INITIALIZER; | 
| 21 | 21 | 
| 22 }  // namespace | 22 }  // namespace | 
| 23 | 23 | 
| 24 // static | 24 // static | 
| 25 scoped_refptr<SequencedTaskRunner> SequencedTaskRunnerHandle::Get() { | 25 scoped_refptr<SequencedTaskRunner> SequencedTaskRunnerHandle::Get() { | 
| 26   // Return the registered SingleThreadTaskRunner, if any. This must be at the | 26   // Return the registered SingleThreadTaskRunner, if any. This must be at the | 
| 27   // top so that a SingleThreadTaskRunner has priority over a | 27   // top so that a SingleThreadTaskRunner has priority over a | 
| 28   // SequencedTaskRunner (RLZ registers both on the same thread despite that | 28   // SequencedTaskRunner (RLZ registers both on the same thread despite that | 
| 29   // being prevented by DCHECKs). | 29   // being prevented by DCHECKs). | 
| 30   // TODO(fdoray): Move this to the bottom once RLZ stops registering a | 30   // TODO(fdoray): Move this to the bottom once RLZ stops registering a | 
| 31   // SingleThreadTaskRunner and a SequencedTaskRunner on the same thread. | 31   // SingleThreadTaskRunner and a SequencedTaskRunner on the same thread. | 
| 32   // https://crbug.com/618530#c14 | 32   // https://crbug.com/618530#c14 | 
| 33   if (ThreadTaskRunnerHandle::IsSet()) { | 33   if (ThreadTaskRunnerHandle::IsSet()) { | 
| 34     // Various modes of setting SequencedTaskRunnerHandle don't combine. | 34     // Various modes of setting SequencedTaskRunnerHandle don't combine. | 
| 35     DCHECK(!lazy_tls_ptr.Pointer()->Get()); | 35     DCHECK(!lazy_tls_strh_ptr.Pointer()->Get()); | 
| 36     DCHECK(!SequencedWorkerPool::GetSequenceTokenForCurrentThread().IsValid()); | 36     DCHECK(!SequencedWorkerPool::GetSequenceTokenForCurrentThread().IsValid()); | 
| 37 | 37 | 
| 38     return ThreadTaskRunnerHandle::Get(); | 38     return ThreadTaskRunnerHandle::Get(); | 
| 39   } | 39   } | 
| 40 | 40 | 
| 41   // Return the registered SequencedTaskRunner, if any. | 41   // Return the registered SequencedTaskRunner, if any. | 
| 42   const SequencedTaskRunnerHandle* handle = lazy_tls_ptr.Pointer()->Get(); | 42   const SequencedTaskRunnerHandle* handle = lazy_tls_strh_ptr.Pointer()->Get(); | 
| 43   if (handle) { | 43   if (handle) { | 
| 44     // Various modes of setting SequencedTaskRunnerHandle don't combine. | 44     // Various modes of setting SequencedTaskRunnerHandle don't combine. | 
| 45     DCHECK(!SequencedWorkerPool::GetSequenceTokenForCurrentThread().IsValid()); | 45     DCHECK(!SequencedWorkerPool::GetSequenceTokenForCurrentThread().IsValid()); | 
| 46 | 46 | 
| 47     return handle->task_runner_; | 47     return handle->task_runner_; | 
| 48   } | 48   } | 
| 49 | 49 | 
| 50   // If we are on a worker thread for a SequencedBlockingPool that is running a | 50   // If we are on a worker thread for a SequencedBlockingPool that is running a | 
| 51   // sequenced task, return a SequencedTaskRunner for it. | 51   // sequenced task, return a SequencedTaskRunner for it. | 
| 52   scoped_refptr<SequencedWorkerPool> pool = | 52   scoped_refptr<SequencedWorkerPool> pool = | 
| 53       SequencedWorkerPool::GetWorkerPoolForCurrentThread(); | 53       SequencedWorkerPool::GetWorkerPoolForCurrentThread(); | 
| 54   // Note if you hit this: the problem isn't the lack of a |pool|, it's the lack | 54   // Note if you hit this: the problem isn't the lack of a |pool|, it's the lack | 
| 55   // of a sequenced context above. The |pool| is just the last desperate attempt | 55   // of a sequenced context above. The |pool| is just the last desperate attempt | 
| 56   // at finding such a context from the deprecated SequencedWorkerPool. | 56   // at finding such a context from the deprecated SequencedWorkerPool. | 
| 57   CHECK(pool) << "Error: This caller requires a sequenced context (i.e. the " | 57   CHECK(pool) << "Error: This caller requires a sequenced context (i.e. the " | 
| 58                  "current task needs to run from a SequencedTaskRunner)."; | 58                  "current task needs to run from a SequencedTaskRunner)."; | 
| 59   SequencedWorkerPool::SequenceToken sequence_token = | 59   SequencedWorkerPool::SequenceToken sequence_token = | 
| 60       SequencedWorkerPool::GetSequenceTokenForCurrentThread(); | 60       SequencedWorkerPool::GetSequenceTokenForCurrentThread(); | 
| 61   DCHECK(sequence_token.IsValid()); | 61   DCHECK(sequence_token.IsValid()); | 
| 62   scoped_refptr<SequencedTaskRunner> sequenced_task_runner( | 62   scoped_refptr<SequencedTaskRunner> sequenced_task_runner( | 
| 63       pool->GetSequencedTaskRunner(sequence_token)); | 63       pool->GetSequencedTaskRunner(sequence_token)); | 
| 64   DCHECK(sequenced_task_runner->RunsTasksInCurrentSequence()); | 64   DCHECK(sequenced_task_runner->RunsTasksInCurrentSequence()); | 
| 65   return sequenced_task_runner; | 65   return sequenced_task_runner; | 
| 66 } | 66 } | 
| 67 | 67 | 
| 68 // static | 68 // static | 
| 69 bool SequencedTaskRunnerHandle::IsSet() { | 69 bool SequencedTaskRunnerHandle::IsSet() { | 
| 70   return lazy_tls_ptr.Pointer()->Get() || | 70   return lazy_tls_strh_ptr.Pointer()->Get() || | 
| 71          SequencedWorkerPool::GetSequenceTokenForCurrentThread().IsValid() || | 71          SequencedWorkerPool::GetSequenceTokenForCurrentThread().IsValid() || | 
| 72          ThreadTaskRunnerHandle::IsSet(); | 72          ThreadTaskRunnerHandle::IsSet(); | 
| 73 } | 73 } | 
| 74 | 74 | 
| 75 SequencedTaskRunnerHandle::SequencedTaskRunnerHandle( | 75 SequencedTaskRunnerHandle::SequencedTaskRunnerHandle( | 
| 76     scoped_refptr<SequencedTaskRunner> task_runner) | 76     scoped_refptr<SequencedTaskRunner> task_runner) | 
| 77     : task_runner_(std::move(task_runner)) { | 77     : task_runner_(std::move(task_runner)) { | 
| 78   DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 78   DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 
| 79   DCHECK(!SequencedTaskRunnerHandle::IsSet()); | 79   DCHECK(!SequencedTaskRunnerHandle::IsSet()); | 
| 80   lazy_tls_ptr.Pointer()->Set(this); | 80   lazy_tls_strh_ptr.Pointer()->Set(this); | 
| 81 } | 81 } | 
| 82 | 82 | 
| 83 SequencedTaskRunnerHandle::~SequencedTaskRunnerHandle() { | 83 SequencedTaskRunnerHandle::~SequencedTaskRunnerHandle() { | 
| 84   DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 84   DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 
| 85   DCHECK_EQ(lazy_tls_ptr.Pointer()->Get(), this); | 85   DCHECK_EQ(lazy_tls_strh_ptr.Pointer()->Get(), this); | 
| 86   lazy_tls_ptr.Pointer()->Set(nullptr); | 86   lazy_tls_strh_ptr.Pointer()->Set(nullptr); | 
| 87 } | 87 } | 
| 88 | 88 | 
| 89 }  // namespace base | 89 }  // namespace base | 
| OLD | NEW | 
|---|