Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
C++ Programming for Linux Systems

You're reading from  C++ Programming for Linux Systems

Product type Book
Published in Sep 2023
Publisher Packt
ISBN-13 9781805129004
Pages 288 pages
Edition 1st Edition
Languages
Authors (2):
Desislav Andreev Desislav Andreev
Profile icon Desislav Andreev
Stanimir Lukanov Stanimir Lukanov
Profile icon Stanimir Lukanov
View More author details

Table of Contents (15) Chapters

Preface 1. Part 1:Securing the Fundamentals
2. Chapter 1: Getting Started with Linux Systems and the POSIX Standard 3. Chapter 2: Learning More about Process Management 4. Chapter 3: Navigating through the Filesystems 5. Chapter 4: Diving Deep into the C++ Object 6. Chapter 5: Handling Errors with C++ 7. Part 2:Advanced Techniques for System Programming
8. Chapter 6: Concurrent System Programming with C++ 9. Chapter 7: Proceeding with Inter-Process Communication 10. Chapter 8: Using Clocks, Timers, and Signals in Linux 11. Chapter 9: Understanding the C++ Memory Model 12. Chapter 10: Using Coroutines in C++ for System Programming 13. Index 14. Other Books You May Enjoy

Using Coroutines in C++ for System Programming

We are almost at the end of our book. The final chapter is dedicated to a feature that is very useful for the purposes of system programming but is fairly new to the C++ standard. Coroutine objects found their application fast, becoming first-class state machine objects. Their power is in hiding logic behind the coroutine frame. Be advised that this is an advanced topic, and the coroutine interface of C++ is neither simple nor comfortable to use. It is well thought out but definitely not the most user-friendly in comparison to other programming languages.

In this chapter, you will learn the basics of using this facility. If you are new to it, then you’ll spend some time understanding its requirements. You’ll have an easier time with coroutines if you have previous experience with them in other programming languages. Still, we will use this chapter to propose their application in system programming.

We will present two...

Technical requirements

In order to run the code examples, you must prepare the following:

Introducing coroutines

At the end of your journey, we’d like to remind you about the knowledge you received in Chapter 1 and Chapter 2 about processes and threads. If you remember well, a process is simply a running instance of a program. It has its respective address space, which is not shared with others, except through shared memory. Threads reside in a process, and they cannot exist outside of them, although both processes and threads are treated as tasks in Linux. They are scheduled in the same manner and have the same controlling structures on the kernel level. Still, threads are considered lightweight because the bigger overhead for the initial load of a program is taken by the parent process.

But this is not the full picture. There are fibers and coroutines as well. If the processes and threads are truly concurrent and working in parallel over shared resources, fibers are just like threads but are not concurrency-compliant. While threads often depend on preemptive...

Network programming and coroutines in C++

In Chapter 7, you learned about the TCP and UDP communication protocols. We discussed their usefulness in network data transfer, but coroutines make them even more powerful. As mentioned, the code will behave in an asynchronous way, but we have control over the scheduling. Coroutines will be more efficient in context switching as they are executed on the user level. We’ll continue with the Generator definition to match the type of the coroutine, as discussed earlier. Traditionally, that object is made move-only – this allows us to restrict the usage of the coroutine wrapper, but in general cases, coroutine objects are non-copyable and non-moveable, because the coroutine frame is a part of them, and some local variables can be references or pointers to other local variables. Thus, let’s extend the structure accordingly:

Important note

This, again, is a very generic pattern that is used in almost every coroutine example...

Revisiting the shared memory problem through coroutines in C++

One of the issues we had with condition variables was synchronization during process startup. In other words, for the producer-consumer example, we didn’t know which threads were going to be first. We synchronized the code through a condition variable – its mutex, together with a predicate in order to handle the correct sequence of events. Otherwise, we would’ve risked losing information or ending in a deadlock. For a good portion of this book’s example preparations, we got to this situation, which made the writing experience even better. But coroutines provide another way of doing it, which could be more efficient at times and simpler to use (after you get used to the interface of coroutines as it is not the easiest to grasp).

The next example is motivated by the awaitable-awaiter pattern. It is similar to the condition variable, but it doesn’t use such synchronization primitives....

Final thoughts on coroutines and their implementations in C++

The examples earlier were practical, although not so simple. They were useful in understanding the sequence that a coroutine’s execution might take. It is good to visualize the state graph of coroutines, although we still believe it would be confusing for inexperienced developers.

As presented earlier, Figure 10.2, Figure 10.3, and Figure 10.4 pretty much cover what we’ve already explained through the code examples. It is useful to understand how much additional logic is generated around the coroutine and its members. Most of it happens in the background, and the system programmer only arranges the scheduling. In this chapter’s examples, we did this through the promise object and awaitables. The fact that the aforementioned figures partially represent a coroutine’s execution as a finite state machine should hint to you that this is another application where coroutines are useful. They transform...

Summary

With this, we’ve covered all the topics of this book. With the upcoming improvements of C++23, coroutines and their evolution will be analyzed more and more, especially in the system programming domain – and applied there, of course. Although complex to understand at first, coroutines allow you to continue sharpening the usage of C++ and give you one more instrument to enhance code.

In this chapter, you learned how to apply them in your concurrent applications, but their usefulness is far greater. We are excited about what comes next. We expect the modules language feature, which we didn’t cover in this book – intentionally – to be fully covered by the compilers and be broadly applied. Another interesting feature is std::generator – a view for the synchronous creation of coroutines in C++23. Stackful coroutines in C++26 are going to be a splendid system programming technique. In that version, you will also be able to obtain and visualize...

lock icon The rest of the chapter is locked
You have been reading a chapter from
C++ Programming for Linux Systems
Published in: Sep 2023 Publisher: Packt ISBN-13: 9781805129004
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}