muduo网络库源码学习————原子性操作Atomic.h
原子性操作可以做到比互斥锁更小的开销,在多线程编程中原子性操作是非常有用的。Atomic.h文件位于muduo/base下,代码如下:
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
//原子性操作:比锁的开销更小
#ifndef MUDUO_BASE_ATOMIC_H
#define MUDUO_BASE_ATOMIC_H
#include <boost/noncopyable.hpp>
#include <stdint.h>
namespace muduo
{
namespace detail
{//模板
template<typename T>
class AtomicIntegerT : boost::noncopyable//不可拷贝
{
public:
AtomicIntegerT(): value_(0)
{
}
// uncomment if you need copying and assignment
//
// AtomicIntegerT(const AtomicIntegerT& that)
// : value_(that.get())
// {}
//
// AtomicIntegerT& operator=(const AtomicIntegerT& that)
// {
// getAndSet(that.get());
// return *this;
// }
T get()
{//原子性比较还有设置操作
return __sync_val_compare_and_swap(&value_, 0, 0);//判断value的值是否为零,如果为0则赋值0
//返回的是未赋值之前的值,其实就是获取value的值
}
T getAndAdd(T x)
{//先获取然后执行加的操作,返回的是未修改的值
return __sync_fetch_and_add(&value_, x);
}
T addAndGet(T x)
{//先加然后获取
return getAndAdd(x) + x;//这里是调用getAndAdd函数,返回之后再加上x
}
T incrementAndGet()
{//自加1
return addAndGet(1);
}
T decrementAndGet()
{//自减1
return addAndGet(-1);
}
void add(T x)
{
getAndAdd(x);//加法
}
void increment()
{//先加后获取
incrementAndGet();
}
void decrement()
{//先减后获取
decrementAndGet();
}
T getAndSet(T newValue)
{//返回原来的值然后设置成新值
return __sync_lock_test_and_set(&value_, newValue);
}
private:
volatile T value_;//volatile关键字确保指令不会因编译器的优化而省略(防止编译器对代码进行优化)
//每次都从内存读取数据而不是使用保存在寄存器中的备份
//是为了避免其他线程已经将该值修改
};
}
//两个实例化,32位和64位的原子性操作
typedef detail::AtomicIntegerT<int32_t> AtomicInt32;
typedef detail::AtomicIntegerT<int64_t> AtomicInt64;
}
#endif // MUDUO_BASE_ATOMIC_H
其测试代码为Atomic_unittest.cc主要是进行一些简单的判别操作:
#include <muduo/base/Atomic.h>
#include <assert.h>
//原子性操作的测试函数
int main()
{
{//64位的原子性操作
muduo::AtomicInt64 a0;
//断言测试一个条件并可能使程序终止
assert(a0.get() == 0);//首先肯定会被置为0
assert(a0.getAndAdd(1) == 0);//加1,先获取然后加,还是0
assert(a0.get() == 1);//此时变为1
assert(a0.addAndGet(2) == 3);//先加然后获取,所以是3
assert(a0.get() == 3);
assert(a0.incrementAndGet() == 4);//先加然后获取
assert(a0.get() == 4);
a0.increment();
assert(a0.get() == 5);
assert(a0.addAndGet(-3) == 2);
assert(a0.getAndSet(100) == 2);
assert(a0.get() == 100);
}
{//32位的原子性操作
muduo::AtomicInt32 a1;
assert(a1.get() == 0);
assert(a1.getAndAdd(1) == 0);
assert(a1.get() == 1);
assert(a1.addAndGet(2) == 3);
assert(a1.get() == 3);
assert(a1.incrementAndGet() == 4);
assert(a1.get() == 4);
a1.increment();
assert(a1.get() == 5);
assert(a1.addAndGet(-3) == 2);
assert(a1.getAndSet(100) == 2);
assert(a1.get() == 100);
}
}
单独编译后运行结果如下,因为断定都是正确的,所以执行不会有任何的结果
muduo网络库源码学习————原子性操作Atomic.h的更多相关文章
- muduo网络库源码学习————Timestamp.cc
今天开始学习陈硕先生的muduo网络库,moduo网络库得到很多好评,陈硕先生自己也说核心代码不超过5000行,所以我觉得有必要拿过来好好学习下,学习的时候在源码上面添加一些自己的注释,方便日后理解, ...
- muduo网络库源码学习————线程类
muduo库里面的线程类是使用基于对象的编程思想,源码目录为muduo/base,如下所示: 线程类头文件: // Use of this source code is governed by a B ...
- muduo网络库源码学习————线程池实现
muduo库里面的线程池是固定线程池,即创建的线程池里面的线程个数是一定的,不是动态的.线程池里面一般要包含线程队列还有任务队列,外部程序将任务存放到线程池的任务队列中,线程池中的线程队列执行任务,也 ...
- muduo网络库源码学习————互斥锁
muduo源码的互斥锁源码位于muduo/base,Mutex.h,进行了两个类的封装,在实际的使用中更常使用MutexLockGuard类,因为该类可以在析构函数中自动解锁,避免了某些情况忘记解锁. ...
- muduo网络库源码学习————线程特定数据
muduo库线程特定数据源码文件为ThreadLocal.h //线程本地存储 // Use of this source code is governed by a BSD-style licens ...
- muduo网络库源码学习————日志滚动
muduo库里面的实现日志滚动有两种条件,一种是日志文件大小达到预设值,另一种是时间到达超过当天.滚动日志类的文件是LogFile.cc ,LogFile.h 代码如下: LogFile.cc #in ...
- muduo网络库源码学习————日志类封装
muduo库里面的日志使方法如下 这里定义了一个宏 #define LOG_INFO if (muduo::Logger::logLevel() <= muduo::Logger::INFO) ...
- muduo网络库源码学习————线程本地单例类封装
muduo库中线程本地单例类封装代码是ThreadLocalSingleton.h 如下所示: //线程本地单例类封装 // Use of this source code is governed b ...
- muduo网络库源码学习————无界队列和有界队列
muduo库里实现了两个队列模板类:无界队列为BlockingQueue.h,有界队列为BoundedBlockingQueue.h,两个测试程序实现了生产者和消费者模型.(这里以无界队列为例,有界队 ...
随机推荐
- PTA 6-1 单链表逆转
本题是一个非常经典的题目:单链表逆转. 这是链表结点的定义: typedef struct Node *PtrToNode; struct Node { ElementType Data; /* 存储 ...
- json文件操作
1.把字典或list转换成字符串方法 json.dumps() 2.把字符串转换成字典方法 json.loads() 3.indent 存储文件时每行加缩进数 4.ensere_asci 文件中有中文 ...
- 《深入理解 Java 虚拟机》读书笔记:垃圾收集器与内存分配策略
正文 垃圾收集器关注的是 Java 堆和方法区,因为这部分内存的分配和回收是动态的.只有在程序处于运行期间时才能知道会创建哪些对象,也才能知道需要多少内存. 虚拟机栈和本地方法栈则不需要过多考虑回收的 ...
- C#多线程(4):进程同步Mutex类
Mutex 类 构造函数和方法 系统只能运行一个程序的实例 解释一下上面的示例 接替运行 进程同步示例 另外 Mutex 类 Mutex 中文为互斥,Mutex 类叫做互斥锁.它还可用于进程间同步的同 ...
- Python—一个简单搜索引擎索引库
因为课业要求,搭建一个简单的搜索引擎,找了一些相关资料并进行了部分优化(坑有点多) 一.数据 数据是网络上爬取的旅游相关的攻略页面 这个是travels表,在索引中主要用到id和url两个字段. 页面 ...
- docker 概览 (1)
Docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化.容器是完全使 ...
- 微信小程序之base64图片如何预览与一键保存到本地相册?
需求:由于后台服务器各方面的限制,现在服务器返回的图片是base64格式的,小程序端需要支持预览图片和多个图片一键下载功能 一.如何预览base64位图片? WXML页面:item.src的值是bas ...
- Python - 批量获取文件夹的大小输出为文件格式化保存
很多时候,查看一个文件夹下的每个文件大小可以轻易的做到,因为文件后面就是文件尺寸,但是如果需要查看一个文件夹下面所有的文件夹对应的尺寸,就发现需要把鼠标放到对应的文件夹上,稍等片刻才会出结果. 有时候 ...
- JavaScript数据类型 —— 基础语法(2)
JavaScript基础语法(2) 数据类型 js中有六种数据类型,包括五种基本数据类型(Number,String,Boolean,Undefined,Null),和一种复杂数据类型(Object) ...
- 1. jquery插件手机
1. http://jqtjs.com/preview/demos/main/index.html#home2. jquery weUI ===== 插件:https://blog.csdn.net/ ...