blob: 6fbe0d7bcc32d083982cd8a1d813159e9259dc2f [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.
#ifndef RUNTIME_VM_THREAD_POOL_H_
#define RUNTIME_VM_THREAD_POOL_H_
#include "vm/allocation.h"
#include "vm/globals.h"
#include "vm/os_thread.h"
namespace dart {
class ThreadPool {
public:
// Subclasses of Task are able to run on a ThreadPool.
class Task {
protected:
Task();
public:
virtual ~Task();
// Override this to provide task-specific behavior.
virtual void Run() = 0;
private:
DISALLOW_COPY_AND_ASSIGN(Task);
};
ThreadPool();
// Shuts down this thread pool. Causes workers to terminate
// themselves when they are active again.
~ThreadPool();
// 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_; }
private:
class Worker {
public:
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();
private:
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
DISALLOW_COPY_AND_ASSIGN(Worker);
};
class JoinList {
public:
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_; }
private:
ThreadJoinId id_;
JoinList* next_;
DISALLOW_COPY_AND_ASSIGN(JoinList);
};
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 SetIdleLocked(Worker* worker); // Assumes mutex_ is held.
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_;
DISALLOW_COPY_AND_ASSIGN(ThreadPool);
};
} // namespace dart
#endif // RUNTIME_VM_THREAD_POOL_H_