void VM::run_and_monitor() { for(;;) { if(interrupts.check_events) { interrupts.check_events = false; interrupts.enable_preempt = false; Thread* current = G(current_thread); // The current thread isn't asleep, so we're being preemptive if(current->alive() == Qtrue && current->sleep() != Qtrue) { // Order is important here. We poll so any threads // might get woken up if they need to be. events->poll(); // Only then do we reschedule the current thread if // we need to. queue_thread() puts the thread at the end // of the list for it's priority, so we shouldn't starve // anything this way. queue_thread(G(current_thread)); } while(!find_and_activate_thread()) { events->run_and_wait(); } interrupts.enable_preempt = interrupts.use_preempt; } collect_maybe(); G(current_task)->execute(); } }
void VM::activate_thread(Thread* thread) { if(thread == globals.current_thread.get()) { thread->task(this, globals.current_task.get()); return; } /* May have been using Tasks directly. */ globals.current_thread->task(this, globals.current_task.get()); queue_thread(globals.current_thread.get()); thread->sleep(this, Qfalse); globals.current_thread.set(thread); if(globals.current_task.get() != thread->task()) { activate_task(thread->task()); } }
int main() { #ifdef STACK_TESTS_ON /* [STACK] */ std::thread stack_thread(stack_test_suite_main); if (stack_thread.joinable()) { stack_thread.detach(); // F&F } std::cout << stack_thread.get_id() << std::endl; #endif #ifdef QUEUE_TESTS_ON /* [QUEUE] */ std::thread queue_thread(queue_test_suite_main); //queue_thread.detach(); if (queue_thread.joinable()) { queue_thread.join(); } #endif std::thread __ttt; std::cout << __ttt.get_id() << std::endl; std::cout << std::thread::hardware_concurrency() << std::endl; std::cout << std::this_thread::get_id() << std::endl; std::mutex m1; std::mutex m2; //std::lock_guard<std::mutex> g(m1); { std::lock(m1, m2); std::lock_guard<std::mutex> lg1(m1, std::adopt_lock); std::lock_guard<std::mutex> lg2(m2, std::adopt_lock); } std::lock(m1, m2); std::lock_guard<std::mutex> lg1(m1, std::adopt_lock); std::lock_guard<std::mutex> lg2(m2, std::adopt_lock); }
int main(int argc, char* argv[]){ //Use info flag to show useful output about program options.info_flag = false; //Set default options set_default_server_options(options); char option; while((option = getopt(argc,argv,"hdl:p:r:t:n:s:"))!=-1){ switch(option){ case 'h': show_help(); return 0; break; case 'd': options.debug_flag = true; break; case 'l': options.file = optarg; options.logging_enabled = true; break; case 'p': options.port = std::stoi(optarg, nullptr, 10); break; case 'r': options.dir = optarg; chdir(optarg); break; case 't': options.time = std::stoi(optarg, nullptr, 10); break; case 'n': options.threadnum = std::stoi(optarg, nullptr, 10); break; case 's': options.sched = optarg; break; default: break; } } if (options.debug_flag == false){ daemon(1, 0); } //At this point options struct contains all options to be used in program. if(options.info_flag == true) show_server_info(options); //Initialize server int server_socket_fd = initialize_server(options); //Main thread creates queueing thread std::thread queue_thread(http_request_handler, std::cref(server_socket_fd)); //Create the scheduling thread (the producer) //if(options.info_flag == true) std::cout <<"(Main thread): Creating scheduling thread\n"; std::thread scheduler_thread(http_request_scheduler); //Create worker threads (the consumers) from -n option //if(options.info_flag == true) std::cout << "(Main thread): Creating worker threads\n"; std::vector<std::thread> threads; threads.reserve(options.threadnum); for(int thread_id = 1 ; thread_id <= options.threadnum; thread_id++ ) { threads.emplace_back(process_queue_block, thread_id); std::this_thread::sleep_for (std::chrono::seconds(1)); } queue_thread.join(); scheduler_thread.join(); for(auto &thread : threads){ thread.detach(); } return 0; }