muduo网络库学习之Timestamp类、AtomicIntegerT 类封装中的知识点

一、Timestamp类封装

class Timestamp : public muduo::copyable,                   public boost::less_than_comparable<Timestamp>

类图如下:

值语义:可以拷贝,拷贝之后,与原对象脱离关系

对象语义:要么是不能拷贝;要么可以拷贝,拷贝之后与原对象仍然存在一定的关系,比如共享底层资源

两者之间的关系参见这里

1、muduo::copyable 空基类,标识类,值类型

2、less_than_comparable<Timestamp> 模板类

Timestamp 要求实现<, =,可自动实现>,<=,>= 3、成员 microSecondsSinceEpoch_ 是现在这个时刻距离1970-01-01 00:00:00 (UTC 时间) 的微秒数

4、BOOST_STATIC_ASSERT 编译时断言

     assert 运行时断言

5、使用PRld64

int64_t 用来表示64位整数,在32位系统中是long long int,在64位系统中是long int,所以打印int64_t的格式化方法是: printf(“%ld”, value);  // 64bit OS printf("%lld", value); // 32bit OS 跨平台的做法: #define __STDC_FORMAT_MACROS #include <inttypes.h> #undef __STDC_FORMAT_MACROS printf("%" PRId64 "\n", value);  

二、AtomicIntegerT 类封装

template<typename T> class AtomicIntegerT : boost::noncopyable

类图如下:

1、为什么需要原子性操作?

x++; (x是共享变量) 从内存中读x的值到寄存器中,对寄存器加1,再把新值写回x所处的内存地址 (1)、假设是多核(multiprocessors)的情况,x 的初始值为5:

因为每个核都有自己独立的寄存器,两个线程同时访问可能出现只加了一次的情况。

(2)、假设是单核的情况: 例如有两个线程,它们按照如下顺序执行(注意读x和写回x是原子操作,两个线程不能同时执行(伪并发),是分时实现): time    Thread 1         Thread 2       load eax, x                            load eax, x       add eax, 1        

add eax, 1

     store x, eax                            store x, eax 我们会发现最终x的值会是1而不是2,Thread 1的结果被覆盖掉了,因为Thread2在进行++之前以为x还是0,而不是1(每个线程都保存自己的上下文包括寄存器的值,重新调度回Thread2时eax被加载为原来保存的0)。

这种情况下我们就需要对x++这样的操作加锁(例如Pthread中的mutex)以保证同步,或者使用一些提供了atomic operations的库,linux下的如atomic.h,下面会介绍部分函数。

2、gcc 原子性操作

// 原子自增操作 type __sync_fetch_and_add (type *ptr, type value)

 type tmp = *ptr;

 *ptr += value;

   return tmp; // 原子比较和设置操作 type __sync_val_compare_and_swap (type *ptr, type oldval, type newval)

 if (*ptr == oldval)  

{

*ptr = newval return oldval;

}

else

     return *ptr;

bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval)

if (*ptr == oldval)  

{

*ptr = newval;  return true;

}

else

     return false;

// 原子赋值操作 type __sync_lock_test_and_set (type *ptr, type value)

 type tmp = *ptr;

 *ptr = value;

   return tmp;

使用这些原子性操作,编译的时候需要加-march=cpu-type  或者 -march = native

无锁队列实现 http://coolshell.cn/articles/8239.html

更多原子性操作 http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/Atomic-Builtins.html

3、volatile 关键字

volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。简单地说就是防止编译器对代码进行优化。当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,而不是使用保存在寄存器中的备份。即使它前面的指令刚刚从该处读取过数据,而且读取的数据立刻被保存。

补充:gcc/g++ 一些编译选项

-Wall               // 大部分警告 -Wextra               // 一些额外的警告 -Werror               // 当出现警告时转为错误,停止编译。(对应 -Wno-error) -Wconversion          // 一些可能改变值的隐式转换,给出警告。 -Wno-unused-parameter     // 函数中出现未使用的参数,不给出警告。 -Wold-style-cast          // C风格的转换,给出警告 -Woverloaded-virtual     // 如果函数的声明隐藏住了基类的虚函数,就给出警告。 -Wpointer-arith          // 对函数指针或者void *类型的指针进行算术操作时给出警告 -Wshadow          // 当一个局部变量遮盖住了另一个局部变量,或者全局变量时,给出警告。

-Wwrite-strings        // 规定字符串常量的类型是const char[length],因此,把这样的地址复制给 non-const char *指针将产生警告.     

                                   这些警告能够帮助你在编译期间发现企图写入字符串常量 的代码

-march=native          // 指定cpu体系结构为本地平台

注:本文对原子操作与锁、volatile等讨论比较基础,更详细的探讨请参考这篇文章

参考:

muduo manual.pdf

《linux 多线程服务器编程:使用muduo c++网络库》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Angular&服务

ionic3 在app首页跳转重定向报错

1182
来自专栏专注数据中心高性能网络技术研发

linux lsof命令查看文件占用进程

1.lsof简介 lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以...

3054
来自专栏地方网络工作室的专栏

Shell 命令行,实现对若干网站状态批量查询是否正常的脚本

Shell 命令行,实现对若干网站状态批量查询是否正常的脚本 如果你有比较多的网站,这些网站的运行状态是否正常则是一件需要关心的事情。但是逐一打开检查那简直是一...

2098
来自专栏抠抠空间

django自带权限机制

权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活;用好权限机制,能让系统更加强大和健壮。因此,基于Django的开发,理清Django权...

823
来自专栏技术之路

翻译qmake文档(三) Creating Project Files

原英文文档:http://qt-project.org/doc/qt-5/qmake-project-files.html 创建项目文件      项目文件...

1806
来自专栏Crossin的编程教室

Python 实战(3):更多的页面

现在我们网站已经有了一个简单的页面、一段简单的请求处理代码和一个简单的数据库。上次最后我剧透了下,之后将会通过豆瓣电影的 API 获取更多的电影数据。不过在此之...

2655
来自专栏眯眯眼猫头鹰的小树杈

linux常用指令学习记录

locate会根据/var/lib/mlocate内的数据库记载,找出用户输入的关键字文件名,即所有包含该关键字的文件都将被输出。但是因为数据库的更新一般为一天...

782
来自专栏玄魂工作室

如何学python 第十九课 文件操作

今天我们来说说文件操作。文件操作在程序编写里有着举足轻重的作用。文件操作,主要包含文件的输入和输出。学会了文件操作,就可以写出更符合实际需求的脚本。 我会先介绍...

34811
来自专栏程序员互动联盟

【答疑释惑第三十六讲】Windows下如何调试?

疑惑一 Windows窗口程序到底能不能用printf? 很多小伙伴在控制台下写程序时,要打印或者调试很方便,用printf就可以直接打印输出,方便看结果,但是...

2564
来自专栏视觉求索无尽也

【置顶】Python开发中常见问题参考资料:问题汇总:

如果我们在outside.py文件中调用hub.py时,就会打印出this message should not be shown out of this fi...

1303

扫码关注云+社区