Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move the watcher cli into the util directory
- Loading branch information
1 parent
b58f70b
commit 4b7951a
Showing
5 changed files
with
603 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
program=build/abc-watcher | ||
make $program && ./$program "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* Copyright (c) 2014, AirBitz, Inc. | ||
* All rights reserved. | ||
*/ | ||
|
||
#include "ReadLine.hpp" | ||
#include <cstring> | ||
#include <iostream> | ||
|
||
ReadLine::~ReadLine() | ||
{ | ||
socket_.send("", 1); | ||
thread_->join(); | ||
delete thread_; | ||
} | ||
|
||
ReadLine::ReadLine(zmq::context_t &context) | ||
: socket_(context, ZMQ_REQ) | ||
{ | ||
socket_.bind("inproc://terminal"); | ||
// The thread must be constructed after the socket is already bound. | ||
// The context must be passed by pointer to avoid copying. | ||
auto functor = std::bind(&ReadLine::run, this, &context); | ||
thread_ = new std::thread(functor); | ||
} | ||
|
||
void ReadLine::show_prompt() | ||
{ | ||
std::cout << "> " << std::flush; | ||
socket_.send("", 0); | ||
} | ||
|
||
zmq_pollitem_t ReadLine::pollitem() | ||
{ | ||
return zmq_pollitem_t | ||
{ | ||
socket_, 0, ZMQ_POLLIN, 0 | ||
}; | ||
} | ||
|
||
std::string ReadLine::get_line() | ||
{ | ||
char line[1000]; | ||
size_t size = socket_.recv(line, sizeof(line), ZMQ_DONTWAIT); | ||
return std::string(line, size); | ||
} | ||
|
||
void ReadLine::run(zmq::context_t *context) | ||
{ | ||
zmq::socket_t socket(*context, ZMQ_REP); | ||
socket.connect("inproc://terminal"); | ||
|
||
while (true) | ||
{ | ||
// Wait for a socket request: | ||
char request[1]; | ||
if (socket.recv(request, sizeof(request))) | ||
return; | ||
|
||
// Read the input: | ||
char line[1000]; | ||
std::cin.getline(line, sizeof(line)); | ||
socket.send(line, std::strlen(line)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* Copyright (c) 2014, AirBitz, Inc. | ||
* All rights reserved. | ||
*/ | ||
|
||
#ifndef UTIL_READ_LINE_HPP | ||
#define UTIL_READ_LINE_HPP | ||
|
||
#include <string> | ||
#include <thread> | ||
#include <zmq.hpp> | ||
|
||
/* | ||
* Reads lines from the terminal in a separate thread. | ||
* | ||
* A networking thread cannot use the C++ standard library to read from the | ||
* terminal. Once the thread calls std::cin.getline or similar, it becomes | ||
* stuck until the user types something, so the thread cannot handle network | ||
* events at the same time. Therefore, the network stuff and the terminal | ||
* stuff need to run in separate threads. | ||
* | ||
* The simplest solution is to create a thread that simply reads from the | ||
* terminal and transmits the results over a zeromq inproc socket. The main | ||
* thread sends an empty REQ message when it wants to read from the terminal, | ||
* and the reader thread sends back a REP message with whatever the user | ||
* typed. If the main thread sends a non-empty REQ message, the thread quits. | ||
* | ||
* To use this class, first call `show_prompt`. This call will display a | ||
* command prompt and begin reading input in the background. Then, use | ||
* `pollitem` with `zmq_poll` to determine when the line is available. Once | ||
* the line is available, use `get_line` to retrieve it. | ||
* | ||
* If you attempt to destroy this class while reading a line, the destructor | ||
* will block until the user finishes their entry. | ||
*/ | ||
class ReadLine | ||
{ | ||
public: | ||
~ReadLine(); | ||
ReadLine(zmq::context_t &context); | ||
|
||
/** | ||
* Displays a command prompt and begins reading a line in the background. | ||
*/ | ||
void show_prompt(); | ||
|
||
/** | ||
* Creates a zeromq pollitem_t structure suitable for passing to the | ||
* zmq_poll function. The zmq_poll function will indicate that there is | ||
* data waiting to be read once a line is available. | ||
*/ | ||
zmq_pollitem_t pollitem(); | ||
|
||
/** | ||
* Retrieves the line requested by `show_prompt`. This method will | ||
* return a blank string if no line is available yet. | ||
*/ | ||
std::string get_line(); | ||
|
||
private: | ||
void run(zmq::context_t *context); | ||
|
||
zmq::socket_t socket_; | ||
std::thread *thread_; | ||
}; | ||
|
||
#endif |
Oops, something went wrong.