Mutexes in C++

Why use Mutexes?

Mutexes are a technique for concurrency management. They are called Mutex because of their MUTual EXclusion property (Only one thread can be doing work at a given time).

Mutexes are used to prevent race conditions on shared data between threads. Lets look at a stack backed by an array. At some point it could look like this:

If we want to insert a value on this stack we need to follow these steps:

1 – Get the index of the head

2 – Increment the index of the head by one

3 – Save a value in the head

If two threads need to insert a value into this stack at the same time, one of the inserted values could get lost:

Read More

IPv6

IPv6 has been an Internet Standard since July 2017. Although I had heard of it since far back, I never had to know much about it until now. In this post I’m going to explain what are some of the differences between IPv4 (The previous and most widely used standard) and IPv6.

Address space

Probably the most commonly known reason behind IPv6 is that we were going to run out of IPv4 addresses soon. An IPv4 address looks like this: 192.168.100.255. In binary it would look something like this: 11000000.10101000.1100100.11111111. That is 32 bits (2^32) which equals 4,294,967,296 values.

IPv6 addresses look a little different. They are represented by 8 groups of 4 hexadecimal digits separated by a colon. For example: 1234:5678:9abc:def1:f00d:1560:0d7a:c055. This is 2^128 different combinations which is a little more than 3*10^38. This is a very high number we’re probably not going to exhaust any time soon.

Because addresses can get very long, a few conventions have been made to make them shorter to write on paper. One of them is that leading zeros in a group can be omitted. For example:

1
2
1234:0abc:9abc:00f1:f00d:1560:0035:0001
1234:abc:9abc:f1:f00d:1560:35:1

The two addresses above are the same.

Read More

Passing by reference to a thread in C++

Today I discovered that there are some interesting behaviors when you use a function that takes a reference as an entry point for a thread.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <thread>

struct container {
  int numThings;
};

void setThings(container& cont)
{
  cont.numThings = 3;
}

int main()
{
  container c;
  std::thread t(setThings, c);

  t.join();

  std::cout << c.numThings;
}
Read More

Android development with Docker

A couple of years ago I wrote a post explaining how to develop and Android application inside a Docker container. After some time away from Android development I tried to follow the instructions in my post but they didn’t work quite well.

A lot has changed in the way Android applications are developed since my last post. Installing SDK elements is easier and Kotlin is the language of choice now. Luckily, once we put everything inside Docker, we don’t have to worry much about the environment and just code.

Create a folder for your project and add a Dockerfile inside that folder:

Read More

Getting familiar with Terraform

In a previous post I covered the basics of Terraform. In this post I’m going to cover a few more things that I find necessary in most infrastructures I create.

The machines

I’m going to start with a couple of machines:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Configure Google Cloud
provider "google" {
  credentials = "${file("credentials.json")}"
  project = "ncona-1504"
  version = "~> 1.13"
}

// Machines
resource "google_compute_instance" "us-central1-c--f1-micro--001" {
  name         = "us-central1-c--f1-micro--001"
  machine_type = "f1-micro"
  zone         = "us-central1-c"

  boot_disk {
    initialize_params {
      image = "ubuntu-1604-xenial-v20170815a"
    }
  }

  network_interface {
    network = "default"
  }
}

resource "google_compute_instance" "us-central1-c--f1-micro--002" {
  name         = "us-central1-c--f1-micro--002"
  machine_type = "f1-micro"
  zone         = "us-central1-c"

  boot_disk {
    initialize_params {
      image = "ubuntu-1604-xenial-v20170815a"
    }
  }

  network_interface {
    network = "default"
  }
}
Read More

Introduction to networking in Google Cloud

Google uses the concept of Virtual Private Cloud (VPC) to refer to their capability for creating your own private network withing their infrastructure. There are a few terms that will allow us to create a network of our design:

  • Network – This is a virtual (because everything is virtual in the cloud) network that can span across the globe
  • Subnet – This is an IP range that can be used by machines in a single region
  • Firewall – Used to limit communication between machines in the same network

Network

A network (or VPC) is just a name used to group your network infrastructure. Subnets are defined inside a network and each host is part of one subnet.

Subnets

Subnets can be defined by region. You can choose any IP range defined as private as specified in RFC-1918 (basically anything inside these ranges: 10.0.0.0 – 10.255.255.255, 172.16.0.0 – 172.31.255.255 and 192.168.0.0 – 192.168.255.255).

Read More

Setting the search directory for Ctrlp vim plugin

By default ctrlp will look for the root of your repo (by looking for a .git, .hg, .svn or .bzr file) and then start searching for files in that folder. For the project I’m currently working on that has too many files (Probably millions) I prefer that ctrlp only searches inside the folder were I started vim. This can be done with this setting in .vimrc:

1
let g:ctrlp_working_path_mode = 'a'
Read More

Taking over existing instances with Terraform

A few days ago, while playing with Terraform I realized that I want Terraform to manage some instances that I had already created in Google Cloud. Because these instances existed before I was using Terraform, it doesn’t konw anything about them.

The first thing I had to do to take over them, was to add them to the configuration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
resource "google_compute_instance" "us-central1-c--f1-micro--001" {
  name         = "us-central1-c--f1-micro--001"
  machine_type = "f1-micro"
  zone         = "us-central1-c"

  boot_disk {
    initialize_params {
      image = "ubuntu-1604-xenial-v20170815a"
    }
  }

  network_interface {
    network = "default"
  }
}

Once I had the machine in my configuration, I just had to tell Terraform, which machine is that:

1
terraform import google_compute_instance.us-central1-c--f1-micro--001 ncona-179804/us-central1-c/us-central1-c--f1-micro--001

From here terraform can manage it as if it had created it.

Read More

Terraform

Terraform is a tool for managing infrastructure. It works with most cloud providers out there, but it can also (although with considerably more work) integrate with any custom solutions a company might have.

Managing infrastructure

What does it mean to manage infrastructure? Although different infrastructure management systems have different features, there are a few features that are present in most systems:

  • Asset lifecycle – Adding or removing assets (machines, load balancers, switches, etc…)
  • Networking – Managing how the assets communicate (networks, routes, permissions, etc…)
  • Security – Secure the network and machines so it can only be accesses by the intended people
  • Updates – Update the system software when necessary for security or stability reasons

Why Terraform?

There are many tools out there that allow you to manage your infrastructure (Chef, Ansible, Salt, etc…). I have worked in companies that run successfully using Chef, Ansible and Salt, so I’m sure any of the tools can be made to work. I’m writing this post about Terraform because I heard good things about it from people I admire. Two things that usually come up are an easy way to manage your whole infrastructure using configuration files, as well as making optimal changes that can be applied quickly without affecting dependent services.

Read More

Linux page cache

Linux (and most other operating systems) provide a transparent layer of caching for auxiliary storage (hard drives, etc…). This layer allows fast access to frequently used files on disk by keeping their content in memory and reading from there when necessary.

The kernel can use any free space in RAM as page cache. If the system requires more memory, the kernel might free space used by this cache and provide it to the application that needs it.

Inspecting page cache

Page cache is stored in RAM, but the space can be reclaimed by the kernel for applications whenever necessary. In Linux we can see how many bytes of RAM are used for page cache:

1
2
3
4
~ $ free -h
              total        used        free      shared  buff/cache   available
Mem:            19G        5.4G        7.8G        1.5G        6.2G         12G
Swap:           19G          0B         19G
Read More