Reader small image

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

Product typeBook
Published inSep 2023
Reading LevelIntermediate
PublisherPackt
ISBN-139781805129004
Edition1st Edition
Languages
Right arrow
Authors (2):
Desislav Andreev
Desislav Andreev
author image
Desislav Andreev

Desislav Andreev is a software engineer with a PhD in artificial intelligence systems and quantum machine learning. He has several publications in software engineering and AI applications. For his 10 years in the field he has a demonstrated history of working in automotive software engineering and in the area of the higher education. He is skilled in system and software architectures, operating systems, C and C++ development, autonomous driving and computer graphics. He is currently working as a Lead C++ Developer in VMware, developing its core software functionalities. He is also a lecturer at the Technical University of Sofia. He was previously a Technical Professional and software architect in the CRE and ADAS departments of Visteon Corporation, working closely with both OEMs and development teams.
Read more about Desislav Andreev

Stanimir Lukanov
Stanimir Lukanov
author image
Stanimir Lukanov

Stanimir Lukanov is a C++ expert, software tech lead and architect at VMWare. He has more than 15 years of professional experience in writing efficient and robust C++ enterprise code. Stanimir is a member of the Bulgarian National Body which is part of The C++ Standards Committee (JTC1/SC22/WG21). His interests are in the area of software security for distributed enterprise software systems. Since 2017 he has worked at VMWare where he currently leads a team which develops core security functionality in one of the major products in the company's portfolio. Before joining VMWare he held the position of senior software engineer at Visteon Corporation and Johnson Controls. He was responsible for defining software architecture, making code reviews, leading C++ training and delivering fast and robust C++ code for real-time automotive embedded systems.
Read more about Stanimir Lukanov

View More author details
Right arrow

Understanding the C++ Memory Model

This chapter is a continuation of the discussion from Chapter 7, where we discussed a few multiprocess and multi-threaded techniques; this chapter will enhance their usage. We will guide you through various techniques while narrowing down to the main focus of the chapter – the C++ memory model. But in order to discuss this, you will start first with a brief examination of memory robustness through the smart pointer and the optional objects. We will use them later to implement lazy initialization and handle shared memory regions safely. An improved memory access analysis of cache-friendly code follows. You will learn when and why using multi-threaded execution could be a trap, even though you did everything right in the software design.

This chapter gives you the opportunity to broaden your understanding of the synchronization primitives. While learning about the condition variables, you will also understand the benefits of the read-write...

Technical requirements

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

Getting to know smart pointers and optionals in C++

In Chapter 4, we revisited the C++ fundamentals in order to be on the same page when it comes to the language. One instrument that is also considered a must is smart pointers. Through these, we are able to improve the safety of the program and also manage our resources more effectively. And as discussed in the earlier chapters, this is one of our main goals as system programmers. Remember the RAII principle? Smart pointers are based on this, helping the C++ developer reduce and even eliminate memory leaks. They could also help with shared memory management as you will see later in the chapter.

Memory leaks appear when we allocate memory but fail to free it. This could happen not only because we forgot to call the object’s destructor, but also when we lose the pointer to that memory address. In addition to these, there are also the wild and dangling pointers to consider as well. The first one happens when the pointer is there...

Learning about condition variables, read-write locks, and ranges in C++

Let’s now start our discussion of synchronization primitives, a fundamental one of which is the condition variable. Its purpose is to allow multiple threads to remain blocked until an event occurs (i.e., a condition is satisfied). The implementation of condition variables requires an additional Boolean variable to indicate whether the condition is met or not, a mutex to serialize the access to the Boolean variable, and the condition variable itself.

POSIX provides an interface for multiple use cases. Do you remember the producer-consumer example in Chapter 7, Using Shared Memory? So, pthread_cond_timedwait() is used to block a thread for a given period of time. Or simply wait for a condition through pthread_cond_wait () and signal with pthread_cond_signal() to one thread, or pthread_cond_broadcast() to all threads. Typically, the condition is checked periodically in the scope of a mutex lock:

...
pthread_cond_t...

Discussing multiprocessor systems – cache locality and cache friendliness in C++

You probably recall Chapter 2 at this point, where we discussed multi-thread and multi-core processors. The respective computational units were presented as processors. We also visualized the transport of instructions from the NVM (the disk) to the processors, through which we explained the creation of processes and software threads.

We want our code to be as performant as required. The most important aspect of getting the code to perform well is the choice of appropriate algorithms and data structures. With a bit of thought, you can try to squeeze the most out of every last CPU cycle. One of the most common examples of misusing algorithms is sorting a large, unordered array with bubble sort. So, make sure to learn your algorithms and data structures – together with the knowledge from this section and beyond, it will make you a really powerful developer.

As you already know, the further...

Revisiting shared resources through the C++ memory model via spinlock implementation

We learned about atomic operations back in Chapter 7. In this chapter, you learned that the placement of atomic variables in the cache is crucial as well. Originally, atomics and locks were introduced because of correctness when multiple threads want to enter the same critical section. Now, our investigation will continue a bit deeper. There’s one last piece of the puzzle of atomic operations. Examine the following snippet:

Thread 1: shrd_res++; T1: load value
                      T1: add 1
Thread 2: shrd_res++; T2: load value
                      T2: add 1
                   ...

Summary

In this chapter, we’ve gathered together the entire set of instruments required for optimal code performance with C++. You learned techniques on many different system and software levels, so it’s understandable if you want to take a breather now. It is true that it would be good to spend more time on some of what we covered, for example, branch predictions and cache friendliness, or to implement more algorithms through condition variables and memory order. We strongly encourage you to use this chapter as a step in the direction of system improvements and more efficient work.

The next chapter is dedicated to one more significant improvement in C++’s features – coroutines. You will see that they are much lighter and, for some of the mechanisms discussed here, such as event waiting, they are much more preferable.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
C++ Programming for Linux Systems
Published in: Sep 2023Publisher: PacktISBN-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.
undefined
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

Authors (2)

author image
Desislav Andreev

Desislav Andreev is a software engineer with a PhD in artificial intelligence systems and quantum machine learning. He has several publications in software engineering and AI applications. For his 10 years in the field he has a demonstrated history of working in automotive software engineering and in the area of the higher education. He is skilled in system and software architectures, operating systems, C and C++ development, autonomous driving and computer graphics. He is currently working as a Lead C++ Developer in VMware, developing its core software functionalities. He is also a lecturer at the Technical University of Sofia. He was previously a Technical Professional and software architect in the CRE and ADAS departments of Visteon Corporation, working closely with both OEMs and development teams.
Read more about Desislav Andreev

author image
Stanimir Lukanov

Stanimir Lukanov is a C++ expert, software tech lead and architect at VMWare. He has more than 15 years of professional experience in writing efficient and robust C++ enterprise code. Stanimir is a member of the Bulgarian National Body which is part of The C++ Standards Committee (JTC1/SC22/WG21). His interests are in the area of software security for distributed enterprise software systems. Since 2017 he has worked at VMWare where he currently leads a team which develops core security functionality in one of the major products in the company's portfolio. Before joining VMWare he held the position of senior software engineer at Visteon Corporation and Johnson Controls. He was responsible for defining software architecture, making code reviews, leading C++ training and delivering fast and robust C++ code for real-time automotive embedded systems.
Read more about Stanimir Lukanov