muduo源码解析10-logstream类
FixedBuffer和logstream
class FixedBuffer:noncopyable
{
};
class logstream:noncopyable
{
};
先说一下包含的头文件有一个StringPiece.h
个人感觉这个stringpiece没有必要实现啊,直接用std::string就好了
内部实现的操作,基本上std::string都能完成.后面有关stringpiece我都直接放弃了
const char* data() const { return ptr_; }
int size() const { return length_; }
bool empty() const { return length_ == 0; }
const char* begin() const { return ptr_; }
const char* end() const { return ptr_ + length_; }
void clear() { ptr_ = NULL; length_ = 0; }
void set(const char* buffer, int len) { ptr_ = buffer; length_ = len; }
下面是作者原话:
A string like object that points into another piece of memory.
Useful for providing an interface that allows clients to easily
pass in either a "const char*" or a "string".
Arghh! I wish C++ literals were automatically of type "string".
FixedBuffer作用:
FixedBuffer类:实现了对于一块字符数组的管理
成员变量:
用char m_data[SIZE]保存数据
用char* m_cur记录当前操作的那个元素的指针,默认指向最后一个字符的下一个位置.
字符数组示意图 SIZE=8
m_data:['1']['2']['3']['4']['\0']['\0']['\0']['\0']
m_cur:4 end:8
因此
length() = 4 =m_cur-m_data
sizeof m_data == 8 ==SIZE
end() == m_data+ sizeof m_data
avail() == end()-m_cur
FixedBuffer成员变量:
private:
void (*m_cookie)(); //一个函数指针,暂时未知作用
char m_data[SIZE]; //最重要的成员,字符数组
char* m_cur; //便于操作字符数组的指针
FixedBuffer成员函数:
public:
FixedBuffer():m_cur(m_data)
{
setCookie(cookieStart);
}
~FixedBuffer()
{
setCookie(cookieEnd);
}
//拷贝一段字符放到字符数组m_data中
void append(const char* buf,size_t len)
{
//只有当剩余元素够用时才进行拷贝
if(implicit_cast<size_t>(avail())>len)
{
memcpy(m_cur,buf,len);
m_cur+=len;
}
}
//返回内部字符串
const char* data() const{return m_data;}
//得到内部字符串的大小,也就是m_data数据长度
int length() const{return static_cast<int>(m_cur-m_data);} //返回m_cur指针
char* current(){return m_cur;} //得到字符数组剩余可用字符
int avail() const{return static_cast<int>(end()-m_cur);} //更改m_cur位置
void add(size_t len){m_cur+=len;} //让m_cur回到初始m_data位置
void reset(){m_cur=m_data;} //清空内部字符数组
void bzero(){memZero(m_data,sizeof(m_data));} //为了GDB使用,返回m_data到m_cur之间的数据
const char* debugString()
{
m_cur='\0';
return m_data;
} void setCookie(void (*cookie)()){m_cookie=cookie;} //为了单元测试使用
string toString() const{return string(m_data,length());}
//StringPiece已放弃使用
//StringPiece toStringPiece() const; private:
const char* end() const{return m_data+sizeof(m_data);}
//都暂时没有实现,以后会实现
static void cookieStart(){}
static void cookieEnd(){}
需要注意一下,源码中作者提供了两个FixedBuffer大小
const int kSmallBuffer=4000;
const int kLargeBuffer=4000*1000;
template class FixedBuffer<kSmallBuffer>;
template class FixedBuffer<kLargeBuffer>;
logstream作用:
logstream 类:
数据成员只有一个,就是上面的FixedBuffer<4000>;
成员函数:
基本上就是重载了一大堆<<操作符,可以实现把各种基本的数据类型保存到内部m_buffer中
logstream成员变量:
private:
typedef detail::FixedBuffer<detail::kSmallBuffer> Buffer;
Buffer m_buffer;//内部数据成员,类型是FixedBuffer<4000>
logstream成员函数:
typedef logstream self; //省字数
public:
//Buffer类型其实就是一个FixedBuffer,大小为4000的类型
typedef detail::FixedBuffer<detail::kSmallBuffer> Buffer;
//重载了一堆<<操作符,可以实现针对各种基本/常用数据类型的logstream << 操作
//很多<<重载的实现都依赖于formatInteger函数
self& operator<<(bool v)
{
m_buffer.append(v?"":"",);
return *this;
}
self& operator<<(short);
self& operator<<(unsigned short);
self& operator<<(int);
self& operator<<(unsigned int);
self& operator<<(long);
self& operator<<(unsigned long);
self& operator<<(long long);
self& operator<<(unsigned long long);
self& operator<<(const void*);
self& operator<<(float v)
{
*this<<static_cast<double>(v);
return *this;
}
self& operator<<(double);
self& operator<<(char v)
{
m_buffer.append(&v,);
return *this;
}
self& operator<<(const char* str)
{
if(str)
m_buffer.append(str,strlen(str));
else
m_buffer.append("(null)",);
return *this;
}
self& operator<<(const unsigned char* str)
{
*this<<reinterpret_cast<const char*>(str);
return *this;
}
self& operator<<(const string& v)
{
m_buffer.append(v.data(),v.size());
return *this;
}
//self& operator<<(const StringPiece& v);废弃掉不用
self& operator<<(const Buffer& v)
{
m_buffer.append(v.data(),v.length());
return *this;
} //一些基本操作,添加数据,返回FixedBuffer<4000>,重置m_buffer
void append(const char* data,int len);
const Buffer& buffer() const{return m_buffer;}
void resetBuffer(){m_buffer.reset();} private:
//用于静态编译时的一些断言
void staticCheck();
//很重要的一个函数,用于实现向m_buffer中append各种类型
template<typename T>
void formatInteger(T);
测试:
#include"base/logstream.h"
#include<iostream>
using namespace std; namespace mymuduo{
namespace currentthread {
void cacheTid()
{
}
}
} int main()
{
//内部数据(字符数组)大小只有4000
mymuduo::logstream ls;
bool b=false;
short s=;
int i=;
unsigned long ul=;
double d=3.123456;
string str("nmsl");
mymuduo::logstream::Buffer buffer;
buffer.append("nmsl2",); ls<<b<<" "<<s<<" "<<i<<" "<<ul<<" "
<<d<<" "<<str.data()<<" "<<buffer; std::cout<<ls.buffer().data()<<std::endl; }
打印结果:
0 23 133 10000000 3.123456 nmsl nmsl2
只要明白了logstream内部是如何存储数据的,就不难理解logstream的实现了,logstream就是封装了一堆
<<操作符,用于保存不同数据类型的数据。
内部存储数据通过FixedBuufer<4000>来实现,而FixedBuufer<4000>又是通过char data[4000]来实现的,
因此只需要搞明白对char[]的基本操作就可以了。
muduo源码解析10-logstream类的更多相关文章
- muduo源码解析5-mutex相关类
mutexlock和mutexlockguard class mutexlock:noncopyable { }: class mutexlockguard:noncopyable { }: 作用: ...
- AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍
AspectJAwareAdvisorAutoProxyCreator 的类图 上图中一些 类/接口 的介绍: AspectJAwareAdvisorAutoProxyCreator : 公开了Asp ...
- Mybatis源码解析3——核心类SqlSessionFactory,看完我悟了
这是昨晚的武汉,晚上九点钟拍的,疫情又一次来袭,曾经熙熙攘攘的夜市也变得冷冷清清,但比前几周要好很多了.希望大家都能保护好自己,保护好身边的人,生活不可能像你想象的那么好,但也不会像你想象的那么糟. ...
- muduo源码解析11-logger类
logger: class logger { }; 在说这个logger类之前,先看1个关键的内部类 Impl private: //logger内部数据实现类Impl,内部含有以下成员变量 //时间 ...
- Netty源码解析 -- 内存对齐类SizeClasses
在学习Netty内存池之前,我们先了解一下Netty的内存对齐类SizeClasses,它为Netty内存池中的内存块提供大小对齐,索引计算等服务方法. 源码分析基于Netty 4.1.52 Nett ...
- AOP源码解析:AspectJExpressionPointcutAdvisor类
先看看 AspectJExpressionPointcutAdvisor 的类图 再了解一下切点(Pointcut)表达式,它指定触发advice的方法,可以精确到返回参数,参数类型,方法名 1 pa ...
- java源码解析之Object类
一.Object类概述 Object类是java中类层次的根,是所有类的基类.在编译时会自动导入.Object中的方法如下: 二.方法详解 Object的方法可以分成两类,一类是被关键字fin ...
- Bulma 源码解析之 .columns 类
{说明} 这一部分的源码内容被我简化了,另外我还额外添加了一个辅助类 is-grow. .columns // 修饰类 &.is-centered justify-content: cente ...
- java源码解析之String类(二)
上一节主要介绍了String类的一些构造方法,主要分为四类 无参构造器:String(),创建一个空字符串"",区别于null字符串,""已经初始化,null并 ...
随机推荐
- 容器centos7安装部署ansible
容器centos7安装部署ansible centos镜像版本及ansible版本 centos:centos7.5.1804 ansible:2.9.11 启动容器并进入容器 docker run ...
- matplotlib常用基础知识
linestyle(ls)线型参数表 常用color(c)参数表 marker标记符号表 plt常用方法表 plt.legend(loc=0)用于显示图例,图例的位置参数loc matplotlib常 ...
- [C#] (原创)一步一步教你自定义控件——01,TrackBar
一.前言 技术没有先进落后之分,只有合不合适. WinForm有着非常多的优点,在使用WinForm久了之后,难免会觉得WinForm自带的某些控件外观上有些许朴素.或者功能上有些不如意,自然而然便想 ...
- 关于tf.cond函数中“正确”与“错误”函数中的普通python语句始终执行的问题
import tensorflow as tf import numpy as np x = tf.constant(2) y = tf.constant(3) global mask0 mask0 ...
- Win10系统安装MySQL Workbench 8
系统:Window10 专业版 MySQL Workbench 8.0.19 下载地址:https://dev.mysql.com/downloads/workbench/8.0.html 点击Dow ...
- MySQL主从同步-原理&实践篇
来源:Onegoleya 简栈文化 什么是mysql的主从复制? MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点.MySQL 默认采用异步复制方式,这样从节点 ...
- Efficient Knowledge Graph Accuracy Evaluation 论文笔记
前言 这篇论文主要讲的是知识图谱正确率的评估,将知识图谱的正确率定义为知识图谱中三元组表述正确的比例.如果要计算知识图谱的正确率,可以用人力一一标注是否正确,计算比例.但是实际上,知识图谱往往很大,不 ...
- 11-Arrays工具类的使用
1.理解:① 定义在java.util包下.② Arrays:提供了很多操作数组的方法. 2.使用: //1.boolean equals(int[] a,int[] b):判断两个数组是否相等. i ...
- 改改Python代码,运行速度还能提升6万倍
这份最新研究指出,在后摩尔定律时代,人类所获得的的算力提升将更大程度上来源于计算堆栈的「顶层」,即软件.算法和硬件架构,这将成为一个新的历史趋势. 很多人学习python,不知道从何学起.很多人学习p ...
- 《RabbitMQ》如何保证消息不被重复消费
一 重复消息 为什么会出现消息重复?消息重复的原因有两个:1.生产时消息重复,2.消费时消息重复. 1.1 生产时消息重复 由于生产者发送消息给MQ,在MQ确认的时候出现了网络波动,生产者没有收到确认 ...