I’ve been looking very eagerly at libuv as a basis for cross-platform asynchronous work handling. It provides logic to work with networks, files and even libraries. So I figured that something like this would be dope for Wintermute1. I read the contents of the libuv book and felt that I still didn’t know enough to get what I had in mind into code. So I decided to hammer out some code into Wintermute itself; makes it easier to share progress and get some common ideas out of the way.
What I wanted from libuv, or rather what I wanted to build using libuv was
something that allowed me to send out an event request for a named action and
have something that listened for said requests and handled that work. It was
very similar to how Qt handled events but after a bit of digging, I figured
that something like
EventEmitter for node. Fortunately, I stumbled upon
a repository that attempts this in C. Only a few qualms about
this is that it’s all in C so dropping that straight into a C++ (let alone a
C++11 project) wasn’t going to be that easy2. AND it’s one of the header-only
libraries . Using the
uv-emitter looks amazingly
straightforward, but I wasn’t sure how this would work in Wintermute now.
A few cups of tea and a comic book later, I came up with the following on how the event loops in Wintermute would look:
I noticed that sending messages was ample times more easier than actually receiving them. What kept tripping me up was how would the system know when to fetch messages from receivers. What I had to accept as given things was that the event loop would be always running in anticipation of a read request from the socket.
At this point, I realized that Wintermute sorely needed a event loop. I had to rethink a few things, specifically how the public facing part of Wintermute would interact with the rest of the system. Also, I had to realize that there’s a good chance that I would be implementing an accompanying binary for Wintermute to allow for quick introspection into the system. Looks like Wintermute’s going to have a fat singleton like the good ol’ days.
Building the Event Loop
Cracking some knuckles and running my hand through my hair, I began to write
out the C++11-ish version of
uvemitter into Wintermute. The issue with
uv-emitter that I had is constant breaking of Wintermute’s linting and how
it wasn’t designed to be C++ friendly. That seemed unfortunate but I’ve taken
it as a chance to get deeper into
Wintermute::Events namespace serves as the basis for all
event-related logic in Wintermute. A snippet of it without comments is
With the above, it was easy to do the following:
Of which, would do the following expectedly:
This is all fine and dandy for sending messages in Wintermute, since we can just do the following now (using Wintermute-style code):
But this brought me back to my original problem; not being able to listen and wait for messages from receivers. It hit me over (yet another) cup of tea: receiving messages would be similar to reading a infinite stream. For now, I figure that using a polling system would work best; having it query each receiver in a separate thread every 10 seconds for a new message. After doing a bit of digging into ZeroMQ sockets, I found this option to fetch the file descriptor used by sockets. This was an excellent find since now, I could use the polling functionality of libuv. Using this in the code now with Wintermute’s wrapper looks like this (sample follows):
With this now, I can just add a listener for the emission of this poller and
wham! Incoming messages using libuv’s event loop ! That’s all I really
wanted from using libuv. Now I can do all sorts of crazy stuff later on. I
notice that this code might be useful outside of Wintermute and I’m debating
extracting (and cleaning it up) for using as perhaps a
something of that nature. I can see this happening after the 0.1 release of
Wintermute but for now, this’ll do.