代码来自陈硕开源代码库 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的更多相关文章

  1. Linux多线程服务端编程:使用muduo C++网络库

    内容推荐本 书主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread.这 ...

  2. 《Linux多线程服务端编程——使用muduo C++网络库》读书笔记

    第一章 线程安全的对象生命期管理 第二章 线程同步精要 第三章 多线程服务器的适用场合与常用编程模型 第四章 C++多线程系统编程精要 1.(P84)11个常用的最基本Pthreads函数: 2个:线 ...

  3. 《Linux 多线程服务端编程:使用 muduo C++ 网络库》电子版上市

    <Linux 多线程服务端编程:使用 muduo C++ 网络库> 电子版已在京东和亚马逊上市销售. 京东购买地址:http://e.jd.com/30149978.html 亚马逊Kin ...

  4. 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

    <Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...

  5. Linux多线程服务端编程一些总结

    能接触这本书是因为上一个项目是用c++开发基于Linux的消息服务器,公司没有使用第三方的网络库,卷起袖子就开撸了.个人因为从业经验较短,主 要负责的是业务方面的编码.本着兴趣自己找了这本书.拿到书就 ...

  6. 《Linux多线程服务端编程》笔记——多线程服务器的适用场合

    如果要在一台多核机器上提供一种服务或执行一个任务,可用的模式有 运行一个单线程的进程 运行一个多线程的进程 运行多个单线程的进程 运行多个多线程的进程 这些模式之间的比较已经是老生常谈,简单地总结 模 ...

  7. 《Linux多线程服务端编程》笔记——线程同步精要

    并发编程基本模型 message passing和shared memory. 线程同步的四项原则 尽量最低限度地共享对象,减少需要同步的场合.如果确实需要,优先考虑共享 immutable 对象. ...

  8. 一、智能指针及线程同步总结------linux多线程服务端编程

    更新2.0 二.多线程及服务器编程总结------linux多线程服务端编程 https://www.cnblogs.com/l2017/p/11335609.html 三.分布式编程总结------ ...

  9. 陈硕 - Linux 多线程服务端编程 - muduo 网络库作者

    http://chenshuo.com/book/ Muduo网络库源码分析(一) EventLoop事件循环(Poller和Channel)http://blog.csdn.net/nk_test/ ...

随机推荐

  1. 16. orcle中replace的用法及例子

    replace 函数用法如下: replace('将要更改的字符串','被替换掉的字符串','替换字符串'); 例子: select  replace ('1,2,3',',',';') from d ...

  2. gulp css 压缩 合并

    //导入工具包 require('node_modules里对应模块') var gulp = require('gulp'), //本地安装gulp所用到的地方 concat = require(' ...

  3. IP Editor IP控件

    HWND hIpEdit; void __fastcall TForm2::FormCreate(TObject *Sender) { hIpEdit = CreateWindow(WC_IPADDR ...

  4. Simple2D-25 精灵动作

    精灵动画作用在精灵上,使精灵表现出动画效果.本文将详细说明如何创建一个简单的动作系统,暂时只有 4 中基本的动作——平移.旋转.缩放和 Alpha 变化,并且这些动作能够自由组合,组成串行动作或并行动 ...

  5. WDA-FPM-4-用OVP做查询跳转到明细

    转载:https://www.cnblogs.com/sapSB/p/10100697.html   FPM四:用OVP做查询跳转到明细 前面做了查询的UIBB配置,在这边可以直接复用,查询的feed ...

  6. POST方式"Content-type"是"application/x-www-form-urlencoded 的请求遇到的问题

    Content-type的方式:application/x-javascript text/xml->xml数据 application/x-javascript->json对象 appl ...

  7. lftp命令详解

    lftp.sh自动上传脚本: #!/bin/bash echo -e "\nScript start at \033[43;35m `date "+%H:%M:%S"` ...

  8. How to Pronounce ‘to the’ in a Sentence

    How to Pronounce ‘to the’ in a Sentence Share Tweet Share Tagged With: The Word THE, TO Reduction St ...

  9. Ansiable Manage MySQL global variables

    mysql_variables - Manage MySQL global variables New in version 1.3. Synopsis Requirements (on host t ...

  10. Eclipse出现错误:The selection cannot be launched,and there are no recent launches

    刚装了eclipse,想写个Java程序测试一下能不能用,结果一run就出现错误,Debug也是同样的错误,错误内容为:the selection cannot be launched,and the ...