参考链接:
http://pmem.io/2016/01/12/cpp-01.html
有关之前 C 语言的 libpmemobj 库的目标是在不修改编译器的条件下实现持续性存储的所有功能,但是只能在低级软件和语言。
而 libpmemobj C++ 库是更高级的语言,减少错误并且具有更好的API。更多专注修改 structs 和 classes,而对函数共能只做简单修改。
C 语言的 API 中存在的错误就是在事务操作中必须跟踪持久性内存变量的修改。
以vector example 为例子
pmem::obj::p 这个类不增加存储开销,但能够形成与C语言版本相同的 vector 结构体。在事务的操作中不需要再使用pmemobj_tx_add_range 函数。原因是:如果代码变得很复杂的时候在使用pmemobj_tx_add_range 函数时就会造成很多错误从而导致持久性问题。
pmem::obj::persistent_ptr
使用 persistent_ptr 之后不再需要使用宏定义 layout 声明!!
这是原先的 layout 声明:
POBJ_LAYOUT_BEGIN(rect_calc);
POBJ_LAYOUT_ROOT(rect_calc, struct my_root);
POBJ_LAYOUT_TOID(rect_calc, struct rectangle);
POBJ_LAYOUT_END(rect_calc);
也不用再使用 D_RW 和 D_RO 宏可以直接使用 ”->”
persistent_ptr rootp = pmemobj_root(pop, sizeof (root));
TX_BEGIN(pop) {
persistent_ptr rect = pmemobj_tx_alloc(sizeof (rectangle), 0);
rect->x = 5;
rect->y = 10;
rootp->rect = rect; /* assignments are automatically added to TX */
} TX_END
其中 persistent_ptrrect = pmemobj_tx_alloc(sizeof (rectangle), 0); 没有调用 rectangle 的构造函数。做如下理解:
shared_ptr rect((rectangle *)malloc(sizeof (rectangle)));
注:
{
shared_ptr 用法参考如下链接:
https://www.cnblogs.com/diysoul/p/5930361.html
使用 C 语言 API中的 raw() 来释放 persistent_ptr 返回值的是 PMEMoid 的 const 型。
TX_BEGIN(pop) {
pmemobj_tx_free(rootp->rect.raw());
rootp->rect = nullptr;
} TX_END
persistent_ptr 类中也自带了一个 raw_ptr() 函数来返回一个指向 PMEMoid 的指针。
}
链表队列
pmem_queue::push()
Step 1
首先需要创建一个新对象,包含数据和指向下一个的指针 next。
由于这些变量的初始化的内存内容并不知道,所以需要用户来赋值
Step 2
将现有的 queue 尾指针 next 指向新创键的对象
Step3
我们需要跟新tail的指向,将他指向新 push 进来的对象的 next 上。如果 push 进来的对象是第一个,那么 head 和 tail 都需要更新。
pmem_queue::pop()
Step1
跟新队列结构的head指向head->next。现在被移除的对象就不会链接任何的队列了。
Step2
被移除的对象会被释放。如果队列中没有任何对象了,那么将 tail 指向 NULL。
C++ 方法实现
对象结构体:
struct pmem_entry {
persistent_ptr next;
p value;
};
根对象:
class pmem_queue {
private:
persistent_ptr head;
persistent_ptr tail;
};
使用 pmemobj_alloc()/pmemobj_free() 来代替 new/delete 会让 pmem_queue::push() 和 pmem_queue::pop() 函数具有非易失性。
例程实现如下