55 , m_has_read_request(
false)
56 , m_read_status(state_init)
59 m_readline_buffer.start();
61 m_reader_thread = boost::thread(std::bind(&async_stdin_reader::reader_thread_func,
this));
73 return m_readline_buffer;
83 if (state_eos == m_read_status)
86 boost::unique_lock<boost::mutex> lock(m_response_mutex);
87 while (state_init == m_read_status)
89 m_response_cv.wait(lock);
93 if (state_success == m_read_status)
100 m_read_status = state_init;
105 bool eos()
const {
return m_read_status == state_eos; }
111 m_run.store(
false, std::memory_order_relaxed);
114 ::CloseHandle(::GetStdHandle(STD_INPUT_HANDLE));
117 m_request_cv.notify_one();
118 m_reader_thread.join();
120 m_readline_buffer.stop();
128 boost::unique_lock<boost::mutex> lock(m_request_mutex);
129 if (!m_run.load(std::memory_order_relaxed) || m_has_read_request)
132 m_has_read_request =
true;
133 m_request_cv.notify_one();
139 boost::unique_lock<boost::mutex> lock(m_request_mutex);
140 while (m_run.load(std::memory_order_relaxed) && !m_has_read_request)
142 m_request_cv.wait(lock);
145 if (m_has_read_request)
147 m_has_read_request =
false;
154 bool wait_stdin_data()
157 #if defined(__OpenBSD__) || defined(__ANDROID__)
158 int stdin_fileno = fileno(stdin);
160 int stdin_fileno = ::fileno(stdin);
163 while (m_run.load(std::memory_order_relaxed))
167 FD_SET(stdin_fileno, &read_set);
171 tv.tv_usec = 100 * 1000;
173 int retval = ::select(stdin_fileno + 1, &read_set, NULL, NULL, &tv);
180 while (m_run.load(std::memory_order_relaxed))
182 DWORD retval = ::WaitForSingleObject(::GetStdHandle(STD_INPUT_HANDLE), 100);
198 void reader_thread_func()
210 if (wait_stdin_data())
212 if (m_run.load(std::memory_order_relaxed))
215 switch (m_readline_buffer.get_line(line))
222 std::getline(std::cin, line);
224 read_ok = !std::cin.eof() && !std::cin.fail();
231 if (std::cin.eof()) {
235 m_read_status = state_eos;
236 m_response_cv.notify_one();
241 boost::unique_lock<boost::mutex> lock(m_response_mutex);
242 if (m_run.load(std::memory_order_relaxed))
244 m_line = std::move(line);
245 m_read_status = read_ok ? state_success : state_error;
249 m_read_status = state_cancelled;
251 m_response_cv.notify_one();
266 boost::thread m_reader_thread;
267 std::atomic<bool> m_run;
269 rdln::readline_buffer m_readline_buffer;
273 bool m_has_read_request;
274 t_state m_read_status;
276 boost::mutex m_request_mutex;
277 boost::mutex m_response_mutex;
278 boost::condition_variable m_request_cv;
279 boost::condition_variable m_response_cv;
297 template<
class t_server,
class chain_handler>
298 bool run(t_server* psrv, chain_handler ch_handler, std::function<std::string(
void)> prompt,
const std::string& usage =
"")
300 return run(prompt, usage, [&](
const std::string& cmd) {
return ch_handler(psrv, cmd); }, [&] { psrv->send_stop_signal(); });
303 template<
class chain_handler>
304 bool run(chain_handler ch_handler, std::function<std::string(
void)> prompt,
const std::string& usage =
"", std::function<
void(
void)> exit_handler = NULL)
306 return run(prompt, usage, [&](
const std::string& cmd) {
return ch_handler(cmd); }, exit_handler);
312 m_stdin_reader.stop();
317 std::string prompt = m_prompt();
321 std::string color_prompt =
"\001\033[1;33m\002" + prompt;
322 if (
' ' != prompt.back())
324 color_prompt +=
"\001\033[0m\002";
325 m_stdin_reader.get_readline_buffer().set_prompt(color_prompt);
329 if (
' ' != prompt.back())
338 template<
typename t_cmd_handler>
339 bool run(std::function<std::string(
void)> prompt,
const std::string& usage,
const t_cmd_handler& cmd_handler, std::function<
void(
void)> exit_handler)
341 bool continue_handle =
true;
343 while(continue_handle)
354 bool get_line_ret = m_stdin_reader.
get_line(command);
357 if (m_stdin_reader.
eos())
359 MGINFO(
"EOF on stdin, exiting");
360 std::cout << std::endl;
365 MERROR(
"Failed to read line.");
374 else if(cmd_handler(command))
378 else if(0 == command.compare(
"exit") || 0 == command.compare(
"q"))
380 continue_handle =
false;
385 rdln::suspend_readline pause_readline;
387 std::cout <<
"unknown command: " << command << std::endl;
391 catch (
const std::exception &ex)
393 LOG_ERROR(
"Exception at [console_handler], what=" << ex.what());
402 async_stdin_reader m_stdin_reader;
403 std::atomic<bool> m_running = {
true};
404 std::function<std::string(
void)> m_prompt;
409 bool start_default_console(t_server* ptsrv, t_handler handlr, std::function<std::string(
void)> prompt,
const std::string& usage =
"")
411 std::shared_ptr<async_console_handler> console_handler = std::make_shared<async_console_handler>();
412 boost::thread([=](){console_handler->run<t_server, t_handler>(ptsrv, handlr, prompt, usage);}).detach();