Skip to content

Instantly share code, notes, and snippets.

@stormouse
Created July 29, 2021 08:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stormouse/af4bcc376e00b405934568350ae06130 to your computer and use it in GitHub Desktop.
Save stormouse/af4bcc376e00b405934568350ae06130 to your computer and use it in GitHub Desktop.
proxy-a-bit-less-messy-imo
struct EventHandler
{
virtual void handle(event_t ev) = 0;
virtual EventHandler* next() const = 0;
virtual void propagate(event_t ev) {
EventHandler* n = next();
if (n != nullptr)
n->handle(ev);
}
};
struct Channel : public EventHandler
{
int read() { /* unimportant */ }
int write() { /* unimportant */ }
void transferTo(const Channel& dstChannel) {
readBuffer()->copyTo(*dstChannel.writeBuffer());
readBuffer()->clear();
}
bool is_read_ready() const { return _fdState & READ_READY; }
bool is_read_active() const { return !readBuffer()->empty(); }
bool is_write_ready() const { return _fdState & WRITE_READY; }
bool is_write_active() const { return !writeBuffer()->empty(); }
virtual void handle(event_t ev) override {
if (IOEvent::is_read_ready(ev)) {
_fdState = _fdState | IOState::READ_READY;
} else {
_fdState = _fdState & ~IOState::READ_READY;
}
if (IOEvent::is_write_ready(ev)) {
_fdState = _fdState | IOState::WRITE_READY;
} else {
_fdState = _fdState & (~IOState::WRITE_READY);
}
propagate(ev);
}
virtual ~Channel() {
// close fd
}
private:
Buffer* readBuffer() { return _readBuf; }
Buffer* writeBuffer() { return _writeBuf; }
Buffer* _readBuf;
Buffer* _writeBuf;
IOState _fdState;
};
struct Pipe : public EventHandler {
std::unique_ptr<Channel> a;
std::unique_ptr<Channel> b;
Pipe(std::unique_ptr<Channel> a, std::unique_ptr<Channel> b)
: a(std::move(a)), b(std::move(b)) {}
virtual void handle(event_t ev) override {
if (IOEvent::is_failure(ev)) {
// TODO: destroy pipe
return;
}
if (a->is_read_ready()) {
a->read();
}
if (b->is_read_ready()) {
b->read();
}
if (a->is_read_active() && b->is_write_ready()) {
a->transferTo(b);
b->write();
}
if (b->is_read_active() && a->is_write_ready()) {
b->transferTo(a);
a->write();
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment