// 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_