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/ ...
随机推荐
- 2018-2019-2 《网络对抗技术》Exp6 信息搜集与漏洞扫描 Week9 20165233
Exp6 信息搜集与漏洞扫描 目录 一.基础问题 二.实验步骤 实验点一:各种搜索技巧的应用 实验点二:DNS IP注册信息的查询 实验点三:基本的扫描技术:主机发现.端口扫描.OS及服务版本探测.具 ...
- 2.纯 CSS 创作一个矩形旋转 loader 特效
原文地址:2.纯 CSS 创作一个矩形旋转 loader 特效 扩展后地址:https://scrimba.com/c/cNJVWUR 扩展地址:https://codepen.io/pen/ HT ...
- 25. oracle密码过期解决
解决方法: 1.连接到oracle会自动提示修改数据库密码; 2.如果要设置为数据库密码不过期,可以直接修改: 查看:select * from dba_profiles where profile= ...
- mysql 解除安全模式
问题:rror Code: 1175. You are using safe update mode and you tried to update a table without a WHERE t ...
- FireFox 书签 缓存 路径设置
English ver down https://www.mozilla.org/en-US/firefox/new/ add ons https://addons.mozilla.org/en-US ...
- Firefox内存占用过高解决方法
刚开始使用firefox火狐浏览器的时候,你会发现firefox占用内存大,CPU占用率高,打开网页停顿等问题,其实这些是因为firefox没有进行优化,默认设置是标准的设置的原因,解决方法如下: 一 ...
- 机器学习入门-概率阈值的逻辑回归对准确度和召回率的影响 lr.predict_proba(获得预测样本的概率值)
1.lr.predict_proba(under_text_x) 获得的是正负的概率值 在sklearn逻辑回归的计算过程中,使用的是大于0.5的是正值,小于0.5的是负值,我们使用使用不同的概率结 ...
- Maven 异常
Archive for required library: '*****org/javassist/javassist/3.21.0-GA/javassist-3.21.0-GA.jar' in pr ...
- CAD2010安装说明
1. 2. 3. 4. 5. . 提供算号服务(也就是付费才能获得的注册码)... 不会的可以问的撒....
- hive 显示分区
显示某一张表的分区值 show partitions table_name;