5

pmem.io: C++ bindings for libpmemobj (part 2) - persistent smart pointer

 3 years ago
source link: https://pmem.io/2016/01/12/cpp-03.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

C++ bindings for libpmemobj (part 2) - persistent smart pointer

In our C API the programmer has to deal with custom pointers represented by the PMEMoid structure. Thanks to some macro magic we made it so that those PMEMoids are somewhat usable. C++ allows us to evolve this concept.

pmem::obj::persistent_ptr

Almost everyone who ever touched a C++ code knows the idea behind smart pointers (for example, std::shared_ptr). Our persistent pointer works in the same way. It wraps around a type and provides implementation of operator*, operator-> and operator[].

A constructor from raw PMEMoid is provided, so that mixing the C API with C++ is possible.

As always, we are going to start with an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <libpmemobj/p.hpp>
#include <libpmemobj/persistent_ptr.hpp>

using namespace pmem::obj;

struct rectangle {
	p<int> a;
	p<int> b;
};

struct root {
	persistent_ptr<rectangle> rect;
};

It’s a modified rectangle example from transactional allocations tutorial. Layout declaration using macros is no longer required :)

As I previously said, the persistent pointers can be constructed from PMEMoids, and as such, we are going to allocate the rectangle by using the regular C API.

1
2
3
4
5
6
7
8
9
persistent_ptr<root> rootp = pmemobj_root(pop, sizeof (root));

TX_BEGIN(pop) {
	persistent_ptr<rectangle> rect = pmemobj_tx_alloc(sizeof (rectangle), 0);
	rect->x = 5;
	rect->y = 10;

	rootp->rect = rect; /* assignments are automatically added to TX */
} TX_END

As you can see, pretty easy. No more ugly D_RW or D_RO macros ! :)

There’s one thing to highlight here: The rectangle constructor is NOT called in this example. This is because we are using C allocation function. This is equivalent to a following construct in a regular C++:

1
shared_ptr<rectangle> rect((rectangle *)malloc(sizeof (rectangle)));

To free a persistent_ptr using the C API, a special raw() function is available that returns a const reference to the PMEMoid.

1
2
3
4
TX_BEGIN(pop) {
	pmemobj_tx_free(rootp->rect.raw());
	rootp->rect = nullptr;
} TX_END

Later tutorials will introduce proper allocator functions that do call the constructor and destructors accordingly.

The persistent_ptr class also implements a raw_ptr() function which returns a pointer to the PMEMoid - this enables usage of the C failsafe atomic API.

Right now the persistent_ptr class can only be used with non-polymorphic and trivially default constructible classes. Those limitations might be relaxed in later versions of the bindings.

[This entry was edited on 2017-12-11 to reflect the name change from NVML to PMDK.]


The contents of this web site and the associated GitHub repositories are BSD-licensed open source.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK