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