Files
sdk/runtime/vm/thread_pool.h
T
Zach Anderson 5f59a954f8 Uses an open thread handle as the ThreadJoinId on Windows.
Also:
- Reaps exited threads in the thread pool before putting
a thread on the idle list so that a new arriving task
isn't blocked on a supposedly idle thread in the middle
of a join.
- Stops trying to join eventhandler threads on
Windows. Now that we're using the correct exit() call,
we probably don't have to worry about exit code pollution,
so joining the threads is unnecessary.

related #26400

R=asiva@google.com, iposva@google.com

Review URL: https://codereview.chromium.org/1978153002 .
2016-05-17 13:18:13 -07:00

151 lines
3.7 KiB
C++

// 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 VM_THREAD_POOL_H_
#define 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 // VM_THREAD_POOL_H_