Nov 16, 2019 - Polymorphic allocators in C++17

A nice and underrated feature of C++ 17 is polymorphic allocators. As you may know most containers of the STL are defined by their contained type as well as their allocator type thanks to templates.
So when we write :

std::vector<int> arr;

We in fact have :

std::vector<int, std::allocator<int>> arr;

However this design comes with some problems, for example the assignement of containers of different allocator types :

std::vector<int> arr;
std::vector<int, custom_allocator<int>> other_arr;
arr = other_arr; // this do not compile since arr and other_arr are not of the same type

One way to handle this problem is to write an overload of ‘=’ operator for theses types, however that’s not a really viable solution because if you want to support other allocators, other containers and other operators that’s lead to a lot of code you’ll need to write (and I’m not even talking of copy/move construction problem). So if overloading is not a viable solution.
So how can we handle this problem properly ?

The answer is of course polymorphic allocators (I will shorten it to pma).
The purpose of pma is to give the same allocator type : std::pmr::polymorphic_allocator to all your containers with custom allocation policy and then at runtime give them different memory resources to give them different allocations strategies.
A memory resource is a class that will handle the memory allocation strategy asked by a pma. So when you create a container with a pma you may want provide a memory resource to control allocation strategy. (If you do not provide one the STL will use a default one, which can be queried and modified with get_default_resource and set_default_resource).

You can create your own memory resources by inheriting from std::pmr::memory_resource, but for the example we will use some predefined memory resources of the STL.

So with pma we can write :

std::pmr::monotonic_buffer_resource monotonic_res;
std::pmr::unsynchronized_pool_resource pool_res;

// arr and arr2 are of the same type but will allocate with different strategies because they are created with different memory_resource
std::vector<int, std::pmr::polymorphic_allocator<int>> arr(&monotonic_res);
std::vector<int, std::pmr::polymorphic_allocator<int>> arr2(&pool_res);

arr = arr2; // this is ok since arr and arr2 are of the same type

A monotonic_buffer_resource is a memory resource that allow very fast allocation but can only release it’s memory all at once, and a synchronized_pool_resource is a thread safe collection of pools. I will not dig deeper than that on allocation strategies since it’s not the topic here, but I may write an article on it later.

You may already noticed it but another cool thing about pma is that since the allocation strategy depend now on the memory resource rather than the allocator type, we can decide at runtime of the allocation strategy rather at compile time. So we can do some stuff like this :

std::unique_ptr<std::pmr::memory_resource> mem_res;

if (some_condition())
	mem_res = std::make_unique<std::pmr::monotonic_buffer_resource>();
else
	mem_res = std::make_unique<std::pmr::synchronized_pool_resource>();

// this is the same as std::vector<int, std::pmr::polymorphic_allocator<int>>
std::pmr::vector<int> arr(mem_res.get());

/* so now the memory resource of arr (so the allocation strategy) is either monotonic_buffer_resource or synchronized_pool_resource
depending of the value returned by some_condition() */

And that’s it, if you wnat to go deeper with polymorphic allocators and memory resources I encourage you to read the STL documentation on it.

Aug 24, 2019 - Range based for loop on user defined types

A great and very appreciated C++11 feature is Range based for loop which allow us to write loops with a cleaner syntax than before.

For example this code in C++03 :

int array[] = {0, 1, 2, 3, 4, 5};
for (int i = 0; i < arraySize; i++)
    std::cout << array[i] << " ";

Can be converted in this in C++11 :

int array[] = {0, 1, 2, 3, 4, 5};
for (auto it : array)
    std::cout << it << " ";

In this case the syntax modification is not huge but It’s more intersting with more complex data structures like std::vector.

C++03 version :

std::vector<int> array(6);
for (int i = 0; i < array.size(); i++)
    array[i] = i;
    
for (std::vector<int>::iterator it = array.begin(); it != array.end(); ++it)
{
    std::cout << *it << " ";
}

C++11 version :

std::vector array = {0, 1, 2, 3, 4, 5};
for (auto it : array)
{
    std::cout << it << " ";
}

With always the same output :

0 1 2 3 4 5 
Read more ...

Aug 19, 2019 - My first blog post !


Hey there welcome on my blog.

If you don’t know what this blog is about, I invite you to read the about section.

So What’s going on here ?

We will talk mostly about gamedev and C++ programming, but maybe other langages too (I think there will be some articles on D, and later maybe rust and Jai).

What kind of articles will we see ?

A little bit of everything, tutorials, thoughts, presentations, news and certainly some random stuff.