持久性内存编程——类型

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

相关文章

NameNode内存生产配置

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

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚: