diff options
author | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-30 22:33:46 +0000 |
---|---|---|
committer | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-30 22:33:46 +0000 |
commit | f6f074d0afc477add1bf6ec36b9848df747d175c (patch) | |
tree | dd7a629564259f2bf7223edf27b19c7827544ba8 /base | |
parent | da99b4e1d68bca6c208614ca9be23e47bd082eda (diff) | |
download | chromium_src-f6f074d0afc477add1bf6ec36b9848df747d175c.zip chromium_src-f6f074d0afc477add1bf6ec36b9848df747d175c.tar.gz chromium_src-f6f074d0afc477add1bf6ec36b9848df747d175c.tar.bz2 |
Add SequencedWorkerPool.IsRunningSequenceOnCurrentThread so callers can make stronger assertions about where methods are being called.
Review URL: https://chromiumcodereview.appspot.com/9845037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129979 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/threading/sequenced_worker_pool.cc | 30 | ||||
-rw-r--r-- | base/threading/sequenced_worker_pool.h | 4 | ||||
-rw-r--r-- | base/threading/sequenced_worker_pool_unittest.cc | 52 |
3 files changed, 86 insertions, 0 deletions
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc index be8f463..7054fba 100644 --- a/base/threading/sequenced_worker_pool.cc +++ b/base/threading/sequenced_worker_pool.cc @@ -63,8 +63,17 @@ class SequencedWorkerPool::Worker : public SimpleThread { // SimpleThread implementation. This actually runs the background thread. virtual void Run() OVERRIDE; + void set_running_sequence(SequenceToken token) { + running_sequence_ = token; + } + + SequenceToken running_sequence() const { + return running_sequence_; + } + private: scoped_refptr<SequencedWorkerPool> worker_pool_; + SequenceToken running_sequence_; DISALLOW_COPY_AND_ASSIGN(Worker); }; @@ -96,6 +105,8 @@ class SequencedWorkerPool::Inner { bool RunsTasksOnCurrentThread() const; + bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const; + void FlushForTesting(); void SignalHasWorkForTesting(); @@ -354,6 +365,15 @@ bool SequencedWorkerPool::Inner::RunsTasksOnCurrentThread() const { return ContainsKey(threads_, PlatformThread::CurrentId()); } +bool SequencedWorkerPool::Inner::IsRunningSequenceOnCurrentThread( + SequenceToken sequence_token) const { + AutoLock lock(lock_); + ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId()); + if (found == threads_.end()) + return false; + return found->second->running_sequence().Equals(sequence_token); +} + void SequencedWorkerPool::Inner::FlushForTesting() { AutoLock lock(lock_); while (!IsIdle()) @@ -435,8 +455,13 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) { if (new_thread_id) FinishStartingAdditionalThread(new_thread_id); + this_worker->set_running_sequence( + SequenceToken(task.sequence_token_id)); + task.task.Run(); + this_worker->set_running_sequence(SequenceToken()); + // Make sure our task is erased outside the lock for the same reason // we do this with delete_these_oustide_lock. task.task = Closure(); @@ -796,6 +821,11 @@ bool SequencedWorkerPool::RunsTasksOnCurrentThread() const { return inner_->RunsTasksOnCurrentThread(); } +bool SequencedWorkerPool::IsRunningSequenceOnCurrentThread( + SequenceToken sequence_token) const { + return inner_->IsRunningSequenceOnCurrentThread(sequence_token); +} + void SequencedWorkerPool::FlushForTesting() { inner_->FlushForTesting(); } diff --git a/base/threading/sequenced_worker_pool.h b/base/threading/sequenced_worker_pool.h index 83d677a..99d7bb9 100644 --- a/base/threading/sequenced_worker_pool.h +++ b/base/threading/sequenced_worker_pool.h @@ -219,6 +219,10 @@ class BASE_EXPORT SequencedWorkerPool : public TaskRunner { TimeDelta delay) OVERRIDE; virtual bool RunsTasksOnCurrentThread() const OVERRIDE; + // Returns true if the current thread is processing a task with the given + // sequence_token. + bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const; + // Blocks until all pending tasks are complete. This should only be called in // unit tests when you want to validate something that should have happened. // diff --git a/base/threading/sequenced_worker_pool_unittest.cc b/base/threading/sequenced_worker_pool_unittest.cc index e44599f..8a3508d 100644 --- a/base/threading/sequenced_worker_pool_unittest.cc +++ b/base/threading/sequenced_worker_pool_unittest.cc @@ -510,6 +510,58 @@ TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) { EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count()); } +void IsRunningOnCurrentThreadTask( + SequencedWorkerPool::SequenceToken test_positive_token, + SequencedWorkerPool::SequenceToken test_negative_token, + SequencedWorkerPool* pool, + SequencedWorkerPool* unused_pool) { + EXPECT_TRUE(pool->RunsTasksOnCurrentThread()); + EXPECT_TRUE(pool->IsRunningSequenceOnCurrentThread(test_positive_token)); + EXPECT_FALSE(pool->IsRunningSequenceOnCurrentThread(test_negative_token)); + EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread()); + EXPECT_FALSE( + unused_pool->IsRunningSequenceOnCurrentThread(test_positive_token)); + EXPECT_FALSE( + unused_pool->IsRunningSequenceOnCurrentThread(test_negative_token)); +} + +// Verify correctness of the IsRunningSequenceOnCurrentThread method. +TEST_F(SequencedWorkerPoolTest, IsRunningOnCurrentThread) { + SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); + SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); + SequencedWorkerPool::SequenceToken unsequenced_token; + + scoped_refptr<SequencedWorkerPool> unused_pool = + new SequencedWorkerPool(2, "unused_pool"); + EXPECT_TRUE(token1.Equals(unused_pool->GetSequenceToken())); + EXPECT_TRUE(token2.Equals(unused_pool->GetSequenceToken())); + + EXPECT_FALSE(pool()->RunsTasksOnCurrentThread()); + EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token1)); + EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token2)); + EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(unsequenced_token)); + EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread()); + EXPECT_FALSE(unused_pool->IsRunningSequenceOnCurrentThread(token1)); + EXPECT_FALSE(unused_pool->IsRunningSequenceOnCurrentThread(token2)); + EXPECT_FALSE( + unused_pool->IsRunningSequenceOnCurrentThread(unsequenced_token)); + + pool()->PostSequencedWorkerTask( + token1, FROM_HERE, + base::Bind(&IsRunningOnCurrentThreadTask, + token1, token2, pool(), unused_pool)); + pool()->PostSequencedWorkerTask( + token2, FROM_HERE, + base::Bind(&IsRunningOnCurrentThreadTask, + token2, unsequenced_token, pool(), unused_pool)); + pool()->PostWorkerTask( + FROM_HERE, + base::Bind(&IsRunningOnCurrentThreadTask, + unsequenced_token, token1, pool(), unused_pool)); + pool()->Shutdown(); + unused_pool->Shutdown(); +} + class SequencedWorkerPoolTaskRunnerTestDelegate { public: SequencedWorkerPoolTaskRunnerTestDelegate() {} |