scclib
Stable Cloud Computing C++ Library
Files | Classes
Signaling kernel event counter

A wrapper for Linux eventfd. More...

Collaboration diagram for Signaling kernel event counter:

Files

file  event.h
 Signaling kernel event counter.
 
file  event.cc
 Signaling kernel event counter implementation
 
file  filedesc.cc
 File descriptor implementation
 
file  event.cc
 Tests for Signaling kernel event counter.
 

Classes

class  scc::util::Event
 Signaling kernel event counter. More...
 

Detailed Description

A wrapper for Linux eventfd.

Provides a signallable event counter, which is readable and writable across process boundaries.

See https://man7.org/linux/man-pages/man2/eventfd.2.html

Test examples from scclib/util/unittest/event.cc

Blocking event:

Event ev;
ev.write(1);
ev.write(2);
ASSERT_EQ(ev.read(), 3);

Non-blocking event:

Event ev(Event::nonblocking);
ev.write(1);
ev.write(2);
ASSERT_EQ(ev.read(), 3);
ASSERT_THROW(ev.read(), std::system_error);
ASSERT_EQ(errno, EAGAIN); // most recent system error was EAGAIN "unavailable"
@ nonblocking
Non-blocking mode. If an event is read while unsignalled, throws and exception.
Definition: event.h:88

Non-blocking semaphore event:

ASSERT_THROW(ev.read(), std::system_error);
ev.write(1);
ev.write(2);
ASSERT_EQ(ev.read(), 1);
ASSERT_EQ(ev.read(), 1);
ASSERT_EQ(ev.read(), 1);
@ semaphore
Semaphore mode. Event reads decrement the counter by 1. Otherwise, reads set the counter to 0.
Definition: event.h:89

Example from scclib/net/unittest/inet.cc using a Poller to wait for Event

TEST(inet_example, client_server_stream_test)
{
Logger log;
log.add_cout();
log.id("tcp client");
// this test sets up a client and server & streams some data between them
addr.host("::1"); // localhost
addr.port(9999);
// listening event
scc::util::Event listening;
std::packaged_task<int(void)> serv_task([&addr, &listening]()
{
Logger log;
log.add_cout();
log.id("tcp server");
try
{
sock.reuse_addr(true);
sock.bind(addr);
log << "server listening" << endl;
sock.listen();
// can play around with timeouts and timing this way...
//log << "sleep for a second" << endl;
//std::this_thread::sleep_for(std::chrono::seconds(1));
log << "signalling client" << endl;
listening.write(1);
auto conn = sock.accept(from);
log << "connection from " << from << endl;
scc::util::IoStream stream(conn, conn);
int count = 0;
for (string got; std::getline(stream, got);) // loop until eof (socket closed)
{
log << "got " << got << endl;
count += got.size();
stream << got << endl;
}
return count;
}
catch (exception& ex)
{
log << ex.what() << endl;
listening.write(1);
return -1;
}
});
auto fut = serv_task.get_future();
std::thread serv(std::move(serv_task)); // start server thread
Poller pin;
pin.set(listening, Poller::input);
while (1)
{
pin.wait(std::chrono::milliseconds(700));
if (pin.event(listening))
{
break;
}
log << "waiting for listener" << endl;
}
listening.read();
// use a non-blocking approach to add a timeout to the connect
sock.non_blocking(true);
error_code ec;
sock.connect(addr, ec);
if (ec.value() != 0 && ec.value() != EINPROGRESS)
{
log << "Non blocking connect failed: " << ec.message() << endl;
ASSERT_EQ(ec.value(), 0);
}
log << "waiting for 200 ms seconds to connect" << endl;
Poller pout;
pout.set(sock, Poller::output);
pout.wait(std::chrono::milliseconds(200));
if (!pout.event(sock))
{
log << "connect attempt timed out" << endl;
ASSERT_EQ(pout.event(sock), 0);
}
sock.non_blocking(false);
sock.connect(addr); // connect will either throw immediately or connect
log << "connected, sending stuff" << endl;
string line1("first line");
string line2("second line");
scc::util::IoStream stream(sock, sock);
string got;
ASSERT_TRUE(stream << line1 << endl);
ASSERT_TRUE(getline(stream, got));
ASSERT_EQ(got, line1);
ASSERT_TRUE(stream << line2 << endl);
ASSERT_TRUE(getline(stream, got));
ASSERT_EQ(got, line2);
sock.close();
serv.join();
int res = fut.get();
log << "got result=" << res << endl;
ASSERT_EQ(res, line1.size()+line2.size());
}
Ipv6 internet address.
Definition: inet.h:120
unsigned port() const
Get the port.
Definition: inet.cc:159
virtual std::string host() const
Get host.
Definition: inet.cc:188
Internet transmission control protocol (tcp) socket.
Definition: inet.h:251
Signaling kernel event counter.
Definition: event.h:79
uint64_t read()
Read from (decrement) the event counter.
Definition: event.cc:82
void write(uint64_t)
Write to (increment) the event counter.
Definition: event.cc:94
Input/output stream wrapper for reader/writer.
Definition: iostream.h:157
@ output
File descriptor is available for write operations.
Definition: poller.h:78
@ input
File descriptor is available for read operations.
Definition: poller.h:77
TEST(inet_example, client_server_stream_test)
[Inet client server]
Definition: inet.cc:521