C++ Generics / Templates

A while ago I discovered generics in Java. Today, I’m going to explore how to do the same with C++.

Generics in C++ are known as templates. We use the keyword template to tell the compiler that we are about to define one:

1
2
template <typename T>
class Hello {};

In the example above, you can also see that typename is used to define the type. You might also see the keyword class used interchangeably (There are some scenarios where they are not interchangeable, but I’m not going to cover those in this article):

1
2
template <class T>
class Hello {};
Read More

Using thread pools in C++

In previous articles, I explored how to write concurrent code using threads, how to communicate between threads using futures, async, packaged tasks and promises, how to avoid race conditions using mutexes, and other related topics. This article is going to go a little higher level and explore some things to consider when designing a concurrent system.

Why use concurrency?

Before I started working with C++, I used to write software in PHP, JavaScript, Ruby, etc. When I wrote software on those languages, I didn’t need to worry about concurrency, why do I need to worry now?

When I was writing web applications in PHP, I didn’t have to worry about threads or mutexes. I received a request, maybe got some data from a database, did some calculations and returned a result. Why can’t life continue to be that easy?

Read More

Building a simple server with C++

In this article, I’m going to explain how to create a very simple server with C++. The server will receive a single message, send a response and then quit. For network programming in C++, we need to use some low level C functions that translate directly to syscalls.

Let’s explore the syscalls we’ll need.

socket

We’ll use the socket function to create a socket. A socket can be seeen as a file descriptor that can be used for communication.

This is the signature of the function:

1
int socket(int domain, int type, int protocol);
Read More

C++ Atomic types

An operation on data is said to be atomic if it is impossible to find the operation half-way done. It’s very easy to see when an operation is not atomic when used in a struct:

1
2
3
4
5
6
7
8
9
10
11
struct Type {
  int a;
  int b;
}

Type data;

void fillType(int a, int b) {
  data.a = a;
  data.b = b;
}
Read More

Using Condition Variables in C++

In a previous article, I showed how to use mutexes to prevent race conditions. Condition Variables use mutexes to allow exclusive access to data, but also allow threads to wait for something to happen before they start to do work.

Understanding when Condition Variables are useful is easier with an example. Let’s say we are building a queue system. To keep it simple we will start with 1 producer and 1 consumer. We can make this system safe with a mutex:

Read More

Dependency management in C++ with Conan

I consider dependency management a very important part of a maintainable software project. Once you start writing software that depends on other code, it can quickly become unpractical to do dependency management by hand, so a good system is necessary to make it easy to work on such projects.

Since C++ has been out for a while, I expected to find a very mature ecosystem in this regard. Looking around and reading a little, I found that there is no community agreed way of solving the problem of managing dependencies. One reason for this seems to be that it’s not easy to build a system that helps you do dependency management when there are many ways to build a package.

Read More

Read-Write mutex with shared_mutex

A while ago I wrote an article about mutexes in C++. I explained how they solve the problem of race conditions by allowing only one thread to access data simultaneously.

A read-write mutex (also known: readers-writer, shared-exclusive, multiple-readers/single-writer, mrsw) is a specialization of a mutex that allows for greater performance in a scenario where reads are more frequent than writes.

Read More

Building a C++ project with CMake

Now that I know enough C++ to be able to build something useful, I started looking at tools that will make it possible to create maintainable projects. I’m exploring CMake because it is probably the most popular build tool for C++ projects. It allows you to create platform independent configuration files that can then be translated to the platform of your choice.

Installation

In Ubuntu, you can install CMake using apt-get:

1
sudo apt-get install cmake

For other systems, you can download the binary from CMake’s downloads page.

Read More

Building and using a library in C++

In a previous article I wrote an article explaining how header files work in C++. Among other things, the article explains how you can split your code in multiple files and link them together to create a single executable. One of the advantages of doing this, is that it allows code to be better organized, by separating different responsibilites in different files.

In this article I want to go one step further and explain how to create a library that can be reused by multiple projects.

Read More

Using lsof to find who is using a file or socket

lsof stands for List Open Files. It can help us find which process is using a file at a given point in time. The reason lsof is so useful in Unix/Linux systems is that sockets and devices are treated the same way as files (Pretty much everything is considered a file in Unix/Linux).

Running lsof without any arguments will list all open files in the system. If you have a lot of processes working with a lot of files, prepare to wait. The output looks somethins like this:

1
2
3
4
5
6
7
$ sudo lsof
COMMAND     PID   TID            USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
systemd       1                  root  cwd       DIR              253,1      4096          2 /
systemd       1                  root  rtd       DIR              253,1      4096          2 /
systemd       1                  root  txt       REG              253,1   1577264    5374284 /lib/systemd/systemd
systemd       1                  root  mem       REG              253,1     18976    5375835 /lib/x86_64-linux-gnu/libuuid.so.1.3.0
...
Read More