diff --git a/src/btop.cpp b/src/btop.cpp index 06dc42f..494418f 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -17,6 +17,7 @@ tab-size = 4 */ #include +#include #include #include #include @@ -237,14 +238,14 @@ void clean_quit(int sig) { } Logger::info("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time)); - //? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor -#ifndef __APPLE__ - if (Tools::active_locks > 0) { - quick_exit((sig != -1 ? sig : 0)); - } -#endif + const auto excode = (sig != -1 ? sig : 0); - if (sig != -1) exit(sig); + //? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor +#ifdef __APPLE__ + _Exit(excode); +#else + quick_exit(excode); +#endif } //* Handler for SIGTSTP; stops threads, restores terminal and sends SIGSTOP diff --git a/src/btop_input.cpp b/src/btop_input.cpp index 0fe5b9d..85ba644 100644 --- a/src/btop_input.cpp +++ b/src/btop_input.cpp @@ -19,6 +19,8 @@ tab-size = 4 #include #include #include +#include +#include #include #include @@ -78,14 +80,66 @@ namespace Input { deque history(50, ""); string old_filter; + struct InputThr { + InputThr() : thr(run, this) { + } + + static void run(InputThr* that) { + that->runImpl(); + } + + void runImpl() { + char ch = 0; + + // TODO(pg83): read whole buffer + while (cin.get(ch)) { + std::lock_guard g(lock); + current.push_back(ch); + if (current.size() > 100) { + current.clear(); + } + } + } + + size_t avail() { + std::lock_guard g(lock); + + return current.size(); + } + + std::string get() { + std::string res; + + { + std::lock_guard g(lock); + + res.swap(current); + } + + return res; + } + + static InputThr& instance() { + // intentional memory leak, to simplify shutdown process + static InputThr* input = new InputThr(); + + return *input; + } + + std::string current; + // TODO(pg83): use std::conditional_variable instead of sleep + std::mutex lock; + std::thread thr; + }; + bool poll(int timeout) { - if (timeout < 1) return cin.rdbuf()->in_avail() > 0; + if (timeout < 1) return InputThr::instance().avail() > 0; while (timeout > 0) { if (interrupt) { interrupt = false; return false; } - if (cin.rdbuf()->in_avail() > 0) return true; + if (InputThr::instance().avail() > 0) return true; sleep_ms(timeout < 10 ? timeout : 10); timeout -= 10; } @@ -93,9 +147,7 @@ namespace Input { } string get() { - string key; - while (cin.rdbuf()->in_avail() > 0 and key.size() < 100) key += cin.get(); - if (cin.rdbuf()->in_avail() > 0) clear(); + string key = InputThr::instance().get(); if (not key.empty()) { //? Remove escape code prefix if present if (key.substr(0, 2) == Fx::e) { @@ -168,19 +220,14 @@ namespace Input { } string wait() { - while (cin.rdbuf()->in_avail() < 1) { + while (InputThr::instance().avail() < 1) { sleep_ms(10); } return get(); } void clear() { - if (auto first_num = cin.rdbuf()->in_avail(); first_num > 0) { - while (cin.rdbuf()->in_avail() == first_num) { - if (first_num-- <= 0) break; - cin.ignore(1); - } - } + // do not need it, actually } void process(const string& key) {