15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/condition_variable.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/sequenced_task_runner_test_template.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/test/sequenced_worker_pool_owner.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/task_runner_test_template.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/test/test_timeouts.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IMPORTANT NOTE: 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Many of these tests have failure modes where they'll hang forever. These 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// tests should not be flaky, and hanging indicates a type of failure. Do not 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mark as flaky if they're hanging, it's likely an actual bug. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kNumWorkerThreads = 3; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Allows a number of threads to all be blocked on the same event, and 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// provides a way to unblock a certain number of them. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadBlocker { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadBlocker() : lock_(), cond_var_(&lock_), unblock_counter_(0) {} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Block() { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (unblock_counter_ == 0) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_.Wait(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unblock_counter_--; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_.Signal(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Unblock(size_t count) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(unblock_counter_ == 0); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unblock_counter_ = count; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_.Signal(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock lock_; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ConditionVariable cond_var_; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t unblock_counter_; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestTracker : public base::RefCountedThreadSafe<TestTracker> { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestTracker() 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : lock_(), 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_(&lock_), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_events_(0) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Each of these tasks appends the argument to the complete sequence vector 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so calling code can see what order they finished in. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void FastTask(int id) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalWorkerDone(id); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SlowTask(int id) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalWorkerDone(id); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void BlockTask(int id, ThreadBlocker* blocker) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that this task has started and signal anybody waiting for that 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to happen. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_events_++; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_.Signal(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocker->Block(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalWorkerDone(id); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void PostAdditionalTasks( 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int id, SequencedWorkerPool* pool, 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool expected_return_value) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Closure fast_task = base::Bind(&TestTracker::FastTask, this, 100); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(expected_return_value, 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool->PostWorkerTaskWithShutdownBehavior( 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, fast_task, 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(expected_return_value, 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool->PostWorkerTaskWithShutdownBehavior( 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, fast_task, 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool->PostWorkerTaskWithShutdownBehavior( 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, fast_task, 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SequencedWorkerPool::BLOCK_SHUTDOWN); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SignalWorkerDone(id); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Waits until the given number of tasks have started executing. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void WaitUntilTasksBlocked(size_t count) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (started_events_ < count) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_.Wait(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_.Signal(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Blocks the current thread until at least the given number of tasks are in 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the completed vector, and then returns a copy. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> WaitUntilTasksComplete(size_t num_tasks) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> ret; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (complete_sequence_.size() < num_tasks) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_.Wait(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = complete_sequence_; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_.Signal(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t GetTasksCompletedCount() { 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(lock_); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return complete_sequence_.size(); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ClearCompleteSequence() { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) complete_sequence_.clear(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_events_ = 0; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<TestTracker>; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~TestTracker() {} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SignalWorkerDone(int id) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) complete_sequence_.push_back(id); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cond_var_.Signal(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Protects the complete_sequence. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock lock_; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ConditionVariable cond_var_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Protected by lock_. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> complete_sequence_; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Counter of the number of "block" workers that have started. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t started_events_; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolTest : public testing::Test { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolTest() 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : tracker_(new TestTracker) { 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResetPool(); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SequencedWorkerPoolTest() {} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() OVERRIDE {} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() OVERRIDE { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->Shutdown(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<SequencedWorkerPool>& pool() { 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return pool_owner_->pool(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestTracker* tracker() { return tracker_.get(); } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Destroys the SequencedWorkerPool instance, blocking until it is fully shut 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // down, and creates a new instance. 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void ResetPool() { 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test")); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetWillWaitForShutdownCallback(const Closure& callback) { 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool_owner_->SetWillWaitForShutdownCallback(callback); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensures that the given number of worker threads is created by adding 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tasks and waiting until they complete. Worker thread creation is 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // serialized, can happen on background threads asynchronously, and doesn't 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happen any more at shutdown. This means that if a test posts a bunch of 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tasks and calls shutdown, fewer workers will be created than the test may 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expect. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function ensures that this condition can't happen so tests can make 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // assumptions about the number of workers active. See the comment in 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PrepareToStartAdditionalThreadIfNecessary in the .cc file for more 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // details. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It will post tasks to the queue with id -1. It also assumes this is the 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first thing called in a test since it will clear the complete_sequence_. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void EnsureAllWorkersCreated() { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a bunch of threads, all waiting. This will cause that may 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // workers to be created. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadBlocker blocker; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < kNumWorkerThreads; i++) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTask(FROM_HERE, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker(), -1, &blocker)); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now wake them up and wait until they're done. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocker.Unblock(kNumWorkerThreads); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksComplete(kNumWorkerThreads); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clean up the task IDs we added. 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->ClearCompleteSequence(); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int has_work_call_count() const { 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return pool_owner_->has_work_call_count(); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageLoop message_loop_; 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SequencedWorkerPoolOwner> pool_owner_; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<TestTracker> tracker_; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks that the given number of entries are in the tasks to complete of 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the given tracker, and then signals the given event the given number of 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// times. This is used to wakt up blocked background threads before blocking 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on shutdown. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnsureTasksToCompleteCountAndUnblock(scoped_refptr<TestTracker> tracker, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t expected_tasks_to_complete, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadBlocker* blocker, 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t threads_to_awake) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ( 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expected_tasks_to_complete, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker->WaitUntilTasksComplete(expected_tasks_to_complete).size()); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocker->Unblock(threads_to_awake); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DeletionHelper : public base::RefCountedThreadSafe<DeletionHelper> { 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit DeletionHelper( 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<base::RefCountedData<bool> >& deleted_flag) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : deleted_flag_(deleted_flag) { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) friend class base::RefCountedThreadSafe<DeletionHelper>; 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~DeletionHelper() { deleted_flag_->data = true; } 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<base::RefCountedData<bool> > deleted_flag_; 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DeletionHelper); 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HoldPoolReference(const scoped_refptr<base::SequencedWorkerPool>& pool, 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<DeletionHelper>& helper) { 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ADD_FAILURE() << "Should never run"; 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests that delayed tasks are deleted upon shutdown of the pool. 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SequencedWorkerPoolTest, DelayedTaskDuringShutdown) { 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Post something to verify the pool is started up. 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(pool()->PostTask( 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 1))); 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedData<bool> > deleted_flag( 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new base::RefCountedData<bool>(false)); 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time posted_at(base::Time::Now()); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Post something that shouldn't run. 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(pool()->PostDelayedTask( 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&HoldPoolReference, 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool(), 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) make_scoped_refptr(new DeletionHelper(deleted_flag))), 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestTimeouts::action_timeout())); 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<int> completion_sequence = tracker()->WaitUntilTasksComplete(1); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(1u, completion_sequence.size()); 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(1, completion_sequence[0]); 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->Shutdown(); 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Shutdown is asynchronous, so use ResetPool() to block until the pool is 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // fully destroyed (and thus shut down). 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResetPool(); 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify that we didn't block until the task was due. 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_LT(base::Time::Now() - posted_at, TestTimeouts::action_timeout()); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify that the deferred task has not only not run, but has also been 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // destroyed. 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(deleted_flag->data); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that same-named tokens have the same ID. 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, NamedTokens) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string name1("hello"); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token1 = 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->GetNamedSequenceToken(name1); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string name3("goodbye"); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token3 = 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->GetNamedSequenceToken(name3); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All 3 tokens should be different. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(token1.Equals(token2)); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(token1.Equals(token3)); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(token2.Equals(token3)); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Requesting the same name again should give the same value. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token1again = 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->GetNamedSequenceToken(name1); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(token1.Equals(token1again)); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token3again = 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->GetNamedSequenceToken(name3); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(token3.Equals(token3again)); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that posting a bunch of tasks (many more than the number of worker 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// threads) runs them all. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, LotsOfTasks) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTask(FROM_HERE, 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::SlowTask, tracker(), 0)); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t kNumTasks = 20; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 1; i < kNumTasks; i++) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTask(FROM_HERE, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), i)); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> result = tracker()->WaitUntilTasksComplete(kNumTasks); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kNumTasks, result.size()); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that posting a bunch of tasks (many more than the number of 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// worker threads) to two pools simultaneously runs them all twice. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test is meant to shake out any concurrency issues between 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pools (like histograms). 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, LotsOfTasksTwoPools) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolOwner pool1(kNumWorkerThreads, "test1"); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolOwner pool2(kNumWorkerThreads, "test2"); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure slow_task = base::Bind(&TestTracker::SlowTask, tracker(), 0); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool1.pool()->PostWorkerTask(FROM_HERE, slow_task); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool2.pool()->PostWorkerTask(FROM_HERE, slow_task); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t kNumTasks = 20; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 1; i < kNumTasks; i++) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure fast_task = 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), i); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool1.pool()->PostWorkerTask(FROM_HERE, fast_task); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool2.pool()->PostWorkerTask(FROM_HERE, fast_task); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> result = 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksComplete(2*kNumTasks); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2 * kNumTasks, result.size()); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool2.pool()->Shutdown(); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool1.pool()->Shutdown(); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that tasks with the same sequence token are executed in order but don't 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// affect other tasks. 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, Sequence) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill all the worker threads except one. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t kNumBackgroundTasks = kNumWorkerThreads - 1; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadBlocker background_blocker; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < kNumBackgroundTasks; i++) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTask(FROM_HERE, 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker(), i, &background_blocker)); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksBlocked(kNumBackgroundTasks); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create two tasks with the same sequence token, one that will block on the 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // event, and one which will just complete quickly when it's run. Since there 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is one worker thread free, the first task will start and then block, and 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the second task should be waiting. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadBlocker blocker; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostSequencedWorkerTask( 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token1, FROM_HERE, 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, tracker(), 100, &blocker)); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostSequencedWorkerTask( 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token1, FROM_HERE, 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 101)); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create another two tasks as above with a different token. These will be 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // blocked since there are no slots to run. 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostSequencedWorkerTask( 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token2, FROM_HERE, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 200)); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostSequencedWorkerTask( 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token2, FROM_HERE, 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 201)); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let one background task complete. This should then let both tasks of 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // token2 run to completion in order. The second task of token1 should still 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be blocked. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_blocker.Unblock(1); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> result = tracker()->WaitUntilTasksComplete(3); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(3u, result.size()); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(200, result[1]); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(201, result[2]); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finish the rest of the background tasks. This should leave some workers 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // free with the second token1 task still blocked on the first. 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_blocker.Unblock(kNumBackgroundTasks - 1); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kNumBackgroundTasks + 2, 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 2).size()); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow the first task of token1 to complete. This should run the second. 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocker.Unblock(1); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 4); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(kNumBackgroundTasks + 4, result.size()); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(100, result[result.size() - 2]); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(101, result[result.size() - 1]); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that any tasks posted after Shutdown are ignored. 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Disabled for flakiness. See http://crbug.com/166451. 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SequencedWorkerPoolTest, DISABLED_IgnoresAfterShutdown) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start tasks to take all the threads and block them. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureAllWorkersCreated(); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadBlocker blocker; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < kNumWorkerThreads; i++) { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTask(FROM_HERE, 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker(), i, &blocker)); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWillWaitForShutdownCallback( 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&EnsureTasksToCompleteCountAndUnblock, 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TestTracker>(tracker()), 0, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &blocker, kNumWorkerThreads)); 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Shutdown the worker pool. This should discard all non-blocking tasks. 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kMaxNewBlockingTasksAfterShutdown = 100; 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->Shutdown(kMaxNewBlockingTasksAfterShutdown); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_has_work_call_count = has_work_call_count(); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> result = 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksComplete(kNumWorkerThreads); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The kNumWorkerThread items should have completed, in no particular order. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(kNumWorkerThreads, result.size()); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < kNumWorkerThreads; i++) { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) != 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.end()); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No further tasks, regardless of shutdown mode, should be allowed. 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 100), 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 101), 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 102), 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::BLOCK_SHUTDOWN)); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(old_has_work_call_count, has_work_call_count()); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SequencedWorkerPoolTest, AllowsAfterShutdown) { 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Test that <n> new blocking tasks are allowed provided they're posted 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // by a running tasks. 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EnsureAllWorkersCreated(); 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ThreadBlocker blocker; 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Start tasks to take all the threads and block them. 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kNumBlockTasks; ++i) { 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(pool()->PostWorkerTask( 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker))); 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Queue up shutdown blocking tasks behind those which will attempt to post 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // additional tasks when run, PostAdditionalTasks attemtps to post 3 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // new FastTasks, one for each shutdown_behavior. 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kNumQueuedTasks = static_cast<int>(kNumWorkerThreads); 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kNumQueuedTasks; ++i) { 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(pool()->PostWorkerTaskWithShutdownBehavior( 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&TestTracker::PostAdditionalTasks, tracker(), i, pool(), 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false), 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SequencedWorkerPool::BLOCK_SHUTDOWN)); 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Setup to open the floodgates from within Shutdown(). 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetWillWaitForShutdownCallback( 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&EnsureTasksToCompleteCountAndUnblock, 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TestTracker>(tracker()), 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, &blocker, kNumBlockTasks)); 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Allow half of the additional blocking tasks thru. 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kNumNewBlockingTasksToAllow = kNumWorkerThreads / 2; 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->Shutdown(kNumNewBlockingTasksToAllow); 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ensure that the correct number of tasks actually got run. 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracker()->WaitUntilTasksComplete(static_cast<size_t>( 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kNumBlockTasks + kNumQueuedTasks + kNumNewBlockingTasksToAllow)); 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Clean up the task IDs we added and go home. 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracker()->ClearCompleteSequence(); 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that unrun tasks are discarded properly according to their shutdown 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mode. 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, DiscardOnShutdown) { 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start tasks to take all the threads and block them. 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureAllWorkersCreated(); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadBlocker blocker; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < kNumWorkerThreads; i++) { 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTask(FROM_HERE, 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker(), i, &blocker)); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create some tasks with different shutdown modes. 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTaskWithShutdownBehavior( 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 100), 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTaskWithShutdownBehavior( 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 101), 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SKIP_ON_SHUTDOWN); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTaskWithShutdownBehavior( 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 102), 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::BLOCK_SHUTDOWN); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shutdown the worker pool. This should discard all non-blocking tasks. 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWillWaitForShutdownCallback( 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&EnsureTasksToCompleteCountAndUnblock, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TestTracker>(tracker()), 0, 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &blocker, kNumWorkerThreads)); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->Shutdown(); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> result = 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksComplete(kNumWorkerThreads + 1); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The kNumWorkerThread items should have completed, plus the BLOCK_SHUTDOWN 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one, in no particular order. 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(kNumWorkerThreads + 1, result.size()); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < kNumWorkerThreads; i++) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) != 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.end()); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(std::find(result.begin(), result.end(), 102) != result.end()); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that CONTINUE_ON_SHUTDOWN tasks don't block shutdown. 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, ContinueOnShutdown) { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TaskRunner> runner(pool()->GetTaskRunnerWithShutdownBehavior( 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SequencedTaskRunner> sequenced_runner( 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->GetSequencedTaskRunnerWithShutdownBehavior( 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->GetSequenceToken(), 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureAllWorkersCreated(); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadBlocker blocker; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTaskWithShutdownBehavior( 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker(), 0, &blocker), 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runner->PostTask( 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker(), 1, &blocker)); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequenced_runner->PostTask( 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker(), 2, &blocker)); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksBlocked(3); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should not block. If this test hangs, it means it failed. 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->Shutdown(); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The task should not have completed yet. 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Posting more tasks should fail. 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0), 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(runner->PostTask( 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(sequenced_runner->PostTask( 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Continue the background thread and make sure the tasks can complete. 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocker.Unblock(3); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> result = tracker()->WaitUntilTasksComplete(3); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(3u, result.size()); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that SKIP_ON_SHUTDOWN tasks that have been started block Shutdown 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// until they stop, but tasks not yet started do not. 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, SkipOnShutdown) { 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start tasks to take all the threads and block them. 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureAllWorkersCreated(); 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadBlocker blocker; 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now block all the threads with SKIP_ON_SHUTDOWN. Shutdown() should not 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return until these tasks have completed. 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < kNumWorkerThreads; i++) { 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTaskWithShutdownBehavior( 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker), 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SKIP_ON_SHUTDOWN); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now post an additional task as SKIP_ON_SHUTDOWN, which should not be 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // executed once Shutdown() has been called. 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTaskWithShutdownBehavior( 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestTracker::BlockTask, 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker(), 0, &blocker), 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SKIP_ON_SHUTDOWN); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This callback will only be invoked if SKIP_ON_SHUTDOWN tasks that have 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // been started block shutdown. 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWillWaitForShutdownCallback( 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&EnsureTasksToCompleteCountAndUnblock, 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TestTracker>(tracker()), 0, 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &blocker, kNumWorkerThreads)); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No tasks should have completed yet. 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should not block. If this test hangs, it means it failed. 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->Shutdown(); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shutdown should not return until all of the tasks have completed. 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> result = 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker()->WaitUntilTasksComplete(kNumWorkerThreads); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only tasks marked SKIP_ON_SHUTDOWN that were already started should be 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allowed to complete. No additional non-blocking tasks should have been 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // started. 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(kNumWorkerThreads, result.size()); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < kNumWorkerThreads; i++) { 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) != 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.end()); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ensure all worker threads are created, and then trigger a spurious 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// work signal. This shouldn't cause any other work signals to be 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// triggered. This is a regression test for http://crbug.com/117469. 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) { 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureAllWorkersCreated(); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_has_work_call_count = has_work_call_count(); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->SignalHasWorkForTesting(); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is inherently racy, but can only produce false positives. 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count()); 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IsRunningOnCurrentThreadTask( 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken test_positive_token, 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken test_negative_token, 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool* pool, 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool* unused_pool) { 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(pool->RunsTasksOnCurrentThread()); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(pool->IsRunningSequenceOnCurrentThread(test_positive_token)); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(pool->IsRunningSequenceOnCurrentThread(test_negative_token)); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread()); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE( 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unused_pool->IsRunningSequenceOnCurrentThread(test_positive_token)); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE( 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unused_pool->IsRunningSequenceOnCurrentThread(test_negative_token)); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify correctness of the IsRunningSequenceOnCurrentThread method. 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, IsRunningOnCurrentThread) { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken unsequenced_token; 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SequencedWorkerPool> unused_pool = 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new SequencedWorkerPool(2, "unused_pool"); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(pool()->RunsTasksOnCurrentThread()); 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token1)); 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token2)); 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(unsequenced_token)); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread()); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(unused_pool->IsRunningSequenceOnCurrentThread(token1)); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(unused_pool->IsRunningSequenceOnCurrentThread(token2)); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE( 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unused_pool->IsRunningSequenceOnCurrentThread(unsequenced_token)); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostSequencedWorkerTask( 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token1, FROM_HERE, 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&IsRunningOnCurrentThreadTask, 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token1, token2, pool(), unused_pool)); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostSequencedWorkerTask( 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token2, FROM_HERE, 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&IsRunningOnCurrentThreadTask, 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token2, unsequenced_token, pool(), unused_pool)); 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->PostWorkerTask( 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&IsRunningOnCurrentThreadTask, 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsequenced_token, token1, pool(), unused_pool)); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool()->Shutdown(); 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unused_pool->Shutdown(); 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Verify that FlushForTesting works as intended. 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SequencedWorkerPoolTest, FlushForTesting) { 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Should be fine to call on a new instance. 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->FlushForTesting(); 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Queue up a bunch of work, including a long delayed task and 7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a task that produces additional tasks as an artifact. 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->PostDelayedWorkerTask( 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 0), 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TimeDelta::FromMinutes(5)); 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->PostWorkerTask(FROM_HERE, 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&TestTracker::SlowTask, tracker(), 0)); 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t kNumFastTasks = 20; 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < kNumFastTasks; i++) { 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->PostWorkerTask(FROM_HERE, 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&TestTracker::FastTask, tracker(), 0)); 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->PostWorkerTask( 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&TestTracker::PostAdditionalTasks, tracker(), 0, pool(), 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) true)); 7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We expect all except the delayed task to have been run. We verify all 782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // closures have been deleted by looking at the refcount of the 7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // tracker. 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(tracker()->HasOneRef()); 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->FlushForTesting(); 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(tracker()->HasOneRef()); 7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(1 + kNumFastTasks + 1 + 3, tracker()->GetTasksCompletedCount()); 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Should be fine to call on an idle instance with all threads created, and 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // spamming the method shouldn't deadlock or confuse the class. 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->FlushForTesting(); 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->FlushForTesting(); 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Should be fine to call after shutdown too. 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->Shutdown(); 7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pool()->FlushForTesting(); 7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(SequencedWorkerPoolRefPtrTest, ShutsDownCleanWithContinueOnShutdown) { 800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MessageLoop loop; 801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<SequencedWorkerPool> pool(new SequencedWorkerPool(3, "Pool")); 802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<SequencedTaskRunner> task_runner = 803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pool->GetSequencedTaskRunnerWithShutdownBehavior( 804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pool->GetSequenceToken(), 805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); 806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Upon test exit, should shut down without hanging. 808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pool->Shutdown(); 809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolTaskRunnerTestDelegate { 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolTaskRunnerTestDelegate() {} 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~SequencedWorkerPoolTaskRunnerTestDelegate() {} 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartTaskRunner() { 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_.reset( 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SequencedWorkerPool> GetTaskRunner() { 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pool_owner_->pool(); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopTaskRunner() { 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure all tasks are run before shutting down. Delayed tasks are 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not run, they're simply deleted. 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_->pool()->FlushForTesting(); 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_->pool()->Shutdown(); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't reset |pool_owner_| here, as the test may still hold a 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reference to the pool. 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageLoop message_loop_; 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SequencedWorkerPoolOwner> pool_owner_; 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TYPED_TEST_CASE_P( 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool, TaskRunnerTest, 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolTaskRunnerTestDelegate); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate { 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate() {} 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate() { 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartTaskRunner() { 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_.reset( 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_runner_ = pool_owner_->pool()->GetTaskRunnerWithShutdownBehavior( 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::BLOCK_SHUTDOWN); 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TaskRunner> GetTaskRunner() { 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return task_runner_; 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopTaskRunner() { 8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure all tasks are run before shutting down. Delayed tasks are 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not run, they're simply deleted. 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_->pool()->FlushForTesting(); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_->pool()->Shutdown(); 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't reset |pool_owner_| here, as the test may still hold a 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reference to the pool. 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageLoop message_loop_; 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SequencedWorkerPoolOwner> pool_owner_; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TaskRunner> task_runner_; 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TYPED_TEST_CASE_P( 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolTaskRunner, TaskRunnerTest, 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolSequencedTaskRunnerTestDelegate { 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolSequencedTaskRunnerTestDelegate() {} 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~SequencedWorkerPoolSequencedTaskRunnerTestDelegate() { 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartTaskRunner() { 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_.reset(new SequencedWorkerPoolOwner( 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10, "SequencedWorkerPoolSequencedTaskRunnerTest")); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_runner_ = pool_owner_->pool()->GetSequencedTaskRunner( 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_->pool()->GetSequenceToken()); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SequencedTaskRunner> GetTaskRunner() { 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return task_runner_; 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopTaskRunner() { 9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure all tasks are run before shutting down. Delayed tasks are 9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not run, they're simply deleted. 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_->pool()->FlushForTesting(); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool_owner_->pool()->Shutdown(); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't reset |pool_owner_| here, as the test may still hold a 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reference to the pool. 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageLoop message_loop_; 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SequencedWorkerPoolOwner> pool_owner_; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SequencedTaskRunner> task_runner_; 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TYPED_TEST_CASE_P( 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest, 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolSequencedTaskRunnerTestDelegate); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TYPED_TEST_CASE_P( 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolSequencedTaskRunnerTestDelegate); 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 925