muduo网络库源码复现笔记(十一):base库的StringPiece.h

Muduo网络库简介

muduo 是一个基于 Reactor 模式的现代 C++ 网络库,作者陈硕。它采用非阻塞 IO 模型,基于事件驱动和回调,原生支持多核多线程,适合编写 Linux 服务端多线程网络应用程序。
muduo网络库的核心代码只有数千行,在网络编程技术学习的进阶阶段,muduo是一个非常值得学习的开源库。目前我也是刚刚开始学习这个网络库的源码,希望将这个学习过程记录下来。这个网络库的源码已经发布在GitHub上,可以点击这里阅读。目前Github上这份源码已经被作者用c++11重写,我学习的版本是没有使用c++11版本的。不过二者大同小异,核心思想是没有变化的。点这里可以看我的源代码,如果你对我之前的博客有兴趣,可以点击下面的连接:
muduo网络库源码复现笔记(一):base库的Timestamp.h
muduo网络库源码复现笔记(二):base库的Atomic.h
muduo网络库源码复现笔记(三):base库的Exception.h
muduo网络库源码复现笔记(四):base库的Thread.h和CurrentThread.h
muduo网络库源码复现笔记(五):base库的Mutex.h和Condition.h和CoutntDownLatch.h
muduo网络库源码复现笔记(六):base库的BlockingQueue.h和BoundedBlockingQueue.h
muduo网络库源码复现笔记(七):base库的ThreadPool.h
muduo网络库源码复现笔记(八):base库的Singleton.h
muduo网络库源码复现笔记(九):base库的ThreadLocalSingleton.h
muduo网络库源码复现笔记(十):base库的ThreadLocalSingleton.h

StringPiece.h

muduo使用了StringPiece.h,这是一个谷歌公开的一个头文件,这个文件封装了StringPiece类,这个类不涉及内存拷贝,实现了高效的字符串传递。比如有一个函数它的参数需要同时兼容std::string和const char*,我们一般是这么定义的:

void foo(const string& str);

如果传入很长一个const char*的话,会生成一个较大的string对象,开销比较大。如果你的目的仅仅是读取字符串的值,则可使用

void foo(const StringPiece& str)

通过这个方法可以减小开销。下面是这个类的关键要素的分析。

私有成员

StringPiece有两个私有成员,第一个是const char型指针ptr_,用于帮助字符串的读取,字符串的实际内存与它无关。length_是目的字符串的长度。

  const char*   ptr_;
  int           length_;

成员函数

正如前面所说,ptr_是一个const char型指针,所以字符串的实际内存与它无关,所以不会使用ptr_进行很复杂的操作,故StringPiece的成员函数都很简单。举一个栗子:

void remove_prefix(int n)
	{
			ptr_ += n;
  			length_ -= n;
	}

这个函数是去除读取字符串的头n个字节,只需ptr向后移动,length减去相应的字节数即可。

宏定义实现函数重载

类中使用了一个通过宏定义来实现重载的技巧值得学习一下,代码如下:

#define STRINGPIECE_BINARY_PREDICATE(cmp,auxcmp)                             \
  bool operator cmp (const StringPiece& x) const {                           \
    int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); \
    return ((r auxcmp 0) || ((r == 0) && (length_ cmp x.length_)));          \
  }
  STRINGPIECE_BINARY_PREDICATE(<,  <);
  STRINGPIECE_BINARY_PREDICATE(<=, <);
  STRINGPIECE_BINARY_PREDICATE(>=, >);
  STRINGPIECE_BINARY_PREDICATE(>,  >);
#undef STRINGPIECE_BINARY_PREDICATE

通过宏定义,实现了StringPiece类<,<=,>,>=的比较,当然本质还是比较ptr_指向的字符串。宏定义中cmp就是我们想要进行操作的字符串,aux用于辅助比较。举例来说,如果我们有StringPiece str1(“abcz”),str2(“abcdef”),
std::cout << (str1 < str2) << std:: endl的结果如何呢?由于str1的length_小于str2的length_,那么r = 0;return后的语句里 r < 0不成立,r==0成立但二者length_不相等,所以返回false。其他操作也可如此类推,总之这一段代码技巧性很强。

使用traits提高效率

StringPiece利用了traits和模板特化与偏特化能力,提升了性能。

template<> struct __type_traits {
  typedef __true_type    has_trivial_default_constructor;
  typedef __true_type    has_trivial_copy_constructor;
  typedef __true_type    has_trivial_assignment_operator;
  typedef __true_type    has_trivial_destructor;
  typedef __true_type    is_POD_type;
};

这个是比较高级的c++编程技巧,目前还不会,再深入之后学习来补。

你可能感兴趣的:(muduo)