blob: 171378104e52df99d3c648193d56f3dd74ad726c [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/allocation.h"
#include "vm/globals.h"
#include "vm/os_thread.h"
namespace dart {
class ThreadPool {
// Subclasses of Task are able to run on a ThreadPool.
class Task {
virtual ~Task();
// Override this to provide task-specific behavior.
virtual void Run() = 0;
// Shuts down this thread pool. Causes workers to terminate
// themselves when they are active again.
// Runs a task on the thread pool.
bool Run(Task* task);
// Some simple stats.
uint64_t workers_running() const { return count_running_; }
uint64_t workers_idle() const { return count_idle_; }
uint64_t workers_started() const { return count_started_; }
uint64_t workers_stopped() const { return count_stopped_; }
class Worker {
explicit Worker(ThreadPool* pool);
// Sets a task on the worker.
void SetTask(Task* task);
// Starts the thread for the worker. This should only be called
// after a task has been set by the initial call to SetTask().
void StartThread();
// Main loop for a worker. Returns true if worker is removed from thread
// lists, false otherwise.
bool Loop();
// Causes worker to terminate eventually.
void Shutdown();
// Get the Worker's thread id.
ThreadId id();
friend class ThreadPool;
// The main entry point for new worker threads.
static void Main(uword args);
bool IsDone() const { return done_; }
// Fields owned by Worker.
Monitor monitor_;
ThreadPool* pool_;
Task* task_;
ThreadId id_;
bool done_;
// Fields owned by ThreadPool. Workers should not look at these
// directly. It's like looking at the sun.
bool owned_; // Protected by ThreadPool::mutex_
Worker* all_next_; // Protected by ThreadPool::mutex_
Worker* idle_next_; // Protected by ThreadPool::mutex_
Worker* shutdown_next_; // Protected by ThreadPool::exit_monitor
class JoinList {
explicit JoinList(ThreadJoinId id, JoinList* next) : id_(id), next_(next) {
// The thread pool's mutex_ must be held when calling this.
static void AddLocked(ThreadJoinId id, JoinList** list);
static void Join(JoinList** list);
ThreadJoinId id() const { return id_; }
JoinList* next() const { return next_; }
ThreadJoinId id_;
JoinList* next_;
void Shutdown();
// Expensive. Use only in assertions.
bool IsIdle(Worker* worker);
bool RemoveWorkerFromIdleList(Worker* worker);
bool RemoveWorkerFromAllList(Worker* worker);
void AddWorkerToShutdownList(Worker* worker);
bool RemoveWorkerFromShutdownList(Worker* worker);
void ReapExitedIdleThreads();
// Worker operations.
void SetIdleAndReapExited(Worker* worker);
bool ReleaseIdleWorker(Worker* worker);
Mutex mutex_;
bool shutting_down_;
Worker* all_workers_;
Worker* idle_workers_;
uint64_t count_started_;
uint64_t count_stopped_;
uint64_t count_running_;
uint64_t count_idle_;
Monitor exit_monitor_;
Worker* shutting_down_workers_;
JoinList* join_list_;
} // namespace dart
#endif // VM_THREAD_POOL_H_