mongo源码学习(四)invariant
前言
在看MongoDB源码的时候,经常会看到这个玩意儿:invariant。
invariant的字面意思是:不变式。
在emacs上跳转到函数定义要安装一个插件,ggtags,费了老大劲儿。这都可以重开一篇写一下了。
invariant的定义如下:
定义真的是恶心啊。。。
BOOST_PP_OVERLOAD
在看invariant的定义之前,先要了解一下:BOOST_PP_OVERLOAD
The BOOST_PP_OVERLOAD variadic macro expands to the name of a non-variadic macro having a given number of parameters.
Usage
BOOST_PP_OVERLOAD(prefix,...) (v)
Arguments
prefix
The prefix of the non-variadic macro name.
...
Variadic data. The number of variadic data elements, as determined by BOOST_PP_VARIADIC_SIZE, is appended to the prefix to form the output non-variadic macro name.
Remarks
This macro creates a macro name which depends on the number of elements of variadic data. It should be used in the form of
BOOST_PP_OVERLOAD(MACRO_NAME_,__VA_ARGS__)(__VA_ARGS__) in order to call a non-variadic macro taking a given number of variadic data elements as non-variadic arguments. In this way one can invoke a variadic macro with a variable number of parameters which calls one of a series of non-variadic macros doing very similar things.
Requirements
Header: <boost/preprocessor/facilities/overload.hpp>
Sample Code
#include <boost/preprocessor/facilities/overload.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/facilities/empty.hpp> #include <boost/preprocessor/arithmetic/add.hpp> #define MACRO_1(number) MACRO_2(number,10) #define MACRO_2(number1,number2) BOOST_PP_ADD(number1,number2) #define MACRO_ADD_NUMBERS(...) BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__) // or for Visual C++ #define MACRO_ADD_NUMBERS(...) \ BOOST_PP_CAT(BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY()) MACRO_ADD_NUMBERS() // output is 15 MACRO_ADD_NUMBERS(,) // output is 9
BOOST_PP_OVERLOAD试一个可变参数的宏,用来扩展固定参数个数的非可变参数宏。
使用方法
BOOST_PP_OVERLOAD(prefix,...) (v)
prefix:非可变参数宏名称的前缀
...:可变的数据。可变数据元素的个数用BOOST_PP_VARIDIC_SIZE决定,通过prefix和BOOST_PP_VARIDIC_SIZE拼接出非可变参数宏的名称。
说明
这个宏可以根据可变数据的个数来生成一个宏的名称。为了对可变长度的参数调用一个非可变参数的宏,应该使用BOOST_PP_OVERLOAD(MACRO_NAME_,__VA_ARGS__)(__VA_ARGS__)这种形式。
举例
仿照Sample Code,我自己来写一个demo。
#include <iostream> #include <boost/preprocessor/facilities/overload.hpp> int add(int number1, int number2); #define MACRO_1(number) MACRO_2(number, 10) // mmp, 它会先检查add的原型, 然后再去做替换, 看来这里还是 #define MACRO_2(number1, number2) add(number1, number2) // 多参数的宏展开实现重载 #define MACRO_ADD_NUMBERS(...) BOOST_PP_OVERLOAD(MACRO_, __VA_ARGS__)(__VA_ARGS__) int main() { std::cout << ) << std::endl; std::cout << , ) << std::endl; ; } int add(int number1, int number2) { return number1 + number2; }
对此,我只想说,你们真牛逼,用宏都可以实现重载。
这个是我第一次用到boost库,以后应该会有机会经常用吧,装这个狗玩意儿花了不少时间~
mongo中的invariant
接下来继续看mongo里面的invariant。
#pragma once #include <boost/preprocessor/facilities/overload.hpp> #include <string> #include "mongo/platform/compiler.h" #include "mongo/util/debug_util.h" namespace mongo { /** * This include exists so that mongo/base/status_with.h can use the invariant macro without causing * a circular include chain. It should never be included directly in any other file other than that * one (and assert_util.h). */ // 我擦, 这个defined还可以这么用 #if !defined(MONGO_INCLUDE_INVARIANT_H_WHITELISTED) #error "Include assert_util.h instead of invariant.h." #endif // 如果invariant failed会怎么办 MONGO_COMPILER_NORETURN void invariantFailed(const char* expr, const char* file, unsigned line) noexcept; // This overload is our legacy invariant, which just takes a condition to test. // // ex) invariant(!condition); // // Invariant failure !condition some/file.cpp 528 // // 这个重载是为了测试我们的条件, 比如invariant(!condition), 如果condition不成立的话 // 就会打印这个文件名和对应的行数, 相当于日志功能? // MONGO_invariant_是宏前缀, 1表示只有一个参数 // 他妈的, #Expression是个鸡毛意思哦 #define MONGO_invariant_1(Expression) \ ::mongo::invariantWithLocation((Expression), #Expression, __FILE__, __LINE__) // 模板来了, 模板只能在头文件中使用哦, 内联函数的模板 template <typename T> inline void invariantWithLocation(const T& testOK, const char* expr, const char* file, unsigned line) { if (MONGO_unlikely(!testOK)) { // 如果测试不合格就执行下面的函数了 ::mongo::invariantFailed(expr, file, line); } } // 同样也是failed的情况 MONGO_COMPILER_NORETURN void invariantFailedWithMsg(const char* expr, const std::string& msg, const char* file, unsigned line) noexcept; // This invariant overload accepts a condition and a message, to be logged if the condition is // false. // // ex) invariant(!condition, "hello!"); // // Invariant failure !condition "hello!" some/file.cpp 528 // // 附加了一个信息 #define MONGO_invariant_2(Expression, contextExpr) \ ::mongo::invariantWithContextAndLocation((Expression), \ #Expression, \ [&]() -> std::string { return (contextExpr); }, \ __FILE__, \ __LINE__) // 又是一个模板 template <typename T, typename ContextExpr> inline void invariantWithContextAndLocation( const T& testOK, const char* expr, ContextExpr&& contextExpr, const char* file, unsigned line) { if (MONGO_unlikely(!testOK)) { ::mongo::invariantFailedWithMsg(expr, contextExpr(), file, line); } } // This helper macro is necessary to make the __VAR_ARGS__ expansion work properly on MSVC. // 这里还要注意在Microsoft Visual C++里面的坑, 所以专门用了这么个宏 #define MONGO_expand(x) x // 实现宏重载 #define invariant(...) \ MONGO_expand(MONGO_expand(BOOST_PP_OVERLOAD(MONGO_invariant_, __VA_ARGS__))(__VA_ARGS__)) // Behaves like invariant in debug builds and is compiled out in release. Use for checks, which can // potentially be slow or on a critical path. // 又来了一个assert #define MONGO_dassert(...) \ if (kDebugBuild) \ invariant(__VA_ARGS__) #define dassert MONGO_dassert } // namespace mongo
反正我是不怕invariant了,我知道这个要干嘛了,哈哈,好多地方都用到了这个玩意儿。其实就是判断一个表达式是否成立,然后打印一下语句,包括文件名和行号这些。
但其实还有几个东西又不懂了,比如#Expression,ContextExpr&&,我们继续哦。
C++中的#和##
C++中的&和&&
mongo源码学习(四)invariant的更多相关文章
- mongo源码学习(四)服务入口点ServiceEntryPoint
在上一篇博客mongo源码学习(三)请求接收传输层中,稍微分析了一下TransportLayer的作用,这篇来看下ServiceEntryPoint是怎么做的. 首先ServiceEntryPoint ...
- mongo源码学习(三)请求接收传输层
在上一篇博客中(mongo源码学习(二)db.cpp之mongoDbMain方法分析),我们把db.cpp中的mongoDbMain的执行过程分析了一下,最后会调用initAndListen(serv ...
- mongo源码学习(一)
在git上把mongo的源码给拉下来了,然后目录大概是这样的: 这个mongo是用C++写的,编译并没有用Makefile而是用的scons工具,这个好像是python写的. mongo后台进程的入口 ...
- [spring源码学习]四、IOC源码——普通bean初始化
一.代码例子 此节开始涉及到一个bean具体生成和保存的过程,仅仅涉及到最简单的bean,代码依旧是最简单的 public static void main(String[] args) { Defa ...
- dubbo源码学习(四):暴露服务的过程
dubbo采用的nio异步的通信,通信协议默认为 netty,当然也可以选择 mina,grizzy.在服务端(provider)在启动时主要是开启netty监听,在zookeeper上注册服务节点, ...
- mongo源码学习(二)db.cpp之mongoDbMain方法分析
mongo后台进程的入口:mongo/src/mongo/db/dbmain.cpp,wmain(for windows)和main函数,main函数也很简单,就是委托给db.cpp中的mongoDb ...
- mybatis源码学习(四)--springboot整合mybatis原理
我们接下来说:springboot是如何和mybatis进行整合的 1.首先,springboot中使用mybatis需要用到mybatis-spring-boot-start,可以理解为mybati ...
- MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)
前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...
- Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析
经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...
随机推荐
- 1142 - show view command denied to user
原因是没有给test用户授予"show_view_priv"权限 mysql> SELECT * FROM mysql.user WHERE User = 'test' an ...
- Linux 的僵尸(zombie)进程
可能很少有人意识到,在一个进程调用了exit之后,该进程 并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构.在Linux进程的5种状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎 ...
- C语言下的错误处理的问题
下面是三种C语言的错误处理,你喜欢哪一种?还是都不喜欢? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /* 问题: 不充分,而且很容易出错,前 ...
- 使用 Apache Commons CSV 读写 CSV 文件
有时候,我们需要读写 CSV 文件,在这里给大家分享Apache Commons CSV,读写 CSV 文件非常方便. 具体官方文档请访问Apache Commons CSV. 官方文档已经写得很详细 ...
- 基于axis1.4的webservice实例
1.准备工作: 概念:SOAP(简单对象访问协议).WSDL(web服务描述语言).XML(可扩展标记语言).axis(阿帕奇可扩展交互系统) (1) 下载axis1.4,将axis1.4中的 ...
- JAVA中使用HTTP 1.1提高基于AXIS 1.4的web service的性能
HTTP 1.1会在第一次连接的时候进行认证, 而在一定时间内保持连接而不用重新验证. 一般情形下,每个web service请求都会在web service服务端验证, 而验证会消耗很多时间, 因此 ...
- 第二篇:呈现内容_第一节:Control呈现
一.Control的呈现过程 在上个章节““生死有序”的控件生命周期”中,我们提到Render是控件开发的主角,但在控件树的“合成模式(Composite)”部分这位主角却缺席了(戏份太多的缘由).哦 ...
- Matlab之视角旋转函数[转]
Matlab中有两个视角旋转函数:view和rotate,下面详细介绍: view: 一: view(az,el):az是方位角,el是仰角,单位均是度.具体: 以x轴从左到右(即从小到大)平行放置在 ...
- C# string和byte[]的转换
转自 http://www.cnblogs.com/Mainz/archive/2008/04/09/String_Byte_Array_Convert_CSharp.html string类型转成b ...
- 负载均衡层次结构:LVS Nginx DNS CDN
文章地址:http://blog.csdn.net/mindfloating/article/details/51020767 作为后端应用的开发者,我们经常开发.调试.测试完我们的应用并发布到生产环 ...