1 muduo网络库的目录结构
/muduo$ tree ./ -L 2
./
├── BUILD.bazel
├── build.sh
├── ChangeLog
├── ChangeLog2
├── CMakeLists.txt
├── contrib
│?? ├── CMakeLists.txt
│?? ├── hiredis
│?? └── thrift
├── muduo
├── README
└── WORKSPACE
……
muduo库主体代码
├── muduo
│ ├── base
│ └── net
├── inspect
├── poller
├── http
├── protobuf
├── protorpc
base 目录
chen@ecs-213609:~/muduo/muduo/base$ tree ./ -L 1
./
├── AsyncLogging.cc
├── AsyncLogging.h
├── Atomic.h
├── BlockingQueue.h
├── BoundedBlockingQueue.h
├── BUILD.bazel
├── CMakeLists.txt
├── Condition.cc
├── Condition.h
├── copyable.h
├── CountDownLatch.cc
├── CountDownLatch.h
├── CurrentThread.cc
├── CurrentThread.h
├── Date.cc
├── Date.h
├── Exception.cc
├── Exception.h
├── FileUtil.cc
├── FileUtil.h
├── GzipFile.h
├── LogFile.cc
├── LogFile.h
├── Logging.cc
├── Logging.h
├── LogStream.cc
├── LogStream.h
├── Mutex.h
├── noncopyable.h
├── ProcessInfo.cc
├── ProcessInfo.h
├── Singleton.h
├── StringPiece.h
├── tests
├── Thread.cc
├── Thread.h
├── ThreadLocal.h
├── ThreadLocalSingleton.h
├── ThreadPool.cc
├── ThreadPool.h
├── Timestamp.cc
├── Timestamp.h
├── TimeZone.cc
├── TimeZone.h
├── Types.h
└── WeakCallback.h
base都是可以提取出来直接使用的一些工具类
base/tests 下是一些测试用例
执行./build.sh 会在上层目录生成一个build/Debug目录
有需要可以把shell 脚本给改掉
set -x
SOURCE_DIR=`pwd`
BUILD_DIR=${BUILD_DIR:-./build}
BUILD_NO_EXAMPLES=${BUILD_NO_EXAMPLES:-0}
mkdir -p $BUILD_DIR/$BUILD_TYPE \
&& cd $BUILD_DIR/$BUILD_TYPE \
&& cmake $SOURCE_DIR \
&& make $*
rm CMakeCache.txt
rm CMakeFiles -r
rm cmake_install.cmake
删掉一些冗余文件和Debug 目录的一些信息,只做最简单的应用输出
build/release-cpp11/bin 下会生成可执行文件
tree ./ -L 1
./
├── CMakeCache.txt
├── CMakeFiles
├── cmake_install.cmake
├── dep.dot
├── dep.dot.muduo_base
├── dep.dot.muduo_base.dependers
├── lib
├── Makefile
└── muduo
单独编译Timestamp.cc 会生成muduo_base 静态库
set(base_SRCS
Timestamp.cc
)
add_library(muduo_base ${base_SRCS})
target_link_libraries(muduo_base pthread rt)
install(TARGETS muduo_base DESTINATION lib)
file(GLOB HEADERS "*.h")
install(FILES ${HEADERS} DESTINATION include/muduo/base)
2 Timestamp时间处理
copyable.h //默认可以拷贝的类,空基类,值语义
#ifndef MUDUO_BASE_COPYABLE_H
#define MUDUO_BASE_COPYABLE_H
namespace muduo {
class copyable {
protected:
copyable() = default;
~copyable() = default;
};
}
#endif
比如 Timestamp 类 处理时间的
class Timestamp : public muduo::copyable,
public boost::less_than_comparable<Timestamp>
{
inline bool operator<(Timestamp lhs, Timestamp rhs)
{
return lhs.microSecondsSinceEpoch() < rhs.microSecondsSinceEpoch();
}
}
继承了该类,要求实现了<,可以自动实现>,<=,>= 的运算符重载,模板元编程的思想。
static const int muduo::Timestamp::microSecondsSinceEpoch_
priavte : int64_t muduo::Timestamp::kMicroSecondsPerSecond
muduo::Timestamp::valid muduo::Timestamp::toString()const
muduo::Timestamp::toFormattedString() const
muduo::Timestamp::Timestamp muduo::Timestamp::Timestamp()
muduo::Timestamp::swap muduo::Timestamp::secondsSinceEpoch()const
muduo::Timestamp::now()
muduo::Timestamp(int64_t microSecondsSinceEpoch)
muduo::Timestamp::invalid()
void swap(Timestamp& that)
{
std::swap(microSecondsSinceEpoch_, that.microSecondsSinceEpoch_);
}
inline double timeDifference(Timestamp high, Timestamp low)
inline Timestamp addTime(Timestamp timestamp, double seconds)
Timestamp Timestamp::now()
string Timestamp::toString() const
{
char buf[32] = {0};
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / kMicroSecondsPerSecond);
int microseconds = static_cast<int>(microSecondsSinceEpoch_ % kMicroSecondsPerSecond);
struct tm tm_time;
gmtime_r(&seconds, &tm_time);
snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d",
tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec,
microseconds);
return buf;
}
toString()
string Timestamp::toString() const
{
char buf[32] = {0};
int64_t seconds = microSecondsSinceEpoch_ / kMicroSecondsPerSecond;
int64_t microseconds = microSecondsSinceEpoch_ % kMicroSecondsPerSecond;
snprintf(buf, sizeof(buf)-1, "%" ".%06" PRId64 "", seconds, microseconds);
return buf;
}
Timestamp_unittest.cc
#include <muduo/base/Timestamp.h>
#include <vector>
#include <stdio.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <ctype.h>
using muduo::Timestamp;
void passByConstReference(const Timestamp& x)
{
printf("%s\n", x.toString().c_str());
}
void passByValue(Timestamp x)
{
int a = 0;
printf("%s\n", x.toString().c_str());
}
void benchmark()
{
const int kNumber = 1000*1000;
std::vector<Timestamp> stamps;
stamps.reserve(kNumber);
for (int i = 0; i < kNumber; ++i)
{
stamps.push_back(Timestamp::now());
}
printf("%s\n", stamps.front().toString().c_str());
printf("%s\n", stamps.back().toString().c_str());
printf("%f\n", timeDifference(stamps.back(), stamps.front()));
int increments[100] = { 0 };
int64_t start = stamps.front().microSecondsSinceEpoch();
for (int i = 1; i < kNumber; ++i)
{
int64_t next = stamps[i].microSecondsSinceEpoch();
int64_t inc = next - start;
start = next;
if (inc < 0)
{
printf("reverse!\n");
}
else if (inc < 100)
{
++increments[inc];
}
else
{
printf("big gap %d\n", static_cast<int>(inc));
}
}
for (int i = 0; i < 100; ++i)
{
printf("%2d: %d\n", i, increments[i]);
}
}
int main()
{
Timestamp now(Timestamp::now());
printf("%s\n", now.toString().c_str());
passByValue(now);
passByConstReference(now);
benchmark();
}
在包含的type.h 里面,提供了两个类型转换的函数
隐式转换和向下转换
template<typename To, typename From>
inline To implicit_cast(From const &f) {
return f;
}
template<typename To, typename From>
inline To down_cast(From* f) {
if (false) {
implicit_cast<From*, To>(0);
}
#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
assert(f == NULL || dynamic_cast<To>(f) != NULL);
#endif
return static_cast<To>(f);
}
3 GCC的CAS
GCC4.1+版本中支持CAS的原子操作(完整的原子操作可参看 GCC Atomic Builtins)
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, …)
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, …)
AtomicIntegerT 一个整数得原子性操作
volatile T value_ 系统总是重新从它所在得内存读取数据,而不是使用保存在寄存器中得备份。即使他前一条指令刚刚读取过数据被保存。防止编译器对该操作优化,需要每次精准读值。
T get()
{
return __sync_val_compare_and_swap(&value_, 0, 0);
}
T getAndAdd(T x)
{
return __sync_fetch_and_add(&value_, x);
}
T incrementAndGet()
{
return addAndGet(1);
}
T getAndSet(T newValue)
{
return __sync_lock_test_and_set(&value_, newValue);
}
typedef detail::AtomicIntegerT<int32_t> AtomicInt32;
typedef detail::AtomicIntegerT<int64_t> AtomicInt64;
4 Exception 类实现
用于保存栈帧地址
Exception::Exception(const char* msg)
: message_(msg)
{
fillStackTrace();
}
void Exception::fillStackTrace()
{
const int len = 200;
void* buffer[len];
int nptrs = ::backtrace(buffer, len);
char** strings = ::backtrace_symbols(buffer, nptrs);
if (strings)
{
for (int i = 0; i < nptrs; ++i)
{
stack_.append(strings[i]);
stack_.push_back('\n');
}
free(strings);
}
}
Exception_test.cc 使用实例
能够把异常的调用堆栈打印出来
int main()
{
try
{
foo();
}
catch (const muduo::Exception& ex)
{
printf("reason: %s\n", ex.what());
printf("stack trace: %s\n", ex.stackTrace());
}
}
5 Thread类的一些细节
thread_test.cc
int main()
{
printf("pid=%d, tid=%d\n", ::getpid(), muduo::CurrentThread::tid());
}
打印当前工作线程的时候
CurrentThread::tid()
extern __thread int t_cachedTid;
inline int tid()
{
if (t_cachedTid == 0)
{
cacheTid();
}
return t_cachedTid;
}
void CurrentThread::cacheTid()
{
if (t_cachedTid == 0)
{
t_cachedTid = detail::gettid();
int n = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid);
assert(n == 6); (void) n;
}
}
pid_t gettid()
pid_t gettid()
{
return static_cast<pid_t>(::syscall(SYS_gettid));
}
|