105 lines · 3.2 KB · C
RawDownload
//// Dis VM// File: scheduler.h// Author: arr// #ifndef _DISVM_SRC_VM_SCHEDULER_H_#define _DISVM_SRC_VM_SCHEDULER_H_ #include <cstdint>#include <thread>#include <mutex>#include <condition_variable>#include <vector>#include <deque>#include <unordered_set>#include <unordered_map>#include <atomic>#include <disvm.h> namespace disvm{    namespace runtime    {        // Default multi-threaded scheduler        class default_scheduler_t final : public vm_scheduler_t, public vm_scheduler_control_t        {        private: // static            static void worker_main(default_scheduler_t &instance);         public:            default_scheduler_t(vm_t &vm, uint32_t system_thread_count, uint32_t thread_quanta);             ~default_scheduler_t();         public: // vm_scheduler_t            bool is_idle() const override;             vm_scheduler_control_t &get_controller() const override;             void schedule_thread(std::unique_ptr<vm_thread_t> thread) override;             void set_tool_dispatch_on_all_threads(vm_tool_dispatch_t *dispatch) override;         public: // vm_scheduler_control_t            void enqueue_blocked_thread(uint32_t thread_id) override;             std::size_t get_system_thread_count() const override;             std::vector<std::shared_ptr<const vm_thread_t>> get_all_threads() const override;         private:            struct thread_instance_t final            {                thread_instance_t(std::unique_ptr<vm_thread_t> t)                    : vm_thread{ std::move(t) }                {                }                 ~thread_instance_t()                {                    if (vm_thread != nullptr)                        vm_thread->release();                }                 std::shared_ptr<vm_thread_t> vm_thread;                std::mutex system_thread_ownership;            };             std::shared_ptr<thread_instance_t> next_thread(std::shared_ptr<thread_instance_t> prev_thread);             void perform_gc(bool is_gc_thread, std::unique_lock<std::mutex> &all_vm_threads_lock);             // Add the thread to the queue in a non-thread safe manner.            // Returns 'true' if the runnable thread queue has been updated, otherwise 'false'.            bool enqueue_thread_unsafe(thread_instance_t *thread, runtime::vm_thread_state_t current_state);         private:            vm_t &_vm;             const uint32_t _worker_thread_count;            std::vector<std::thread> _worker_pool;             std::condition_variable _worker_event;            std::atomic_bool _terminating;             const uint32_t _vm_thread_quanta;            mutable std::mutex _vm_threads_lock;            std::deque<uint32_t> _runnable_vm_thread_ids;            std::size_t _running_vm_thread_count;             std::mutex _gc_wait;            std::condition_variable _gc_done_event;            std::atomic_bool _gc_complete; // Used to avoid spurious wakeups            std::size_t _gc_counter;             std::unordered_set<uint32_t> _blocked_vm_thread_ids;             using all_thread_map_t = std::unordered_map<uint32_t, std::shared_ptr<thread_instance_t>>;            all_thread_map_t _all_vm_threads;        };    }} #endif // _DISVM_SRC_VM_SCHEDULER_H_