Linux多线程服务端编程 使用muduo C++网络库 学习笔记 日志log
代码来自陈硕开源代码库 muduo中
地址是https://github.com/chenshuo/muduo
#pragma once
#include <string>
#define NAMESPACE(X) namespace X {
#define NAMESPACE_END(X) }
NAMESPACE(DEF)
class noncopyable
{
protected:
noncopyable() {}
private:
noncopyable(const noncopyable&) = delete;
void operator=(const noncopyable&) = delete;
};
const int kSmallBuffer = ;
const int kLargeBuffer = * ;
template<int SIZE>
class FixedBuffer : DEF::noncopyable
{
public:
FixedBuffer()
: cur_(data_)
{
setCookie(cookieStart);
}
~FixedBuffer()
{
setCookie(cookieEnd);
}
void append(const char* /*restrict*/ buf, size_t len)
{
// FIXME: append partially
if (static_cast<size_t>(avail()) > len)
{
memcpy(cur_, buf, len);
cur_ += len;
}
}
const char* data() const { return data_; }
int length() const { return static_cast<int>(cur_ - data_); }
// write to data_ directly
char* current() { return cur_; }
int avail() const { return static_cast<int>(end() - cur_); }
void add(size_t len) { cur_ += len; }
void reset() { cur_ = data_; }
void bzero() { ::memset(data_,, sizeof data_); }
void setCookie(void(*cookie)()) { cookie_ = cookie; }
std::string asString() const { return std::string(data_, length()); }
private:
const char* end() const { return data_ + sizeof data_; }
// Must be outline function for cookies.
static void cookieStart() {};
static void cookieEnd() {};
void(*cookie_)();
char data_[SIZE];
char* cur_;
};
class LogStream : DEF::noncopyable
{
typedef LogStream self;
public:
typedef FixedBuffer<kSmallBuffer> Buffer;
self& operator<<(bool v)
{
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<<(long double);
self& operator<<(char v)
{
buffer_.append(&v, );
return *this;
}
// self& operator<<(signed char);
// self& operator<<(unsigned char);
self& operator<<(const char* str)
{
if (str)
{
buffer_.append(str, strlen(str));
}
else
{
buffer_.append("(null)", );
}
return *this;
}
self& operator<<(const unsigned char* str)
{
return operator<<(reinterpret_cast<const char*>(str));
}
self& operator<<(const std::string& v)
{
buffer_.append(v.c_str(), v.size());
return *this;
}
void append(const char* data, int len) { buffer_.append(data, len); }
const Buffer& buffer() const { return buffer_; }
void resetBuffer() { buffer_.reset(); }
private:
template<typename T>
void formatInteger(T);
Buffer buffer_;
static const int kMaxNumericSize = ;
};
class Fmt // : boost::noncopyable
{
public:
template<typename T>
Fmt(const char* fmt, T val);
const char* data() const { return buf_; }
int length() const { return length_; }
private:
char buf_[];
int length_;
};
inline LogStream& operator<<(LogStream& s, const Fmt& fmt)
{
s.append(fmt.data(), fmt.length());
return s;
}
NAMESPACE_END(DEF)
#include "LogStream.h" NAMESPACE(DEF)
const char digits[] = "";
const char* zero = digits + ; const char digitsHex[] = "0123456789ABCDEF"; // Efficient Integer to String Conversions, by Matthew Wilson.
template<typename T>
size_t convert(char buf[], T value)
{
T i = value;
char* p = buf; do
{
int lsd = static_cast<int>(i % );
i /= ;
*p++ = zero[lsd];
} while (i != ); if (value < )
{
*p++ = '-';
}
*p = '\0';
std::reverse(buf, p); return p - buf;
} size_t convertHex(char buf[], uintptr_t value)
{
uintptr_t i = value;
char* p = buf; do
{
int lsd = static_cast<int>(i % );
i /= ;
*p++ = digitsHex[lsd];
} while (i != ); *p = '\0';
std::reverse(buf, p); return p - buf;
} //template class FixedBuffer<kSmallBuffer>;
//template class FixedBuffer<kLargeBuffer>; template<typename T>
void LogStream::formatInteger(T v)
{
if (buffer_.avail() >= kMaxNumericSize)
{
size_t len = convert(buffer_.current(), v);
buffer_.add(len);
}
} LogStream& LogStream::operator<<(short v)
{
*this << static_cast<int>(v);
return *this;
} LogStream& LogStream::operator<<(unsigned short v)
{
*this << static_cast<unsigned int>(v);
return *this;
} LogStream& LogStream::operator<<(int v)
{
formatInteger(v);
return *this;
} LogStream& LogStream::operator<<(unsigned int v)
{
formatInteger(v);
return *this;
} LogStream& LogStream::operator<<(long v)
{
formatInteger(v);
return *this;
} LogStream& LogStream::operator<<(unsigned long v)
{
formatInteger(v);
return *this;
} LogStream& LogStream::operator<<(long long v)
{
formatInteger(v);
return *this;
} LogStream& LogStream::operator<<(unsigned long long v)
{
formatInteger(v);
return *this;
} LogStream& LogStream::operator<<(const void* p)
{
uintptr_t v = reinterpret_cast<uintptr_t>(p);
if (buffer_.avail() >= kMaxNumericSize)
{
char* buf = buffer_.current();
buf[] = '';
buf[] = 'x';
size_t len = convertHex(buf + , v);
buffer_.add(len + );
}
return *this;
} // FIXME: replace this with Grisu3 by Florian Loitsch.
LogStream& LogStream::operator<<(double v)
{
if (buffer_.avail() >= kMaxNumericSize)
{
int len = snprintf(buffer_.current(), kMaxNumericSize, "%.12g", v);
buffer_.add(len);
}
return *this;
} template<typename T>
Fmt::Fmt(const char* fmt, T val)
{
//BOOST_STATIC_ASSERT(boost::is_arithmetic<T>::value == true); length_ = snprintf(buf_, sizeof buf_, fmt, val);
assert(static_cast<size_t>(length_) < sizeof buf_);
} // Explicit instantiations
/*
template Fmt::Fmt(const char* fmt, char); template Fmt::Fmt(const char* fmt, short);
template Fmt::Fmt(const char* fmt, unsigned short);
template Fmt::Fmt(const char* fmt, int);
template Fmt::Fmt(const char* fmt, unsigned int);
template Fmt::Fmt(const char* fmt, long);
template Fmt::Fmt(const char* fmt, unsigned long);
template Fmt::Fmt(const char* fmt, long long);
template Fmt::Fmt(const char* fmt, unsigned long long); template Fmt::Fmt(const char* fmt, float);
template Fmt::Fmt(const char* fmt, double);
*/ NAMESPACE_END(DEF)
// LogStreamTest.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include "LogStream.h"
#include <chrono>
#include <sstream>
#include <iostream>
using namespace DEF; const int N = ; template<typename T>
void benchPrintf(const char* fmt)
{
char buf[];
std::chrono::steady_clock::time_point t1 =
std::chrono::steady_clock::steady_clock::now(); for (int i = ; i < N; ++i)
snprintf(buf, sizeof buf, fmt, (T)(i)); std::chrono::steady_clock::time_point t2 =
std::chrono::steady_clock::steady_clock::now();
std::chrono::duration<double> time_span =
std::chrono::duration_cast<std::chrono::duration<double>> (t2 - t1);
std::cout << "benchPrintf took " << time_span.count() << std::endl<< std::endl;
} template<typename T>
void benchStringStream()
{
std::chrono::steady_clock::time_point t1 =
std::chrono::steady_clock::steady_clock::now(); std::ostringstream os; for (int i = ; i < N; ++i)
{
os << (T)(i);
os.seekp(, std::ios_base::beg);
}
std::chrono::steady_clock::time_point t2 =
std::chrono::steady_clock::steady_clock::now();
std::chrono::duration<double> time_span =
std::chrono::duration_cast<std::chrono::duration<double>> (t2 - t1);
std::cout << "benchStringStream took " <<time_span.count() << std::endl << std::endl;
} template<typename T>
void benchLogStream()
{
std::chrono::steady_clock::time_point t1 =
std::chrono::steady_clock::steady_clock::now();
LogStream os;
for (int i = ; i < N; ++i)
{
os << (T)(i);
os.resetBuffer();
}
std::chrono::steady_clock::time_point t2 =
std::chrono::steady_clock::steady_clock::now();
std::chrono::duration<double> time_span =
std::chrono::duration_cast<std::chrono::duration<double>> (t2 - t1);
std::cout << "benchLogStream took " << time_span.count() << std::endl << std::endl;
} void PrintTest()
{
LogStream os;
int i = ;
os << "this is a test " << 3.14159265 << 's' << " a " << &i << " " << ;
os << "this is a test " << 3.14159265 << 's' << " a " << &i << " " << ;
os << "this is a test " << 3.14159265 << 's' << " a " << &i << " " << ;
os << "this is a test " << 3.14159265 << 's' << " a " << &i << " " << ;
os << "this is a test " << 3.14159265 << 's' << " a " << &i << " " << ;
os << "this is a test " << 3.14159265 << 's' << " a " << &i << " " << ;
os << "this is a test " << 3.14159265 << 's' << " a " << &i << " " << ;
std::cout << os.buffer().data() << std::endl;
} void Bench()
{
benchPrintf<int>("%d"); puts("int");
benchPrintf<int>("%d");
benchStringStream<int>();
benchLogStream<int>(); puts("double");
benchPrintf<double>("%.12g");
benchStringStream<double>();
benchLogStream<double>(); puts("int64_t");
benchPrintf<int64_t>("%ll");
benchStringStream<int64_t>();
benchLogStream<int64_t>(); puts("void*");
benchPrintf<void*>("%p");
benchStringStream<void*>();
benchLogStream<void*>();
} int main()
{
Bench();
PrintTest(); return ;
}
主要是在内存中自己开辟了一块内存 然后对基本数据的输入 进行了定义
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 char* str);
self& operator<<(const unsigned char* str);
self& operator<<(const std::string& v);
相比C++自带的STREAM 没有继承及太多改写
在胜任基本的输入输出任务 自然效率会高一些
然后基本的输出方面 需要记录写入的时间 日志级别和进程ID和名字等
采用生产消费者模式 多个产生日志的生产者产生日志投入队列,然后仅仅一个消费者写入BUFFER
BUFFER采用两个缓存写入日志进行替换,一个接受消费者写入 一个将日志序列化到磁盘中。
如果速度实在太快 可能考虑再创建一个到两个BUFFER 实践中这种情况应该极小概率发生。
然后日志的根据时间和文件的体积的临界值可自动创建新的日志文件
Linux多线程服务端编程 使用muduo C++网络库 学习笔记 日志log的更多相关文章
- Linux多线程服务端编程:使用muduo C++网络库
内容推荐本 书主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread.这 ...
- 《Linux多线程服务端编程——使用muduo C++网络库》读书笔记
第一章 线程安全的对象生命期管理 第二章 线程同步精要 第三章 多线程服务器的适用场合与常用编程模型 第四章 C++多线程系统编程精要 1.(P84)11个常用的最基本Pthreads函数: 2个:线 ...
- 《Linux 多线程服务端编程:使用 muduo C++ 网络库》电子版上市
<Linux 多线程服务端编程:使用 muduo C++ 网络库> 电子版已在京东和亚马逊上市销售. 京东购买地址:http://e.jd.com/30149978.html 亚马逊Kin ...
- 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册
<Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...
- Linux多线程服务端编程一些总结
能接触这本书是因为上一个项目是用c++开发基于Linux的消息服务器,公司没有使用第三方的网络库,卷起袖子就开撸了.个人因为从业经验较短,主 要负责的是业务方面的编码.本着兴趣自己找了这本书.拿到书就 ...
- 《Linux多线程服务端编程》笔记——多线程服务器的适用场合
如果要在一台多核机器上提供一种服务或执行一个任务,可用的模式有 运行一个单线程的进程 运行一个多线程的进程 运行多个单线程的进程 运行多个多线程的进程 这些模式之间的比较已经是老生常谈,简单地总结 模 ...
- 《Linux多线程服务端编程》笔记——线程同步精要
并发编程基本模型 message passing和shared memory. 线程同步的四项原则 尽量最低限度地共享对象,减少需要同步的场合.如果确实需要,优先考虑共享 immutable 对象. ...
- 一、智能指针及线程同步总结------linux多线程服务端编程
更新2.0 二.多线程及服务器编程总结------linux多线程服务端编程 https://www.cnblogs.com/l2017/p/11335609.html 三.分布式编程总结------ ...
- 陈硕 - Linux 多线程服务端编程 - muduo 网络库作者
http://chenshuo.com/book/ Muduo网络库源码分析(一) EventLoop事件循环(Poller和Channel)http://blog.csdn.net/nk_test/ ...
随机推荐
- django-插件django REST framework,返回序列化的数据
官网: http://www.django-rest-framework.org 1.安装 pip install djangorestframework 2.在setting.py中注册app 中添 ...
- 5. Java中序列化的serialVersionUID作用
Java序列化是将一个对象编码成一个字节流,反序列化将字节流编码转换成一个对象. 序列化是Java中实现持久化存储的一种方法:为数据传输提供了线路级对象表示法. Java的序列化机制是通过在运行时判断 ...
- Using Celery with Django
参考1: http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html#using-celery-with-d ...
- myeclipse配置gradle插件
首先,到Gradle官网下载最新版的gradle,已经到了2.13了 下载地址是 http://gradle.org/gradle-download/ 下载下来解压到任意目录 然后配置Windows环 ...
- z-index层级顺序 opacity透明度 display: none 模态框实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- OpenSL ES 查询设备支持的SL Profiles
opensl es 提供了三种类型:分别是 SL_PROFILES_PHONE(手机):SL_PROFILES_MUSIC(音乐); SL_PROFILES_GAME (游戏). 如果你使用的手机的开 ...
- 复制CentOS虚拟机网络配置
复制出来的CentOS虚拟机,网络需要重新配置. 卸载原来的VMware网卡,重新启用一块新的网卡,网卡网段要匹配. ifconfig -a 查看当前启用网卡的mac地址 编辑/etc/ude ...
- 01Tensorflow学习之Tensorflow基本介绍
1 tensorflow简介 TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理.Tensor(张量)意味着N维数组,Flow(流)意味着基 ...
- 一文看懂Stacking!(含Python代码)
一文看懂Stacking!(含Python代码) https://mp.weixin.qq.com/s/faQNTGgBZdZyyZscdhjwUQ
- tensorflow生成随机数的操作 tf.random_normal & tf.random_uniform & tf.truncated_normal & tf.random_shuffle
tf.random_normal 从正态分布输出随机值. random_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name ...