-
Notifications
You must be signed in to change notification settings - Fork 1
/
Log.h
157 lines (132 loc) · 3.06 KB
/
Log.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//
// Created by tong on 18-12-29.
//
#ifndef NOOBHTTPPARSER_LOG_H
#define NOOBHTTPPARSER_LOG_H
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <thread>
#include <sstream>
using namespace std;
struct Block{
private:
char* buf;
const size_t size;
size_t cur; // 已用字符数
public:
Block *pre;
bool ready;
explicit Block(size_t size);
~Block();
size_t push(const char* src, size_t sz);
string pop();
bool empty();
};
/**
* 该数据结构内部不含任何同步操作,不是线程安全的。
* **/
class LogBuffer{
private:
Block *front;
Block *back;
size_t blockSize;
public:
explicit LogBuffer(size_t sz = 256);
~LogBuffer();
void push(const string &str);
/**
* 功能:pop出标记为ready的block内的数据
* 返回值:pop出的数据的大小,0表示没有满足条件的block
* **/
string pop(); // 返回pop的字节数, 0表示pop失败
void makeReady();
bool ready();
bool empty();
Block *getBlockAfterBack(); // 获得队尾部的空block,此时block已经加入队列,切为空。
};
class Log {
public:
static Log* getInstance(){
if(!__instance){
__singletonLock.lock();
if(!__instance){
__instance = new Log(5);
}
__singletonLock.unlock();
}
return __instance;
};
template <typename T>
Log& operator <<(T obj){
ostringstream ss;
ss << obj;
if(!ss.str().empty()){
bufLockMtx.lock();
buffer.push(ss.str());
bufLockMtx.unlock();
if(buffer.ready())
condVar.notify_all();
}
return *this;
};
static void setLogFile(const string &s){
if(__filePath.empty()){
__filePath = s;
}
};
private:
struct GC{
~GC(){
if(__instance){
delete __instance;
__instance = nullptr;
}
}
};
static Log *__instance;
static mutex __singletonLock;
static string __filePath;
static GC __gc;
explicit Log(int flushInterval);
~Log();
ostream *fout;
LogBuffer buffer;
mutex bufLockMtx;
condition_variable condVar;
bool running;
chrono::duration<int> flushInterval;
void logThreadFn();
thread logThread;
};
class LogWrap{
public:
LogWrap(): __buffer(__curDate()), __dateSize(__buffer.size()) {
};
~LogWrap(){
if(__buffer.size() > __dateSize){
*Log::getInstance() << __buffer;
}
}
template <typename T>
LogWrap& operator<<(const T &obj){
ostringstream ss;
ss << obj;
__buffer.append(ss.str());
return *this;
}
void setLogFile(const string &s){
Log::setLogFile(s);
};
private:
string __buffer;
size_t __dateSize;
string __curDate();
};
#define LOG LogWrap()
//#define LOG cout
#endif //NOOBHTTPPARSER_LOG_H