持久性内存编程——类型

2024-02-29 21:48
文章标签 类型 内存 编程 持久性

本文主要是介绍持久性内存编程——类型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在之前的所有关于持久化内存编程的文章中,代码片段和示例都有持久指针(pmemoid),没有任何类型信息——它们是简单的C结构。在pmem库开发的早期,开发者发现使用类似的东西非常容易出错,而且通常很困难。他们在用类型安全容器封装pmemoids时付出了相当大的努力,最终结果可以与C++11中的SydDypTr等进行比较,之后的所有内容将只使用类型安全特性。

目录

布局声明

类型化持久指针

PMEMoid和TOID操作

运行时类型安全

用例


布局声明

所有使用pmemobj的持久内存程序都应该有一个明确定义的内存布局,最好是在自己的文件中进行布局的定义。为了提供运行时和编译时类型的安全性,除了声明结构之外,还需要使用特殊的宏。例如,我们的字符串存储示例的布局如下所示:

POBJ_LAYOUT_BEGIN(string_store);
POBJ_LAYOUT_ROOT(string_store, struct my_root);
POBJ_LAYOUT_END(string_store);#define	MAX_BUF_LEN 10
struct my_root {char buf[MAX_BUF_LEN];
};

现在可以在代码中使用类型化的持久指针。此代码中的字符串存储只是一个名称,创建或打开具有特定布局的池时,建议使用pobj_layout_name宏,如下所示:

pmemobj_create(path, POBJ_LAYOUT_NAME(string_store), PMEMOBJ_MIN_POOL, 0666);
...
pmemobj_open(path, POBJ_LAYOUT_NAME(string_store));

如果你觉得所有这些都令人困惑,请先阅读这篇文章( this ),这对该内容有深入解释。

类型化持久指针

使用以下构造来代替pmemoids指针:

TOID(struct my_root) root;

要取消引用,不再需要将另一个变量与pmemobj_direct结合使用,首选的方法是使用d_rw进行写入,使用d_ro进行读取。如下所示:

if (D_RO(root)->buf[0] != 0)D_RW(root)->buf[0] = 0;

大多数IDE都会正确地评估这些宏,并自动完成类型代码。

PMEMoid和TOID操作

一般来说,有两种类型的安全宏可以区分:在原始pmemoid上操作的宏(前缀为OID_),在类型TOID上操作的宏(前缀为TOID_)。

所有pmemobj_函数只接受原始pmemoids作为参数。我们通常建议只使用宏,但如果需要将TOID“强制转换”为pmemoid,可以这样做:

TOID(struct foo) data;
pmemobj_direct(data.oid);

所有没有TOID_或OID_前缀的宏通常都采用类型化指针,并将其作为结果返回(如POBJ_ROOT宏)。

运行时类型安全

布局中的每种类型都在内部分配了一个唯一的编号,然后可以用于验证。

例如,对现有软件的更新可能改变了布局,如下所示:

struct my_root_v1 {TOID(struct foo) data;
}
struct my_root_v2 {TOID(struct bar) data;
}

要检查布局的版本是否与现有对象对应,可以使用以下表达式:

if (TOID_VALID(D_RO(root)->data)) {/* can use the data ptr safely */
} else {/* declared type doesn't match the object */
}

如果不确定对象类型,也可以依赖嵌入的类型号,如:

PMEMoid data;
TOID(struct foo) foo;
TOID(struct bar) bar;
if (OID_INSTANCEOF(data, struct foo)) {TOID_ASSIGN(foo, data);
} else if (OID_INSTANCEOF(data, struct bar)) {TOID_ASSIGN(bar, data);
} else {/* error */
}

与高级语言的相似性并非偶然。

用例

这是最后一次修改字符串存储示例。layout.h修改可以在上面看到。首先,从root对象开始。可以使用以下行,而不是首先使用pmemobj_root函数,然后使用pmemobj_direct作为实际指针:

TOID(struct my_root) root = POBJ_ROOT(pop, struct my_root);

还记得怎么保证代码会变短的吗?writer.c:

TX_BEGIN(pop) {TX_MEMCPY(D_RW(root)->buf, buf, strlen(buf));
} TX_END

因为不再有rootp了,这个也变得简单了,reader.c

printf("%s\n", D_RO(root)->buf);

完整代码:repository

原文来自:http://pmem.io/2015/06/16/types.html

这篇关于持久性内存编程——类型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/760200

相关文章

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

IDEA如何将String类型转json格式

《IDEA如何将String类型转json格式》在Java中,字符串字面量中的转义字符会被自动转换,但通过网络获取的字符串可能不会自动转换,为了解决IDEA无法识别JSON字符串的问题,可以在本地对字... 目录问题描述问题原因解决方案总结问题描述最近做项目需要使用Ai生成json,可生成String类型

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景

C# dynamic类型使用详解

《C#dynamic类型使用详解》C#中的dynamic类型允许在运行时确定对象的类型和成员,跳过编译时类型检查,适用于处理未知类型的对象或与动态语言互操作,dynamic支持动态成员解析、添加和删... 目录简介dynamic 的定义dynamic 的使用动态类型赋值访问成员动态方法调用dynamic 的

C#反射编程之GetConstructor()方法解读

《C#反射编程之GetConstructor()方法解读》C#中Type类的GetConstructor()方法用于获取指定类型的构造函数,该方法有多个重载版本,可以根据不同的参数获取不同特性的构造函... 目录C# GetConstructor()方法有4个重载以GetConstructor(Type[]

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam