`
febird
  • 浏览: 246868 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

检查序列化声明的顺序和成员定义的顺序

阅读更多

项目地址:http://code.google.com/p/febird

 

DataIO_is_realdump用来推断一个对象是否可以直接通过dump内存来完成序列化,如果可以,在load/save时会有极大的性能提高。如果dump后,一些成员除了需要byte_swap,而不需要其它任何转化,也可以安全地先dump然后再byte_swap,这样比一个成员一个成员地load/save并且byte_swap要快得多。

但是可以引发一个问题,就是如果序列化声明的顺序和成员定义的顺序不同,并且推断结果表明DataIO_is_realdump为真,真正序列化的顺序就就是成员定义的顺序,和序列化声明的顺序不同,而序列化声明的顺序才是调用者真正的意图。

一开始没有仔细考虑这个问题,只是把它丢给使用者,但是这样的错误实在太微妙了,很多时候都不会出错(因为load和save一样),除非load/save一个优化一个没优化,问题才会暴露出来。

认真考虑一下,这个问题其实可以检测出来,但不是在编译时,只能在运行时。只要每次调用 operator& 的时候记录参数(某个成员)的地址,下个成员的地址如果小于等于这个地址,就表明出了错。再进一步,如果某个“成员”的地址出了那个对象的地址范围,更是一个错误,如果这个成员是个指向其他对象的引用,则有可能不是一个错误,这也是可以推断出来的,引用类型本来就不是dumpable的,可以用trait去除。以下是实现代码:

template<class DataIO, class Outer, int Size, bool Dumpable>
struct DataIO_is_realdump
{
	BOOST_STATIC_CONSTANT(int, size = Size);
	typedef boost::mpl::bool_<Dumpable> is_dump;

#if (defined(_DEBUG) || !defined(NDEBUG)) && !defined(DATA_IO_DONT_CHECK_REAL_DUMP)
	const Outer* address;
	const char*  prev_member;
	DataIO_is_realdump(const Outer* p, const void* prev_member)
		: address(p), prev_member((const char*)prev_member) {}
	DataIO_is_realdump(const Outer* p)
		: address(p), prev_member((const char*)p) {}
#else
	DataIO_is_realdump(const Outer*, const void* = 0) {}
#endif

	template<class T>
	void check_member_order(const T& x, ::boost::mpl::true_)
	{
#if (defined(_DEBUG) || !defined(NDEBUG)) && !defined(DATA_IO_DONT_CHECK_REAL_DUMP)
	// if member declaration order of &a&b&c&d is different with where they defined in class
	// here will raise an assertion fail
	//
	// 如果成员序列化声明的顺序 &a&b&c&d 和它们在类中定义的顺序不同
	// 这里会引发一个断言
	// 如果序列化了一个非类的成员(比如 &a&b&c&d 中可能一个标识符引用了不是雷成员的某个变量),也会引发断言
		assert((const char*)&x >= (const char*)address);
		assert((const char*)&x <= (const char*)address + sizeof(Outer) - sizeof(T));
		if (prev_member != (const char*)address)
			assert(prev_member < (const char*)&x);
#endif
	}
	template<class T>
	void check_member_order(const T&, ::boost::mpl::false_)
	{
	}

	template<class T>
	DataIO_is_realdump<DataIO, Outer, Size+sizeof(T), boost::mpl::bool_<Dumpable && DataIO_is_dump<DataIO, T>::value>::value>
	operator&(const T& x)
	{
		check_member_order(x, ::boost::mpl::bool_<Dumpable && DataIO_is_dump<DataIO, T>::value>());
		return DataIO_is_realdump<DataIO, Outer, Size+sizeof(T), boost::mpl::bool_<Dumpable && DataIO_is_dump<DataIO, T>::value>::value>(address, &x);
	}
};

 

其中,check_member_order只对“根据目前的推断,Outer对象如果是dumpable,就执行检查,反之则啥都不做。

当然,需要注意的就是,在外部初始化时,调用DataIO_is_realdump(const Outer* p),而 DataIO_is_realdump(const Outer* p, const void* prev_member)仅在递归(严格讲并非递归)推断时,才使用。因此初始化传入的那个p,必须就是operator&中的对象属主,这只能由调用者保证,幸好,这个调用者只是DataIO库。

 

项目地址:http://code.google.com/p/febird

1
0
分享到:
评论

相关推荐

    canvas-sequencer:存储,序列化,解析和执行画布上下文指令序列

    画布音序器 存储,序列化,解析和执行一系列画布上下文指令!内容为什么通常,如果您有一系列的画布指令,则可以在一个函数中对其进行预定义,该函数将以脚本文件的形式分发给所有客户端。 但是,假设您希望能够动态...

    UML2.x之序列图详解

    序列图是用来记录系统需求和整理系统设计的不可或缺的uml框图,它...序列图是所有框图里改进最大的一个,序列图改进了定义事务的能力和拓展性,对序列图的符号集合的改变,已经在序列化逻辑建模方面取得巨大的进步。

    数据结构实验

    1. 学会定义单链表的结点类型,实现对单链表的一些基本操作和具体的函数定义,了解并掌握单链表的类定义以及成员函数的定义与调用。 2. 掌握单链表基本操作及两个有序表归并、单链表逆置等操作的实现。 二 、实验...

    dessser:(反)序列化器生成器

    这些类型可以通过多种方式进行(反)序列化和操纵。 通常,(某些值类型的)值是可选的(又称null或未知)。 因此,类maybe_nullable使用布尔值扩展了值类型,该布尔值指示这些值是否可以为null。 最

    c#学习笔记——学习心得

    写类的时候使用System.Serializable属性以便使类的成员可以序列化 方法:是一种用于实现可以由对象或类执行的计算或操作的成员。类的方法主要是和类相关联的动作,它是类的外部界面,对于那些私有的字段来说,外部...

    数据分析—排序.pdf

    实现接⼝的 3 个⽅法 write:序列化属性值为⼆进制 readFields:从⼆进制反序列化属性值 compareTo:⾃定义⼤⼩⽐较规则 4. 使⽤⾃定义 key 作为 map 输出的 key 类型 ⽅案⼆:⾃定义排序规则 1. ⾃定义类继承 ...

    Microsoft SQL Server 2005 Express Edition SP3

    由于这两个产品都依赖于相同版本的 .NET Framework,因此必须按照以下顺序卸载它们: SQL Server Express Visual Studio 2005 .NET Framework 2.0 [顶部] 3.13 维护模式下将提示输入 Setup.exe 的路径 如果...

    C#语言规范(4.0版本)

    10.3.7 静态成员和实例成员 281 10.3.8 嵌套类型 282 10.3.8.1 完全限定名 282 10.3.8.2 已声明可访问性 282 10.3.8.3 隐藏 283 10.3.8.4 this 访问 283 10.3.8.5 对包含类型的私有和受保护成员的访问 284 10.3.8.6 ...

    JAVA基础课程讲义

    序列化/反序列化的步骤和实例 162 综合的序列化和反序列化练习 163 JAVA.IO包相关流对象用法总结(尚学堂1002班王鑫) 165 IO中其他常用类 165 File类 165 RandomAccessFile 166 思考作业 166 上机作业 166 提高课外...

    C++ Primer中文版(第5版)李普曼 等著 pdf 1/3

     2.2.2 变量声明和定义的关系 41  2.2.3 标识符 42  2.2.4 名字的作用域 43  2.3 复合类型 45  2.3.1 引用 45  2.3.2 指针 47  2.3.3 理解复合类型的声明 51  2.4 const限定符 53  2.4.1 const的引用 54  ...

    C++Primer(第5版 )中文版(美)李普曼等著.part2.rar

     2.2.2 变量声明和定义的关系 41  2.2.3 标识符 42  2.2.4 名字的作用域 43  2.3 复合类型 45  2.3.1 引用 45  2.3.2 指针 47  2.3.3 理解复合类型的声明 51  2.4 const限定符 53  2.4.1 const的引用 54  ...

    数据结构栈和队列

    1、理解栈的逻辑结构定义及特点、掌握栈的存储结构的描述、 实现栈的基本运算。 2、理解队列的逻辑结构定义及特点、掌握循环队列存储结构及其描述方法、掌握循环队列的基本运算。 二、实验内容: 1、建立顺序栈,并...

    微软C#语言规范,C#语言教程中文版

    10.3.7 静态成员和实例成员 281 10.3.8 嵌套类型 282 10.3.8.1 完全限定名 282 10.3.8.2 已声明可访问性 282 10.3.8.3 隐藏 283 10.3.8.4 this 访问 283 10.3.8.5 对包含类型的私有和受保护成员的访问 284 10.3.8.6 ...

    C#语言规范4.0

    10.3.7 静态成员和实例成员 281 10.3.8 嵌套类型 282 10.3.8.1 完全限定名 282 10.3.8.2 已声明可访问性 282 10.3.8.3 隐藏 283 10.3.8.4 this 访问 283 10.3.8.5 对包含类型的私有和受保护成员的访问 284 10.3.8.6 ...

    XQuery权威指南(简码·扫描版)

     3.8 计算顺序和括号  3.9 比较表达式  3.10 条件(ifIthen-else)表达式  3.11 逻辑表达式 第4章 使用路径定位输入文件 4.1 路径表达式 4.2 谓词 4.3 动态路径 4.4 输入文件 4.5 深入了解上下文 第5章 在结果中...

    C#语言规范(2.0,3.0,4.0合集)

    10.3.7 静态成员和实例成员 281 10.3.8 嵌套类型 282 10.3.8.1 完全限定名 282 10.3.8.2 已声明可访问性 282 10.3.8.3 隐藏 283 10.3.8.4 this 访问 283 10.3.8.5 对包含类型的私有和受保护成员的访问 284 10.3.8.6 ...

    C#_语言规范_4.0_中文版

    10.3.7 静态成员和实例成员 281 10.3.8 嵌套类型 282 10.3.8.1 完全限定名 282 10.3.8.2 已声明可访问性 282 10.3.8.3 隐藏 283 10.3.8.4 this 访问 283 10.3.8.5 对包含类型的私有和受保护成员的访问 284 10.3.8.6 ...

    C#5.0本质论第四版(因文件较大传的是百度网盘地址)

    3.4 代码块、作用域和声明空间 74 3.5 布尔表达式 76 3.5.1 关系操作符和相等性操作符 77 3.5.2 逻辑布尔操作符 77 3.5.3 逻辑求反操作符 78 3.5.4 条件操作符 79 3.5.5 空接合操作符 80 ...

    Visual C++ 2010入门经典(第5版)--源代码及课后练习答案

    4.4.2 声明并初始化lvalue引用 172 4.4.3 声明并初始化rvalue引用 173 4.5 字符串的本地C++库函数 174 4.5.1 查找以空字符结尾的字符串的长度 174 4.5.2 连接以空字符结尾的字符串 174 4.5.3 复制以空字符结尾...

Global site tag (gtag.js) - Google Analytics