thrift之TTransport层的缓存传输类TBufferedTransport和缓冲基类TBufferBase
本节主要介绍缓冲相关的传输类,缓存的作用就是为了提高读写的效率。Thrift在实现缓存传输的时候首先建立一个缓存的基类,然后需要实现缓存功能的类都可以直接从这个基类继承。下面就详细分析这个基类以及一个具体的实现类。
缓存基类TBufferBase
缓存基类就是让传输类所有的读写函数都提供缓存来提高性能。它在通常情况下采用memcpy来设计和实现快路径的读写访问操作,这些操作函数通常都是小、非虚拟和内联函数。TBufferBase是一个抽象的基类,子类必须实现慢路径的读写函数等操作,慢路径的读写等操作主要是为了在缓存已经满或空的情况下执行。首先看看缓存基类的定义,代码如下:
[cpp]
class TBufferBase : public TVirtualTransport<TBufferBase> {
public:
uint32_t read(uint8_t* buf, uint32_t len) {//读函数
uint8_t* new_rBase = rBase_ + len;//得到需要读到的缓存边界
if (TDB_LIKELY(new_rBase <= rBound_)) {//判断缓存是否有足够的数据可读,采用了分支预测技术
std::memcpy(buf, rBase_, len);//直接内存拷贝
rBase_ = new_rBase;//更新新的缓存读基地址
return len;//返回读取的长度
}
return readSlow(buf, len);//如果缓存已经不能够满足读取长度需要就执行慢读
}
uint32_t readAll(uint8_t* buf, uint32_t len) {
uint8_t* new_rBase = rBase_ + len;//同read函数
if (TDB_LIKELY(new_rBase <= rBound_)) {
std::memcpy(buf, rBase_, len);
rBase_ = new_rBase;
return len;
}
return apache::thrift::transport::readAll(*this, buf, len);//调用父类的
}
void write(const uint8_t* buf, uint32_t len) {//快速写函数
uint8_t* new_wBase = wBase_ + len;//写入后的新缓存基地址
if (TDB_LIKELY(new_wBase <= wBound_)) {//判断缓存是否有足够的空间可以写入
std::memcpy(wBase_, buf, len);//内存拷贝
wBase_ = new_wBase;//更新基地址
return;
}
writeSlow(buf, len);//缓存空间不足就调用慢写函数
}
const uint8_t* borrow(uint8_t* buf, uint32_t* len) {//快速路径借
if (TDB_LIKELY(static_cast<ptrdiff_t>(*len) <= rBound_ - rBase_)) {//判断是否足够借的长度
*len = static_cast<uint32_t>(rBound_ - rBase_);
return rBase_;//返回借的基地址
}
return borrowSlow(buf, len);//不足就采用慢路径借
}
void consume(uint32_t len) {//消费函数
if (TDB_LIKELY(static_cast<ptrdiff_t>(len) <= rBound_ - rBase_)) {//判断缓存是否够消费
rBase_ += len;//更新已经消耗的长度
} else {
throw TTransportException(TTransportException::BAD_ARGS,
"consume did not follow a borrow.");//不足抛异常
}
}
protected:
virtual uint32_t readSlow(uint8_t* buf, uint32_t len) = 0;//慢函数
virtual void writeSlow(const uint8_t* buf, uint32_t len) = 0;
virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) = 0;
TBufferBase()
: rBase_(NULL)
, rBound_(NULL)
, wBase_(NULL)
, wBound_(NULL)
{}//构造函数,把所有的缓存空间设置为NULL
void setReadBuffer(uint8_t* buf, uint32_t len) {//设置读缓存空间地址
rBase_ = buf;//读缓存开始地址
rBound_ = buf+len;//读缓存地址界限
}
void setWriteBuffer(uint8_t* buf, uint32_t len) {//设置写缓存地址空间
wBase_ = buf;//起
wBound_ = buf+len;//边界
}
virtual ~TBufferBase() {}
uint8_t* rBase_;//读从这儿开始
uint8_t* rBound_;//读界限
uint8_t* wBase_;//写开始地址
uint8_t* wBound_;//写界限
};
class TBufferBase : public TVirtualTransport<TBufferBase> {
public:
uint32_t read(uint8_t* buf, uint32_t len) {//读函数
uint8_t* new_rBase = rBase_ + len;//得到需要读到的缓存边界
if (TDB_LIKELY(new_rBase <= rBound_)) {//判断缓存是否有足够的数据可读,采用了分支预测技术
std::memcpy(buf, rBase_, len);//直接内存拷贝
rBase_ = new_rBase;//更新新的缓存读基地址
return len;//返回读取的长度
}
return readSlow(buf, len);//如果缓存已经不能够满足读取长度需要就执行慢读
}
uint32_t readAll(uint8_t* buf, uint32_t len) {
uint8_t* new_rBase = rBase_ + len;//同read函数
if (TDB_LIKELY(new_rBase <= rBound_)) {
std::memcpy(buf, rBase_, len);
rBase_ = new_rBase;
return len;
}
return apache::thrift::transport::readAll(*this, buf, len);//调用父类的
}
void write(const uint8_t* buf, uint32_t len) {//快速写函数
uint8_t* new_wBase = wBase_ + len;//写入后的新缓存基地址
if (TDB_LIKELY(new_wBase <= wBound_)) {//判断缓存是否有足够的空间可以写入
std::memcpy(wBase_, buf, len);//内存拷贝
wBase_ = new_wBase;//更新基地址
return;
}
writeSlow(buf, len);//缓存空间不足就调用慢写函数
}
const uint8_t* borrow(uint8_t* buf, uint32_t* len) {//快速路径借
if (TDB_LIKELY(static_cast<ptrdiff_t>(*len) <= rBound_ - rBase_)) {//判断是否足够借的长度
*len = static_cast<uint32_t>(rBound_ - rBase_);
return rBase_;//返回借的基地址
}
return borrowSlow(buf, len);//不足就采用慢路径借
}
void consume(uint32_t len) {//消
补充:软件开发 , C++ ,