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 <list> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/atomic_sequence_num.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/critical_closure.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/lazy_instance.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/linked_ptr.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/condition_variable.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/simple_thread.h" 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/threading/thread_local.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/scoped_nsautorelease_pool.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if !defined(OS_NACL) 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/metrics/histogram.h" 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SequencedTask : public TrackingInfo { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedTask() 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : sequence_token_id(0), 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trace_id(0), 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequence_task_number(0), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_behavior(SequencedWorkerPool::BLOCK_SHUTDOWN) {} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit SequencedTask(const tracked_objects::Location& from_here) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : base::TrackingInfo(from_here, TimeTicks()), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequence_token_id(0), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trace_id(0), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequence_task_number(0), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_behavior(SequencedWorkerPool::BLOCK_SHUTDOWN) {} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~SequencedTask() {} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sequence_token_id; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int trace_id; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 sequence_task_number; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::WorkerShutdown shutdown_behavior; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::Location posted_from; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Closure task; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-delayed tasks and delayed tasks are managed together by time-to-run 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // order. We calculate the time by adding the posted time and the given delay. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks time_to_run; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SequencedTaskLessThan { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operator()(const SequencedTask& lhs, const SequencedTask& rhs) const { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lhs.time_to_run < rhs.time_to_run) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lhs.time_to_run > rhs.time_to_run) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the time happen to match, then we use the sequence number to decide. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return lhs.sequence_task_number < rhs.sequence_task_number; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SequencedWorkerPoolTaskRunner --------------------------------------------- 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A TaskRunner which posts tasks to a SequencedWorkerPool with a 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fixed ShutdownBehavior. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that this class is RefCountedThreadSafe (inherited from TaskRunner). 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolTaskRunner : public TaskRunner { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolTaskRunner( 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<SequencedWorkerPool>& pool, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::WorkerShutdown shutdown_behavior); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TaskRunner implementation 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool PostDelayedTask(const tracked_objects::Location& from_here, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) OVERRIDE; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool RunsTasksOnCurrentThread() const OVERRIDE; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SequencedWorkerPoolTaskRunner(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<SequencedWorkerPool> pool_; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SequencedWorkerPool::WorkerShutdown shutdown_behavior_; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPoolTaskRunner); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPoolTaskRunner::SequencedWorkerPoolTaskRunner( 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<SequencedWorkerPool>& pool, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::WorkerShutdown shutdown_behavior) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : pool_(pool), 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_behavior_(shutdown_behavior) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPoolTaskRunner::~SequencedWorkerPoolTaskRunner() { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPoolTaskRunner::PostDelayedTask( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delay == TimeDelta()) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pool_->PostWorkerTaskWithShutdownBehavior( 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_here, task, shutdown_behavior_); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pool_->PostDelayedWorkerTask(from_here, task, delay); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPoolTaskRunner::RunsTasksOnCurrentThread() const { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pool_->RunsTasksOnCurrentThread(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SequencedWorkerPoolSequencedTaskRunner ------------------------------------ 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A SequencedTaskRunner which posts tasks to a SequencedWorkerPool with a 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fixed sequence token. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that this class is RefCountedThreadSafe (inherited from TaskRunner). 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolSequencedTaskRunner : public SequencedTaskRunner { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPoolSequencedTaskRunner( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<SequencedWorkerPool>& pool, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::WorkerShutdown shutdown_behavior); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TaskRunner implementation 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool PostDelayedTask(const tracked_objects::Location& from_here, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) OVERRIDE; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool RunsTasksOnCurrentThread() const OVERRIDE; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SequencedTaskRunner implementation 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool PostNonNestableDelayedTask( 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) OVERRIDE; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SequencedWorkerPoolSequencedTaskRunner(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<SequencedWorkerPool> pool_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SequencedWorkerPool::SequenceToken token_; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SequencedWorkerPool::WorkerShutdown shutdown_behavior_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPoolSequencedTaskRunner); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPoolSequencedTaskRunner::SequencedWorkerPoolSequencedTaskRunner( 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<SequencedWorkerPool>& pool, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::SequenceToken token, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool::WorkerShutdown shutdown_behavior) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : pool_(pool), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_(token), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_behavior_(shutdown_behavior) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPoolSequencedTaskRunner:: 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)~SequencedWorkerPoolSequencedTaskRunner() { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPoolSequencedTaskRunner::PostDelayedTask( 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delay == TimeDelta()) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pool_->PostSequencedWorkerTaskWithShutdownBehavior( 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_, from_here, task, shutdown_behavior_); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pool_->PostDelayedSequencedWorkerTask(token_, from_here, task, delay); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPoolSequencedTaskRunner::RunsTasksOnCurrentThread() const { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pool_->IsRunningSequenceOnCurrentThread(token_); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPoolSequencedTaskRunner::PostNonNestableDelayedTask( 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) { 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There's no way to run nested tasks, so simply forward to 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // PostDelayedTask. 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return PostDelayedTask(from_here, task, delay); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Create a process-wide unique ID to represent this task in trace events. This 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will be mangled with a Process ID hash to reduce the likelyhood of colliding 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with MessageLoop pointers on other processes. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint64 GetTaskTraceID(const SequencedTask& task, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* pool) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (static_cast<uint64>(task.trace_id) << 32) | 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(reinterpret_cast<intptr_t>(pool)); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbase::LazyInstance<base::ThreadLocalPointer< 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SequencedWorkerPool::SequenceToken> >::Leaky g_lazy_tls_ptr = 2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch LAZY_INSTANCE_INITIALIZER; 2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Worker --------------------------------------------------------------------- 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPool::Worker : public SimpleThread { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hold a (cyclic) ref to |worker_pool|, since we want to keep it 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // around as long as we are running. 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Worker(const scoped_refptr<SequencedWorkerPool>& worker_pool, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int thread_number, 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& thread_name_prefix); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Worker(); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SimpleThread implementation. This actually runs the background thread. 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void set_running_task_info(SequenceToken token, 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WorkerShutdown shutdown_behavior) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) running_sequence_ = token; 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) running_shutdown_behavior_ = shutdown_behavior; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken running_sequence() const { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return running_sequence_; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WorkerShutdown running_shutdown_behavior() const { 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return running_shutdown_behavior_; 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SequencedWorkerPool> worker_pool_; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken running_sequence_; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WorkerShutdown running_shutdown_behavior_; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Worker); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Inner ---------------------------------------------------------------------- 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPool::Inner { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Take a raw pointer to |worker| to avoid cycles (since we're owned 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by it). 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Inner(SequencedWorkerPool* worker_pool, size_t max_threads, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& thread_name_prefix, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestingObserver* observer); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~Inner(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken GetSequenceToken(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken GetNamedSequenceToken(const std::string& name); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function accepts a name and an ID. If the name is null, the 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // token ID is used. This allows us to implement the optional name lookup 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from a single function without having to enter the lock a separate time. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool PostTask(const std::string* optional_token_name, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken sequence_token, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkerShutdown shutdown_behavior, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool RunsTasksOnCurrentThread() const; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CleanupForTesting(); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SignalHasWorkForTesting(); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int GetWorkSignalCountForTesting() const; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Shutdown(int max_blocking_tasks_after_shutdown); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool IsShutdownInProgress(); 3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Runs the worker loop on the background thread. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ThreadLoop(Worker* this_worker); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum GetWorkStatus { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_WORK_FOUND, 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_WORK_NOT_FOUND, 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_WORK_WAIT, 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enum CleanupState { 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CLEANUP_REQUESTED, 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CLEANUP_STARTING, 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CLEANUP_RUNNING, 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CLEANUP_FINISHING, 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CLEANUP_DONE, 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called from within the lock, this converts the given token name into a 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // token ID, creating a new one if necessary. 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int LockedGetNamedTokenID(const std::string& name); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called from within the lock, this returns the next sequence task number. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 LockedGetNextSequenceTaskNumber(); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Called from within the lock, returns the shutdown behavior of the task 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // running on the currently executing worker thread. If invoked from a thread 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that is not one of the workers, returns CONTINUE_ON_SHUTDOWN. 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WorkerShutdown LockedCurrentThreadShutdownBehavior() const; 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets new task. There are 3 cases depending on the return value: 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1) If the return value is |GET_WORK_FOUND|, |task| is filled in and should 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be run immediately. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2) If the return value is |GET_WORK_NOT_FOUND|, there are no tasks to run, 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and |task| is not filled in. In this case, the caller should wait until 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a task is posted. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3) If the return value is |GET_WORK_WAIT|, there are no tasks to run 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // immediately, and |task| is not filled in. Likewise, |wait_time| is 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // filled in the time to wait until the next task to run. In this case, the 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caller should wait the time. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In any case, the calling code should clear the given 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delete_these_outside_lock vector the next time the lock is released. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See the implementation for a more detailed description. 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWorkStatus GetWork(SequencedTask* task, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta* wait_time, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Closure>* delete_these_outside_lock); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void HandleCleanup(); 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Peforms init and cleanup around running the given task. WillRun... 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returns the value from PrepareToStartAdditionalThreadIfNecessary. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The calling code should call FinishStartingAdditionalThread once the 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lock is released if the return values is nonzero. 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int WillRunWorkerTask(const SequencedTask& task); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DidRunWorkerTask(const SequencedTask& task); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if there are no threads currently running the given 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sequence token. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsSequenceTokenRunnable(int sequence_token_id) const; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks if all threads are busy and the addition of one more could run an 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // additional task waiting in the queue. This must be called from within 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the lock. 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If another thread is helpful, this will mark the thread as being in the 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process of starting and returns the index of the new thread which will be 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0 or more. The caller should then call FinishStartingAdditionalThread to 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // complete initialization once the lock is released. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If another thread is not necessary, returne 0; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See the implementedion for more. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int PrepareToStartAdditionalThreadIfHelpful(); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The second part of thread creation after 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PrepareToStartAdditionalThreadIfHelpful with the thread number it 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // generated. This actually creates the thread and should be called outside 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the lock to avoid blocking important work starting a thread in the lock. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void FinishStartingAdditionalThread(int thread_number); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signal |has_work_| and increment |has_work_signal_count_|. 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SignalHasWork(); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks whether there is work left that's blocking shutdown. Must be 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called inside the lock. 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool CanShutdown() const; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool* const worker_pool_; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last sequence number used. Managed by GetSequenceToken, since this 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only does threadsafe increment operations, you do not need to hold the 3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // lock. This is class-static to make SequenceTokens issued by 3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // GetSequenceToken unique across SequencedWorkerPool instances. 3987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static base::StaticAtomicSequenceNumber g_last_sequence_number_; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This lock protects |everything in this class|. Do not read or modify 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // anything without holding this lock. Do not block while holding this 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lock. 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable Lock lock_; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Condition variable that is waited on by worker threads until new 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tasks are posted or shutdown starts. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConditionVariable has_work_cv_; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Condition variable that is waited on by non-worker threads (in 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shutdown()) until CanShutdown() goes to true. 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConditionVariable can_shutdown_cv_; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The maximum number of worker threads we'll create. 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t max_threads_; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string thread_name_prefix_; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Associates all known sequence token names with their IDs. 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<std::string, int> named_sequence_tokens_; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Owning pointers to all threads we've created so far, indexed by 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ID. Since we lazily create threads, this may be less than 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // max_threads_ and will be initially empty. 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<PlatformThreadId, linked_ptr<Worker> > ThreadMap; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadMap threads_; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set to true when we're in the process of creating another thread. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See PrepareToStartAdditionalThreadIfHelpful for more. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool thread_being_created_; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of threads currently waiting for work. 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t waiting_thread_count_; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of threads currently running tasks that have the BLOCK_SHUTDOWN 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or SKIP_ON_SHUTDOWN flag set. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t blocking_shutdown_thread_count_; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A set of all pending tasks in time-to-run order. These are tasks that are 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // either waiting for a thread to run on, waiting for their time to run, 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or blocked on a previous task in their sequence. We have to iterate over 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the tasks by time-to-run order, so we use the set instead of the 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // traditional priority_queue. 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::set<SequencedTask, SequencedTaskLessThan> PendingTaskSet; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingTaskSet pending_tasks_; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The next sequence number for a new sequenced task. 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 next_sequence_task_number_; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of tasks in the pending_tasks_ list that are marked as blocking 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutdown. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t blocking_shutdown_pending_task_count_; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lists all sequence tokens currently executing. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<int> current_sequences_; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An ID for each posted task to distinguish the task from others in traces. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int trace_id_; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set when Shutdown is called and no further tasks should be 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allowed, though we may still be running existing tasks. 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool shutdown_called_; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The number of new BLOCK_SHUTDOWN tasks that may be posted after Shudown() 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // has been called. 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int max_blocking_tasks_after_shutdown_; 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // State used to cleanup for testing, all guarded by lock_. 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CleanupState cleanup_state_; 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t cleanup_idlers_; 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConditionVariable cleanup_cv_; 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestingObserver* const testing_observer_; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Inner); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Worker definitions --------------------------------------------------------- 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::Worker::Worker( 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<SequencedWorkerPool>& worker_pool, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int thread_number, 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& prefix) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : SimpleThread( 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefix + StringPrintf("Worker%d", thread_number).c_str()), 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) worker_pool_(worker_pool), 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) running_shutdown_behavior_(CONTINUE_ON_SHUTDOWN) { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Start(); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::Worker::~Worker() { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SequencedWorkerPool::Worker::Run() { 4947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Store a pointer to the running sequence in thread local storage for 4957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // static function access. 4967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch g_lazy_tls_ptr.Get().Set(&running_sequence_); 4977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Just jump back to the Inner object to run the thread, since it has all the 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tracking information and queues. It might be more natural to implement 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using DelegateSimpleThread and have Inner implement the Delegate to avoid 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // having these worker objects at all, but that method lacks the ability to 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // send thread-specific information easily to the thread loop. 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) worker_pool_->inner_->ThreadLoop(this); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release our cyclic reference once we're done. 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) worker_pool_ = NULL; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Inner definitions --------------------------------------------------------- 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::Inner::Inner( 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedWorkerPool* worker_pool, 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_threads, 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& thread_name_prefix, 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestingObserver* observer) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : worker_pool_(worker_pool), 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_(), 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_work_cv_(&lock_), 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) can_shutdown_cv_(&lock_), 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_threads_(max_threads), 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_name_prefix_(thread_name_prefix), 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_being_created_(false), 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_thread_count_(0), 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocking_shutdown_thread_count_(0), 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_sequence_task_number_(0), 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocking_shutdown_pending_task_count_(0), 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trace_id_(0), 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_called_(false), 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_blocking_tasks_after_shutdown_(0), 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_state_(CLEANUP_DONE), 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_idlers_(0), 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_(&lock_), 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testing_observer_(observer) {} 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::Inner::~Inner() { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // You must call Shutdown() before destroying the pool. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(shutdown_called_); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to explicitly join with the threads before they're destroyed or else 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // they will be running when our object is half torn down. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ThreadMap::iterator it = threads_.begin(); it != threads_.end(); ++it) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->second->Join(); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) threads_.clear(); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (testing_observer_) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testing_observer_->OnDestruct(); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::SequenceToken 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::Inner::GetSequenceToken() { 5507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Need to add one because StaticAtomicSequenceNumber starts at zero, which 5517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // is used as a sentinel value in SequenceTokens. 5527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return SequenceToken(g_last_sequence_number_.GetNext() + 1); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::SequenceToken 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::Inner::GetNamedSequenceToken(const std::string& name) { 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoLock lock(lock_); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SequenceToken(LockedGetNamedTokenID(name)); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::Inner::PostTask( 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string* optional_token_name, 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken sequence_token, 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkerShutdown shutdown_behavior, 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delay == TimeDelta() || shutdown_behavior == SKIP_ON_SHUTDOWN); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedTask sequenced(from_here); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequenced.sequence_token_id = sequence_token.id_; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequenced.shutdown_behavior = shutdown_behavior; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequenced.posted_from = from_here; 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequenced.task = 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_behavior == BLOCK_SHUTDOWN ? 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MakeCriticalClosure(task) : task; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequenced.time_to_run = TimeTicks::Now() + delay; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int create_thread_id = 0; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoLock lock(lock_); 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (shutdown_called_) { 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (shutdown_behavior != BLOCK_SHUTDOWN || 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LockedCurrentThreadShutdownBehavior() == CONTINUE_ON_SHUTDOWN) { 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (max_blocking_tasks_after_shutdown_ <= 0) { 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DLOG(WARNING) << "BLOCK_SHUTDOWN task disallowed"; 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_blocking_tasks_after_shutdown_ -= 1; 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The trace_id is used for identifying the task in about:tracing. 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequenced.trace_id = trace_id_++; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT_FLOW_BEGIN0("task", "SequencedWorkerPool::PostTask", 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_ID_MANGLE(GetTaskTraceID(sequenced, static_cast<void*>(this)))); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequenced.sequence_task_number = LockedGetNextSequenceTaskNumber(); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now that we have the lock, apply the named token rules. 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (optional_token_name) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequenced.sequence_token_id = LockedGetNamedTokenID(*optional_token_name); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_tasks_.insert(sequenced); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shutdown_behavior == BLOCK_SHUTDOWN) 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocking_shutdown_pending_task_count_++; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_thread_id = PrepareToStartAdditionalThreadIfHelpful(); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Actually start the additional thread or signal an existing one now that 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we're outside the lock. 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (create_thread_id) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinishStartingAdditionalThread(create_thread_id); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalHasWork(); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::Inner::RunsTasksOnCurrentThread() const { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoLock lock(lock_); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ContainsKey(threads_, PlatformThread::CurrentId()); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::Inner::IsRunningSequenceOnCurrentThread( 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken sequence_token) const { 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoLock lock(lock_); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId()); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found == threads_.end()) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return sequence_token.Equals(found->second->running_sequence()); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// See https://code.google.com/p/chromium/issues/detail?id=168415 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SequencedWorkerPool::Inner::CleanupForTesting() { 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!RunsTasksOnCurrentThread()); 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ThreadRestrictions::ScopedAllowWait allow_wait; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoLock lock(lock_); 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(CLEANUP_DONE, cleanup_state_); 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (shutdown_called_) 6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pending_tasks_.empty() && waiting_thread_count_ == threads_.size()) 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_state_ = CLEANUP_REQUESTED; 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_idlers_ = 0; 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) has_work_cv_.Signal(); 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (cleanup_state_ != CLEANUP_DONE) 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_.Wait(); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SequencedWorkerPool::Inner::SignalHasWorkForTesting() { 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalHasWork(); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SequencedWorkerPool::Inner::Shutdown( 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int max_new_blocking_tasks_after_shutdown) { 6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_GE(max_new_blocking_tasks_after_shutdown, 0); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoLock lock(lock_); 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Cleanup and Shutdown should not be called concurrently. 6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(CLEANUP_DONE, cleanup_state_); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shutdown_called_) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_called_ = true; 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_blocking_tasks_after_shutdown_ = max_new_blocking_tasks_after_shutdown; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tickle the threads. This will wake up a waiting one so it will know that 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it can exit, which in turn will wake up any other waiting ones. 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalHasWork(); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There are no pending or running tasks blocking shutdown, we're done. 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CanShutdown()) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're here, then something is blocking shutdown. So wait for 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CanShutdown() to go to true. 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (testing_observer_) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testing_observer_->WillWaitForShutdown(); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if !defined(OS_NACL) 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks shutdown_wait_begin = TimeTicks::Now(); 6867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::ScopedAllowWait allow_wait; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoLock lock(lock_); 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!CanShutdown()) 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) can_shutdown_cv_.Wait(); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if !defined(OS_NACL) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("SequencedWorkerPool.ShutdownDelayTime", 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - shutdown_wait_begin); 6977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 6987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 6997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 7007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool SequencedWorkerPool::Inner::IsShutdownInProgress() { 7017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AutoLock lock(lock_); 7027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return shutdown_called_; 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoLock lock(lock_); 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thread_being_created_); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_being_created_ = false; 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<ThreadMap::iterator, bool> result = 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) threads_.insert( 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::make_pair(this_worker->tid(), make_linked_ptr(this_worker))); 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(result.second); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::mac::ScopedNSAutoreleasePool autorelease_pool; 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HandleCleanup(); 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See GetWork for what delete_these_outside_lock is doing. 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedTask task; 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta wait_time; 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Closure> delete_these_outside_lock; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWorkStatus status = 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWork(&task, &wait_time, &delete_these_outside_lock); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == GET_WORK_FOUND) { 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT_FLOW_END0("task", "SequencedWorkerPool::PostTask", 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_ID_MANGLE(GetTaskTraceID(task, static_cast<void*>(this)))); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT2("task", "SequencedWorkerPool::ThreadLoop", 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "src_file", task.posted_from.file_name(), 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "src_func", task.posted_from.function_name()); 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_thread_id = WillRunWorkerTask(task); 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoUnlock unlock(lock_); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There may be more work available, so wake up another 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // worker thread. (Technically not required, since we 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already get a signal for each new task, but it doesn't 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hurt.) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalHasWork(); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete_these_outside_lock.clear(); 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Complete thread creation outside the lock if necessary. 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_thread_id) 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinishStartingAdditionalThread(new_thread_id); 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this_worker->set_running_task_info( 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SequenceToken(task.sequence_token_id), task.shutdown_behavior); 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::TrackedTime start_time = 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::ThreadData::NowForStartOfRun(task.birth_tally); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task.task.Run(); 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(task, 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time, tracked_objects::ThreadData::NowForEndOfRun()); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure our task is erased outside the lock for the 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // same reason we do this with delete_these_oustide_lock. 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Also, do it before calling set_running_task_info() so 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that sequence-checking from within the task's destructor 7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // still works. 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task.task = Closure(); 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this_worker->set_running_task_info( 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SequenceToken(), CONTINUE_ON_SHUTDOWN); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DidRunWorkerTask(task); // Must be done inside the lock. 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (cleanup_state_ == CLEANUP_RUNNING) { 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (status) { 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GET_WORK_WAIT: { 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AutoUnlock unlock(lock_); 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_these_outside_lock.clear(); 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GET_WORK_NOT_FOUND: 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(delete_these_outside_lock.empty()); 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_state_ = CLEANUP_FINISHING; 7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_.Broadcast(); 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we're terminating and there's no more work, we can 7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // shut down, other workers can complete any pending or new tasks. 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We can get additional tasks posted after shutdown_called_ is set 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // but only worker threads are allowed to post tasks at that time, and 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the workers responsible for posting those tasks will be available 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to run them. Also, there may be some tasks stuck behind running 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ones with the same sequence token, but additional threads won't 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // help this case. 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shutdown_called_ && 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocking_shutdown_pending_task_count_ == 0) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_thread_count_++; 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GET_WORK_NOT_FOUND: 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_work_cv_.Wait(); 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GET_WORK_WAIT: 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_work_cv_.TimedWait(wait_time); 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_thread_count_--; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } // Release lock_. 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We noticed we should exit. Wake up the next worker so it knows it should 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exit as well (because the Shutdown() code only signals once). 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalHasWork(); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Possibly unblock shutdown. 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) can_shutdown_cv_.Signal(); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SequencedWorkerPool::Inner::HandleCleanup() { 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cleanup_state_ == CLEANUP_DONE) 8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cleanup_state_ == CLEANUP_REQUESTED) { 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We win, we get to do the cleanup as soon as the others wise up and idle. 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_state_ = CLEANUP_STARTING; 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (thread_being_created_ || 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_idlers_ != threads_.size() - 1) { 8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) has_work_cv_.Signal(); 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_.Wait(); 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_state_ = CLEANUP_RUNNING; 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cleanup_state_ == CLEANUP_STARTING) { 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Another worker thread is cleaning up, we idle here until thats done. 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++cleanup_idlers_; 8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_.Broadcast(); 8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (cleanup_state_ != CLEANUP_FINISHING) { 8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_.Wait(); 8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --cleanup_idlers_; 8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_.Broadcast(); 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cleanup_state_ == CLEANUP_FINISHING) { 8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We wait for all idlers to wake up prior to being DONE. 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (cleanup_idlers_ != 0) { 8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_.Broadcast(); 8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_.Wait(); 8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cleanup_state_ == CLEANUP_FINISHING) { 8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_state_ = CLEANUP_DONE; 8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_cv_.Signal(); 8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SequencedWorkerPool::Inner::LockedGetNamedTokenID( 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name) { 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!name.empty()); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<std::string, int>::const_iterator found = 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) named_sequence_tokens_.find(name); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found != named_sequence_tokens_.end()) 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return found->second; // Got an existing one. 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a new one for this name. 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken result = GetSequenceToken(); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) named_sequence_tokens_.insert(std::make_pair(name, result.id_)); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result.id_; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 SequencedWorkerPool::Inner::LockedGetNextSequenceTaskNumber() { 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We assume that we never create enough tasks to wrap around. 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return next_sequence_task_number_++; 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SequencedWorkerPool::WorkerShutdown 8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SequencedWorkerPool::Inner::LockedCurrentThreadShutdownBehavior() const { 8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lock_.AssertAcquired(); 8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId()); 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (found == threads_.end()) 8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CONTINUE_ON_SHUTDOWN; 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return found->second->running_shutdown_behavior(); 8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork( 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequencedTask* task, 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta* wait_time, 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Closure>* delete_these_outside_lock) { 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if !defined(OS_NACL) 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("SequencedWorkerPool.TaskCount", 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(pending_tasks_.size())); 9027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the next task with a sequence token that's not currently in use. 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the token is in use, that means another thread is running something 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in that sequence, and we can't run it without going out-of-order. 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This algorithm is simple and fair, but inefficient in some cases. For 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // example, say somebody schedules 1000 slow tasks with the same sequence 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // number. We'll have to go through all those tasks each time we feel like 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there might be work to schedule. If this proves to be a problem, we 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should make this more efficient. 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // One possible enhancement would be to keep a map from sequence ID to a 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list of pending but currently blocked SequencedTasks for that ID. 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When a worker finishes a task of one sequence token, it can pick up the 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // next one from that token right away. 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This may lead to starvation if there are sufficient numbers of sequences 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in use. To alleviate this, we could add an incrementing priority counter 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to each SequencedTask. Then maintain a priority_queue of all runnable 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tasks, sorted by priority counter. When a sequenced task is completed 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we would pop the head element off of that tasks pending list and add it 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the priority queue. Then we would run the first item in the priority 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // queue. 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWorkStatus status = GET_WORK_NOT_FOUND; 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int unrunnable_tasks = 0; 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingTaskSet::iterator i = pending_tasks_.begin(); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We assume that the loop below doesn't take too long and so we can just do 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a single call to TimeTicks::Now(). 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TimeTicks current_time = TimeTicks::Now(); 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (i != pending_tasks_.end()) { 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsSequenceTokenRunnable(i->sequence_token_id)) { 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrunnable_tasks++; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shutdown_called_ && i->shutdown_behavior != BLOCK_SHUTDOWN) { 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're shutting down and the task we just found isn't blocking 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutdown. Delete it and get more work. 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we do not want to delete unrunnable tasks. Deleting a task 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can have side effects (like freeing some objects) and deleting a 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // task that's supposed to run after one that's currently running could 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cause an obscure crash. 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We really want to delete these tasks outside the lock in case the 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // closures are holding refs to objects that want to post work from 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // their destructorss (which would deadlock). The closures are 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // internally refcounted, so we just need to keep a copy of them alive 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // until the lock is exited. The calling code can just clear() the 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // vector they passed to us once the lock is exited to make this 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happen. 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete_these_outside_lock->push_back(i->task); 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_tasks_.erase(i++); 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i->time_to_run > current_time) { 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The time to run has not come yet. 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *wait_time = i->time_to_run - current_time; 9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status = GET_WORK_WAIT; 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cleanup_state_ == CLEANUP_RUNNING) { 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Deferred tasks are deleted when cleaning up, see Inner::ThreadLoop. 9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_these_outside_lock->push_back(i->task); 9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_tasks_.erase(i); 9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Found a runnable task. 9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *task = *i; 9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_tasks_.erase(i); 9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (task->shutdown_behavior == BLOCK_SHUTDOWN) { 9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) blocking_shutdown_pending_task_count_--; 9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status = GET_WORK_FOUND; 9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Track the number of tasks we had to skip over to see if we should be 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // making this more efficient. If this number ever becomes large or is 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // frequently "some", we should consider the optimization above. 9877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if !defined(OS_NACL) 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("SequencedWorkerPool.UnrunnableTaskCount", 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrunnable_tasks); 9907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SequencedWorkerPool::Inner::WillRunWorkerTask(const SequencedTask& task) { 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the task's sequence number as in use. 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (task.sequence_token_id) 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_sequences_.insert(task.sequence_token_id); 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that threads running tasks posted with either SKIP_ON_SHUTDOWN 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or BLOCK_SHUTDOWN will prevent shutdown until that task or thread 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // completes. 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (task.shutdown_behavior != CONTINUE_ON_SHUTDOWN) 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocking_shutdown_thread_count_++; 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We just picked up a task. Since StartAdditionalThreadIfHelpful only 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // creates a new thread if there is no free one, there is a race when posting 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tasks that many tasks could have been posted before a thread started 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // running them, so only one thread would have been created. So we also check 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whether we should create more threads after removing our task from the 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // queue, which also has the nice side effect of creating the workers from 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // background threads rather than the main thread of the app. 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If another thread wasn't created, we want to wake up an existing thread 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if there is one waiting to pick up the next task. 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we really need to do this *before* running the task, not 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after. Otherwise, if more than one task is posted, the creation of the 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // second thread (since we only create one at a time) will be blocked by 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the execution of the first task, which could be arbitrarily long. 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PrepareToStartAdditionalThreadIfHelpful(); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SequencedWorkerPool::Inner::DidRunWorkerTask(const SequencedTask& task) { 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (task.shutdown_behavior != CONTINUE_ON_SHUTDOWN) { 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(blocking_shutdown_thread_count_, 0u); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocking_shutdown_thread_count_--; 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (task.sequence_token_id) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_sequences_.erase(task.sequence_token_id); 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::Inner::IsSequenceTokenRunnable( 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sequence_token_id) const { 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !sequence_token_id || 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_sequences_.find(sequence_token_id) == 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_sequences_.end(); 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SequencedWorkerPool::Inner::PrepareToStartAdditionalThreadIfHelpful() { 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // How thread creation works: 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'de like to avoid creating threads with the lock held. However, we 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // need to be sure that we have an accurate accounting of the threads for 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // proper Joining and deltion on shutdown. 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to figure out if we need another thread with the lock held, which 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is what this function does. It then marks us as in the process of creating 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a thread. When we do shutdown, we wait until the thread_being_created_ 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // flag is cleared, which ensures that the new thread is properly added to 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all the data structures and we can't leak it. Once shutdown starts, we'll 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // refuse to create more threads or they would be leaked. 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that this creates a mostly benign race condition on shutdown that 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will cause fewer workers to be created than one would expect. It isn't 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // much of an issue in real life, but affects some tests. Since we only spawn 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one worker at a time, the following sequence of events can happen: 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Main thread posts a bunch of unrelated tasks that would normally be 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // run on separate threads. 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. The first task post causes us to start a worker. Other tasks do not 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cause a worker to start since one is pending. 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3. Main thread initiates shutdown. 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4. No more threads are created since the shutdown_called_ flag is set. 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The result is that one may expect that max_threads_ workers to be created 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // given the workload, but in reality fewer may be created because the 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sequence of thread creation on the background threads is racing with the 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutdown call. 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shutdown_called_ && 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !thread_being_created_ && 10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cleanup_state_ == CLEANUP_DONE && 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) threads_.size() < max_threads_ && 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_thread_count_ == 0) { 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We could use an additional thread if there's work to be done. 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (PendingTaskSet::const_iterator i = pending_tasks_.begin(); 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != pending_tasks_.end(); ++i) { 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsSequenceTokenRunnable(i->sequence_token_id)) { 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Found a runnable task, mark the thread as being started. 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_being_created_ = true; 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(threads_.size() + 1); 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SequencedWorkerPool::Inner::FinishStartingAdditionalThread( 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int thread_number) { 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called outside of the lock. 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thread_number > 0); 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The worker is assigned to the list when the thread actually starts, which 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will manage the memory of the pointer. 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new Worker(worker_pool_, thread_number, thread_name_prefix_); 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SequencedWorkerPool::Inner::SignalHasWork() { 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_work_cv_.Signal(); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (testing_observer_) { 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testing_observer_->OnHasWork(); 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::Inner::CanShutdown() const { 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See PrepareToStartAdditionalThreadIfHelpful for how thread creation works. 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !thread_being_created_ && 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocking_shutdown_thread_count_ == 0 && 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocking_shutdown_pending_task_count_ == 0; 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbase::StaticAtomicSequenceNumber 11207dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSequencedWorkerPool::Inner::g_last_sequence_number_; 11217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SequencedWorkerPool -------------------------------------------------------- 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static 11257dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSequencedWorkerPool::SequenceToken 11267dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSequencedWorkerPool::GetSequenceTokenForCurrentThread() { 1127fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // Don't construct lazy instance on check. 1128fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch if (g_lazy_tls_ptr == NULL) 1129fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch return SequenceToken(); 1130fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 11317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SequencedWorkerPool::SequenceToken* token = g_lazy_tls_ptr.Get().Get(); 11327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!token) 11337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return SequenceToken(); 11347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return *token; 11357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 11367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::SequencedWorkerPool( 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_threads, 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& thread_name_prefix) 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : constructor_message_loop_(MessageLoopProxy::current()), 1141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_(new Inner(this, max_threads, thread_name_prefix, NULL)) { 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::SequencedWorkerPool( 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_threads, 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& thread_name_prefix, 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestingObserver* observer) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : constructor_message_loop_(MessageLoopProxy::current()), 1149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_(new Inner(this, max_threads, thread_name_prefix, observer)) { 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::~SequencedWorkerPool() {} 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SequencedWorkerPool::OnDestruct() const { 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(constructor_message_loop_.get()); 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Avoid deleting ourselves on a worker thread (which would 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deadlock). 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RunsTasksOnCurrentThread()) { 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) constructor_message_loop_->DeleteSoon(FROM_HERE, this); 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetSequenceToken() { 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->GetSequenceToken(); 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetNamedSequenceToken( 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name) { 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->GetNamedSequenceToken(name); 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<SequencedTaskRunner> SequencedWorkerPool::GetSequencedTaskRunner( 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken token) { 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetSequencedTaskRunnerWithShutdownBehavior(token, BLOCK_SHUTDOWN); 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<SequencedTaskRunner> 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::GetSequencedTaskRunnerWithShutdownBehavior( 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken token, WorkerShutdown shutdown_behavior) { 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new SequencedWorkerPoolSequencedTaskRunner( 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, token, shutdown_behavior); 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<TaskRunner> 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SequencedWorkerPool::GetTaskRunnerWithShutdownBehavior( 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkerShutdown shutdown_behavior) { 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new SequencedWorkerPoolTaskRunner(this, shutdown_behavior); 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::PostWorkerTask( 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task) { 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->PostTask(NULL, SequenceToken(), BLOCK_SHUTDOWN, 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_here, task, TimeDelta()); 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::PostDelayedWorkerTask( 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) { 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkerShutdown shutdown_behavior = 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delay == TimeDelta() ? BLOCK_SHUTDOWN : SKIP_ON_SHUTDOWN; 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->PostTask(NULL, SequenceToken(), shutdown_behavior, 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_here, task, delay); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::PostWorkerTaskWithShutdownBehavior( 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkerShutdown shutdown_behavior) { 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->PostTask(NULL, SequenceToken(), shutdown_behavior, 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_here, task, TimeDelta()); 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::PostSequencedWorkerTask( 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken sequence_token, 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task) { 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->PostTask(NULL, sequence_token, BLOCK_SHUTDOWN, 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_here, task, TimeDelta()); 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::PostDelayedSequencedWorkerTask( 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken sequence_token, 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) { 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkerShutdown shutdown_behavior = 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delay == TimeDelta() ? BLOCK_SHUTDOWN : SKIP_ON_SHUTDOWN; 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->PostTask(NULL, sequence_token, shutdown_behavior, 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_here, task, delay); 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::PostNamedSequencedWorkerTask( 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& token_name, 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task) { 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!token_name.empty()); 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->PostTask(&token_name, SequenceToken(), BLOCK_SHUTDOWN, 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_here, task, TimeDelta()); 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::PostSequencedWorkerTaskWithShutdownBehavior( 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken sequence_token, 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkerShutdown shutdown_behavior) { 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->PostTask(NULL, sequence_token, shutdown_behavior, 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_here, task, TimeDelta()); 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::PostDelayedTask( 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task, 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta delay) { 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PostDelayedWorkerTask(from_here, task, delay); 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::RunsTasksOnCurrentThread() const { 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->RunsTasksOnCurrentThread(); 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SequencedWorkerPool::IsRunningSequenceOnCurrentThread( 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequenceToken sequence_token) const { 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inner_->IsRunningSequenceOnCurrentThread(sequence_token); 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SequencedWorkerPool::FlushForTesting() { 12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) inner_->CleanupForTesting(); 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SequencedWorkerPool::SignalHasWorkForTesting() { 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inner_->SignalHasWorkForTesting(); 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SequencedWorkerPool::Shutdown(int max_new_blocking_tasks_after_shutdown) { 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(constructor_message_loop_->BelongsToCurrentThread()); 12802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) inner_->Shutdown(max_new_blocking_tasks_after_shutdown); 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool SequencedWorkerPool::IsShutdownInProgress() { 12847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return inner_->IsShutdownInProgress(); 12857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 12867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1288