Articles & Books

SObjectizer Tales – 2. Can you call me back?--Marco Arena

A new episode of the series about SObjectizer and message passing:

SObjectizer Tales – 2. Can you call me back

by Marco Arena

From the article:

A camera vendor has just released a new SDK that works through callbacks. Basically, the user sets a function that will get called by the SDK on every new available frame. How can we integrate this into a producer agent?

How to Use Monadic Operations for `std::optional` in C++23 -- Bartlomiej Filipek

monadic_optional.pngIn this post we’ll have a look at new operations added to std::optional in C++23. These operations, inspired by functional programming concepts, offer a more concise and expressive way to work with optional values, reducing boilerplate and improving code readability.

How to Use Monadic Operations for `std::optional` in C++23

By Bartlomiej Filipek

From the article:

Let’s meet and_then()transform() and or_else(), new member functions.

Traditional Approach with if/else and optional C++20  

In C++20 when you work with std::optional you have to rely heavily on conditional checks to ensure safe access to the contained values. This often led to nested if/else code blocks, which could make the code verbose and harder to follow.

Consider the task of fetching a user profile. The profile might be available in a cache, or it might need to be fetched from a server. Once retrieved, we want to extract the user’s age and then calculate their age for the next year. 

Phantom and Indulgent Shared Pointers -- Raymond Chen

RaymondChen_5in-150x150.jpgIn our exploration of shared_ptr variations, we've previously covered cases where the stored pointer was either empty or pointed to a managed object. Now, we delve into the intriguing cases of phantom shared pointers, where the stored pointer is null but secretly manages an object, and indulgent shared pointers, which point to something but own nothing, offering unique utility for scenarios like static storage duration, with methods like use_count() and get() aiding in their detection.

Phantom and Indulgent Shared Pointers

By Raymond Chen

From the article:

Last time, we looked at various ways to convert among different shared_ptrs. We finished with this diagram:

2023-10-02_14-15-23.png

 

 

 

You are familiar with an empty shared pointer, which manages no object and has no stored pointer. You are also familiar with a full shared pointer, which manages an object and has a non-null stored pointer (to the managed object, or something whose lifetime is controlled by the managed object). But what about those other two guys?

In the upper right corner, you have the case of a shared pointer that manages an object but whose stored pointer is null, which I’ve called a phantom shared pointer. If you convert the shared pointer to a bool, it produces false, because you can’t use it to access anything. The phantom shared pointer looks empty at a casual glance, but it secretly manages an object behind the scenes. That secretly-managed object remains alive for no visible reason. There is no way to access that secretly-managed object, but it’s still there. It’s a phantom which follows you around.

SObjectizer Tales - 1. Producing Images--Marco Arena

A new episode of the series about SObjectizer and message passing:

SObjectizer Tales - 1. Producing Images

by Marco Arena

From the article:

Since using any real camera drivers is out of scope, we’ll use OpenCV to open our default camera (e.g. the webcam) and grab frames one by one. In case you don’t have any available camera on your machine, we’ll provide a simple “virtual producer” that replays some images from a directory...

What it means when you convert between different shared_ptrs -- Raymond Chen

RaymondChen_5in-150x150.jpgIn C++, the shared_ptr is commonly used to manage reference-counted pointers, typically pointing to objects that get deleted when the last reference expires. However, it's possible to create shared_ptr instances where the managed object and the stored pointer are different, enabling scenarios like accessing sub-objects or creating aliasing shared pointers. This article explores various ways to achieve this, including type conversions and special helper functions like static_pointer_cast, const_pointer_cast, reinterpret_pointer_cast, and dynamic_pointer_cast, shedding light on some nuances in the process.

What it means when you convert between different shared_ptrs

By Raymond Chen

From the article:

The C++ shared_ptr manages a reference-counted pointer. Usually, it’s a pointer to an object that will be delete‘d when the last reference expires. But it doesn’t have to be that way.

Recall that a shared_ptr is really two pointers.

  • A pointer to a control block which manages the shared and weak reference counts, and which destroys an object (commonly known as the managed object) when the shared reference count drops to zero.
  • A pointer to return from the get() method, commonly know as the stored pointer.

Most of the time, the stored pointer points to the managed object, because that what you get when you construct a shared_ptrs from a raw pointer or when you call make_shared. But what is the use case for a shared_ptr where the managed object and the stored pointer are different?

 

Inside STL: The shared_ptr constructor and enable_shared_from_this -- Raymond Chen

RaymondChen_5in-150x150.jpgIn C++, when you create a class that derives from std::enable_shared_from_this, it becomes eligible for special treatment by shared_ptr, allowing the shared_from_this() method to return a shared_ptr to the object. However, certain conditions and constraints must be met, and this functionality is enabled through a mechanism involving a secret weak pointer called weak_this.

Inside STL: The shared_ptr constructor and enable_shared_from_this

By Raymond Chen

From the article:

If you create a class of the form

struct S : std::enable_shared_from_this<S>
{
    /* ... */
};

which derives from std::enable_shared_from_this of itself (using the curiously recurring template pattern), then this class becomes a candidate for special treatment by shared_ptr: The shared_from_this() method will produce a shared_ptr<S>. Some restrictions apply.

Inside STL: The shared_ptr constructor vs make_shared -- Raymond Chen

RaymondChen_5in-150x150.jpgThis article discusses the memory layouts when creating an object controlled by a shared_ptr in C++ through two methods: using a raw pointer and via the make_shared function. 

Inside STL: The shared_ptr constructor vs make_shared

By Raymond Chen

From the article:

There are two ways to create a new object that is controlled by a shared_ptr.

// From a raw pointer
auto p = std::shared_ptr<S>(new S());

// Via make_shared
auto p = std::make_shared<S>();

They result in two different memory layouts.

In the first case, you manually created a new S object, and then passed a pointer to it to the shared_ptr constructor. The shared_ptr adopts the raw pointer and creates a control block to monitor its lifetime. When the last shared pointer destructs, the Dispose() method deletes the pointer you passed in.¹ When the last shared or weak pointer destructs, the Delete() method deletes the control block.

SObjectizer Tales - Prelude--Marco Arena

A new blog series about SObjectizer and message passing:

SObjectizer Tales - Prelude

by Marco Arena

From the article:

Some time ago, I was looking for alternatives to Microsoft’s Asynchronous Agents Library. I developed a Windows application interfacing with industrial cameras and performing multiple tasks such as visualization and object recognition...

Inside STL: Smart Pointers -- Raymond Chen

RaymondChen_5in-150x150.jpgThe C++ standard library comes with a few smart pointer types. The simplest one is unique_ptr: This class babysits a raw pointer and remembers to delete it at destruction (in an appropriate manner). Dumping the contents of a unique_ptr is just looking at the raw pointer inside.

Inside STL: Smart Pointers

By Raymond Chen

From the article:

The C++ standard library comes with a few smart pointer types.

The simplest one is unique_ptr: This class babysits a raw pointer and remembers to delete it at destruction (in an appropriate manner). Dumping the contents of a unique_ptr is just looking at the raw pointer inside.

The complication is that there is also a deleter object in the unique_ptr. This deleter object is usually an empty class, so it is stored as part of a compressed pair.

The Visual Studio debugger has a visualizer that understands unique_ptr, but here’s what it looks like at a low level in the Microsoft implementation:

0:000< ?? p
class std::unique_ptr<S,std::default_delete<S> >
   +0x000 _Mypair          : std::_Compressed_pair<std::default_delete<S>,S *,1>
0:000< ?? p._Mypair
class std::_Compressed_pair<std::default_delete<S>,S *,1>
   +0x000 _Myval2          : 0x0000020a`11f08490 S
0:000< ?? p._Mypair._Myval2
struct S * 0x0000020a`11f08490 ← here is the unique object
   +0x000 a                : 0n42

Inside STL: The array -- Raymond Chen

RaymondChen_5in-150x150.jpgThe C++ standard library array is just a C-style array wrapped inside a class so that it behaves like a normal C++ object instead of a wacky thing that undergoes decay.

Inside STL: The array

By Raymond Chen

From the article:

template<typename T, size_t N>
class array
{
    T elements[N];
};

template<typename T>
class array<T, 0>
{
};

The only weird case is N = 0. You are allowed to create a zero-length std::array, but C++ does not allow zero-length C-style arrays. The zero-length std::array is just an empty class.

Visual Studio and the Windows debugger come with a visualizer:

0:000> dx a
a                : { size=5 } [Type: std::array<int,5>]
    [<Raw View>]     [Type: std::array<int,5>]
    [0]              : 3 [Type: int]
    [1]              : 1 [Type: int]
    [2]              : 4 [Type: int]
    [3]              : 1 [Type: int]
    [4]              : 5 [Type: int]