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