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/ ...
随机推荐
- leetcode91
class Solution { public int numDecodings(String s) { if(s.length()==0){ return 0; } int[] dp = new i ...
- NRF51822之DFU使用手机升级
演示的工程是 [application] nRF51_SDK_10.0.0_dc26b5e\examples\ble_peripheral\ble_app_hrs\pca10028\s110_w ...
- RabbitMQ 端口号解析
转自:https://www.cnblogs.com/liuxingke/articles/9889517.html 端口号解析 12345 - 4369 (epmd), 25672 (Erlang ...
- java 调用apache.commons.codec的包简单实现MD5加密
转自:https://blog.csdn.net/mmd1234520/article/details/70210002/ import java.security.MessageDigest; im ...
- JS计算时间差值
var d = '2016 04 30 11:28:04'; var currentDate = new Date();//当前时间 var endDate = new Date(d); //结束时间 ...
- 从底层谈WebGIS 原理设计与实现(五):WebGIS中通过行列号来换算出多种瓦片的URL 之在线地图
从底层谈WebGIS 原理设计与实现(五):WebGIS中通过行列号来换算出多种瓦片的URL 之在线地图 作者:naaoveGI… 文章来源:naaoveGIS 点击数:2063 更 ...
- HttpClient获取返回类型为JSON或XML的数据
Java_HttpClient获取返回类型为JSON或XML的数据 原创 2017年04月06日 17:38:29 706 HttpClient 获取返回类型为JSON或XML的数据 使用httpco ...
- 提取linux中eth0的IP地址
法1:cut [root@oldboy oldboy]# ifconfig eth0|grep 'inet addr'|cut -d ":" -f2|cut -d " & ...
- UGUI双击事件
经测试在Android.ios平台下无效 using UnityEngine; using UnityEngine.EventSystems; using System.Collections; us ...
- a,b = b,a 换值问题
a = "hello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhe ...