What is the difference between epoll and boost::asio::io_context? - c++

I know that epoll and io_context work asynchronously. So, can you tell me what is the difference between the two?
Are you using epoll inside asio::io_context?

POSIX gives us a suite of utilities useful for dispatching on events and watching for activity on file descriptors. One of those utilities is epoll().
Boost ASIO also gives us a suite of utilities useful for dispatching on events and watching for activity on file descriptors. io_context is what it sounds like: a "handle" of sorts to a context for some I/O operations. Through an io_context you can poll() for activity (among other things).
They are two different interfaces for (in this comparison) a largely similar task. Boost ASIO, however, is an abstraction. Whether it uses epoll() under the bonnet to implement its magic is not really something we need to or should concern ourselves with, but it's certainly possible that it does so on POSIX systems. On Windows systems it would likely delegate to something else that the OS provides.
One school of thought is that cross-platform abstractions are always helpful, so the Boost ASIO technologies are a good choice for networking. On the other hand, some people find the old POSIX utilities to be simpler and more familiar to other programmers reading their code (as long as their target platforms support them); they also do not require you to ship a dependency. As with anything, it is up to you to decide which is the most appropriate for your use case and audience.

Related

Comparing Boost.Asio, libunifex, liburing, and CppCoro

I am trying to understand asynchronous models in C++. I am investigating 4 libraries that purport to deal with asynchronous I/O:
liburing (C version, C++ version): provides an interface for io_uring. The C++ version uses coroutines.
libunifex: implements the C++ sender/receiver async programming model
Boost.Asio: library for asynchronous network and low-level I/O programming
CppCoro: provides a large set of general-purpose primitives for making use of coroutines
These libraries have an enormous amount of overlap.
Execution context and io_uring
The future of asynchronous I/O will likely use io_uring on Linux machines. liburing exists to provide an interface for io_uring with io_service. However, libunifex also provides io_uring_context. These both explicitly use io_uring but have usage similar to Boost.Asio's io_context and CppCoro's io_service.
Can liburing's io_service, libunifex's io_uring_context Boost.Asio's io_context, and CppCoro's io_service all be used together? If my code included all four of these libraries, would I have 1 execution context from each?
Functionality: opening files
This section contains an example of how CppCoro asynchronously opens a file. I believe this template class would be used in Boost.Asio for asynchronous file access. libunifex has an io_uring_text.cpp doc that includes asynchronous writes to files. Obviously liburing exists for asynchronously writing files.
Should I only use the io_uring specific libraries for file access?
Functionality: networking
Everyone knows that Boost.Asio provides networking functionality. CppCoro does too. The liburing GitHub includes an example echo server that uses low-level C code.
Linbunifex does not appear to include direct networking functionality. I presume it is meant to be combined with some other networking library. Would I combine it with one of the above three libraries to give an old library a sender-receiver interface? How would I do that?
Interface: coroutines
I'm guessing that coroutines are meant to be glue that allows these libraries to exist together. Boost.Asio is compatible with coroutines. liburing4cpp and libunifex have coroutine compatibility as a central feature. CppCoro, on the other hand, is essentially a coroutine library.
Does it at all make sense to talk about using coroutines as glue? Could I say "I will use library A to implement the async function and library B to handle the output of the async function"?
My Questions
Would you expect to see someone use all 4 of these libraries simultaneously? Are any of these libraries meant to be used on top of any of the others?
In cases where functionality overlaps, how do these libraries compare on performance? Is Boost.Asio falling behind new asynchronous models? Is Boost.Asio staying ahead by integrating the most recent asynchronous models? liburing4cpp included a low-level echo server that isn't much comparable to the modern interface of Boost.Asio. How do applications based on low-level io_uring usage compare to applications built using Boost.Asio?
I believe that senders/receivers in libunifex is primarily meant as an interface. Should I use it as an interface to other libraries, for example Boost.Asio?
Look at asio-grpc, I think they had almost all of your comparisons in examples

MPI or Asio for wide-area plugin-based message passing

I'm writing a distributed system wherein each node interfaces with local applications via some RESTful API, supports extensions and runtime customization, etc. It's a bit like an Enterprise Service Bus over the wide area, but with a lot else going on which is not related to the question at hand.
I've read a little about both MPI and Asio - originally I was set on Asio, but then I found MPI, and now again I'm thinking Asio is the better solution for me. MPI seems to provide a lot I don't need and a higher level of abstraction than I want - for example, I only need point-to-point communication, and it is important to me to be in control of when and what data is transmitted. (e.g. I have already designed a packet structure that I would conform to ideally)
So my primary question: it is worth it to start from a lower level with Asio, or should I try to graft MPI onto what i'm looking for? Further, are there 'skeleton applications' available which use MPI or Asio which would aid development? (Actually I am 100% new to C++.. ;) Or, does it make sense to use them in tandem?
For more perspective, maybe it's worth noting that I already have implemented the bulk of this project in Perl using Perl Object Environment, which itself is just an asynchronous event system with a ton of networking libraries.
Also, if it makes a difference, I would ideally use threads for this.
Honestly though I have not used Boost at all yet, as I hinted above, so any input is appreciated.
I should start by saying that I know nothing about Asio, but from the 2 minute scan of the website and the description of your problem, it sounds like while either would probably work for you, Asio might be simpler. MPI is really designed less for general purpose network communication and more for running applications where the set of processes and applications is a little more static. While it provides a client/server style interface if desired, it's not the main focus of the library.
MPI is also more difficult to use if you already have a packet structure designed. MPI is great for abstracting away the need to worry about packets, location of processes, etc. but if you've already taken all of that into account in you application, you have already done the hard work.
There have been at least one other discussion of Asio vs. MPI that you can take a look at (For distributed applications, which to use, ASIO vs. MPI?) to get more opinions too.

glib's GAsyncQueue equivalent for C++?

glib has a data structure called GAsyncQueue, which allows inter-thread communication with no semaphores/locks/etc., and even makes trivial the task of implementing a producer/consumer solution. If two different threads push data to a GAsyncQueue structure, the push function internally implements the mutually exclusive access to the queue; more awesomely, if a thread calls the pop function, and there is no data there, the calling thread blocks until some data is pushed into the queue by some other thread. All of this is done in a thread-safe manner, transparently to the developer.
As much as I like it, though, this library was built for C, and there might be better alternatives for higher level languages. I'm thinking about using glib anyway, but it feels odd to use a C library in a C++ code...
So, the question is: is there a C++ recommended equivalent for glib? More specifically, is there a more recommended C++ library that provides the same functionality as GAsyncQueue?
There is absolutely nothing wrong with using C in a C++ program (after all, C++ implementation is heavily based on C runtime, for example C++11 thread support cannot live without pthread library, at least on UNIX®-like platforms). I would definitely not choose the tool/library only and entirely basing on the language it is written in. But if you must use something else, then glib is not the only library in the world that provides provides asynchronous message passing (by the way, it doesn't really look like it supports IPC). Anyhow, here is a list of C++ frameworks that immediately come to my mind (in random order, as random as my thoughts):
Intel Threading Building Blocks
Boost MPI
Boost.ASIO
Qt
Each one has its own strengths and weaknesses, and which one to use really depends on what exactly your requirements are. I can only recommend you to pay attention to overall application architecture and how well the asynchronous message passing would fit into all of the components of your application. For example, in more or less complex applications that involve more than simple message passing, such asynchronous queues are oftentimes integrated with the event notification mechanisms in use (for example, OSX is built around kqueue/GCD).
Hope it helps. Good Luck!

Portable lightweight C++ sockets wrapper

I really thought this would be easier to find...
I need a portable c++ sockets wrapper. I'm planning to use it for a windows server application and a client that will be running on a embedded device running ulinux (or something similar). I would use Boost but I need it to be lightweight and easy to add to the embedded device project.
Also I would like it to be a "higher level" wrapper... so it starts a background thread to read data and informs be over a callback...
Any ideas?
I'd suggest Boost.Asio. Despite it's name, you are not forced to use asynchronous I/O. You could use synchronous I/O and threads, as your question implies.
Boost.Asio is a cross-platform C++
library for network and low-level I/O
programming that provides developers
with a consistent asynchronous model
using a modern C++ approach.
Just learn to use the socket API directly. You can then easily wrap it yourself. It's not that hard, and you can get started with Beej's excellent guide. As Beej says:
The sockets API, though started by the
Berkeley folk, has been ported to many
many platforms, including Unix, Linux,
and even Windows.
In his guide he details the very small addition you need to do to get the same API in Windows and *nix systems.
Once you've learned, wrap it yourself if you're so inclined. Then you can control exactly how "lightweight" you want it.
If you really don't like Boost asio then you might like the sockets support in dlib. It is simpler in the sense that it uses traditional blocking IO and threads rather than asio's asynchronous proactor pattern. For example, it makes it easy to make a threaded TCP server that reads and writes from the iostreams. See this example for instance. Or you can just make a simple iosockstream if not acting as a server.
I know this is old, but there is a very nice and simple implementation in below location which I'm using for personal use. Had implemented my own wrapper a while back but lost the code and found this one online which is much better than mine:
http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/
Take a look at ENet http://enet.bespin.org/ it is very lightweight and portable and works on top of UDP, with optional support for reliable packets. It is easy to use, the API is low-level and with little performance overhead. You have a high degree of control over the memory management, which could be good if networking is a bottleneck for you and the malloc/new implementation you use performs badly under multithreading.
It would not be that hard to implement your high level thread “optimally”, since there is optional support for blocking receive and the library is a “library” and not a framework therefore you are the decision maker instead of the library.
Perhaps you can have a look at http://www.pt-framework.org/
Old question, but for C++, BSD style synchronous sockets this is about as minimal baggage wrapper as you can find
http://code.google.com/p/ting/source/browse/trunk/src/ting/net/
It does come with exceptions. You could make a bit more lightweight one as a header-only template library, and maybe make exceptions optional, but that would change the API a bit
POCO network classes are quite similar, but do require more dependencies from other parts of the Poco lib
I'm personally creating my own AsIO wrapper for both TCP and Serial sockets, and I started by reviewing the following tutorial:
https://www.gamedev.net/blogs/blog/950-they-dont-teach-this-stuff-in-school/
and
https://objectcomputing.com/resources/publications/mnb/multi-platform-serial-interfacing-using-boost-a-gps-sensor-and-opendds-part-i/
I found the first one very useful and simple to understand.
C++CSP2
Used it loved it. Stable and powerful

Where to begin with multi-threaded programming with c++?

I'm trying to implement my own IRC client as a personal proejct and I realized I needed a way to read and write from the socket at the same time. I realized I could have a reading thread which reads from the socket in the background and puts data in a queue and I could have another thread which writes data from a queue to the socket. However I have no idea on how to start with multithreaded programing or how to do it with c++. Where do I go from here?
For C++ threads, boost::thread (which is the basis for the upcoming std::thread) is the best way to go. That said, while threads might be the correct solution for your particular case, I just wanted to throw it out there that select and non-blocking sockets are a common approach to interleaving the reading/writing and writing of multiple sockets without the need for threads. The boost::asio library wraps the functionality of select and non-blocking sockets in a cross-platform, C++ manner.
It's specific to C and *nix, but I can't think of a better starting place than Beej's Guide to Network Programming. "You will learn from the Jedi Master who instructed me."
You'll learn the basics of reading and writing to sockets, and more importantly, that multi-threading isn't necessarily the right answer.
I would suggest using Qt Threading. It is highly documented with really excellent sample code on almost every feature. Plus they are LGPL licensed now and will run on most every platform and include the source code with the binaries. They also have very good network supoort.
Whatever way you choose, make sure that they have good documentation and samples
I'd suggest looking at the POCO libraries. In my opinion they are easier to get on with than boost and have excellent documentation. These libs provide great frameworks for writing multithreaded networking code. You can learn a lot from them and get up and running pretty quickly.
I suggest ACE. It has portable abstractions for many operating system functions (*nix, Windows etc): BSD sockets, Threads, Mutexes, Semaphores etc - write once compile anywhere (See ACE_OS namespace of ACE).
It has a lot of network application patterns you can use (ACE_Reactor would be good for the beginning) but you can use the portable abstractions of the BSD functions (socket, send, recv, close, select - they are enough for your IRC client)
As previously mentioned boost is also an option and usually any cross-platform library providing portable abstractions for each operating system (I can think of wxWidgets, qt for the graphical part - if you want to do this).
And one advice: do not use threads unless you really need to. They are not as easy as it seems.
When referring to the network communication I believe that what you want to do is easily achievable in a single threaded application(ACE_Reactor helps you a lot here but you are free to use the BSD socket functions). First understand how sockets work, then - if you want to - understand how the reactor makes use of sockets in its network application patterns(ACE_Reactor works in conjuction with ACE_Event_Handler objects).
Hope it helps!