添加win测试程序

This commit is contained in:
xiongziliang
2017-12-13 14:18:10 +08:00
parent 34176f0e2b
commit f347bec3cb
100 changed files with 10477 additions and 0 deletions

View File

@@ -0,0 +1,246 @@
//
// Socket.h
// xzl
//
// Created by xzl on 16/4/13.
//
#ifndef Socket_h
#define Socket_h
#include <memory>
#include <string>
#include <deque>
#include <mutex>
#include <atomic>
#include <functional>
#include "Util/util.h"
#include "Util/TimeTicker.h"
#include "Poller/Timer.h"
#include "Network/sockutil.h"
#include "Thread/spin_mutex.h"
using namespace std;
using namespace ZL::Util;
using namespace ZL::Poller;
using namespace ZL::Thread;
namespace ZL {
namespace Network {
#if defined(MSG_NOSIGNAL)
#define FLAG_NOSIGNAL MSG_NOSIGNAL
#else
#define FLAG_NOSIGNAL 0
#endif //MSG_NOSIGNAL
#if defined(MSG_MORE)
#define FLAG_MORE MSG_MORE
#else
#define FLAG_MORE 0
#endif //MSG_MORE
#if defined(MSG_DONTWAIT)
#define FLAG_DONTWAIT MSG_DONTWAIT
#else
#define FLAG_DONTWAIT 0
#endif //MSG_DONTWAIT
#define TCP_DEFAULE_FLAGS (FLAG_NOSIGNAL | FLAG_DONTWAIT)
#define UDP_DEFAULE_FLAGS (FLAG_NOSIGNAL | FLAG_DONTWAIT)
#define MAX_SEND_PKT (256)
#if defined(__APPLE__)
#import "TargetConditionals.h"
#if TARGET_IPHONE_SIMULATOR
#define OS_IPHONE
#elif TARGET_OS_IPHONE
#define OS_IPHONE
#endif
#endif //__APPLE__
typedef enum {
Err_success = 0, //成功
Err_eof, //eof
Err_timeout, //超时
Err_refused,
Err_dns,
Err_other,
} ErrCode;
class SockException: public std::exception {
public:
SockException(ErrCode _errCode = Err_success, const string &_errMsg = "") {
errMsg = _errMsg;
errCode = _errCode;
}
void reset(ErrCode _errCode, const string &_errMsg) {
errMsg = _errMsg;
errCode = _errCode;
}
virtual const char* what() const noexcept {
return errMsg.c_str();
}
ErrCode getErrCode() const {
return errCode;
}
operator bool() const{
return errCode != Err_success;
}
private:
string errMsg;
ErrCode errCode;
};
class SockFD
{
public:
typedef std::shared_ptr<SockFD> Ptr;
SockFD(int sock){
_sock = sock;
}
virtual ~SockFD(){
::shutdown(_sock, SHUT_RDWR);
#if defined (OS_IPHONE)
unsetSocketOfIOS(_sock);
#endif //OS_IPHONE
int fd = _sock;
EventPoller::Instance().delEvent(fd,[fd](bool){
close(fd);
});
}
void setConnected(){
#if defined (OS_IPHONE)
setSocketOfIOS(_sock);
#endif //OS_IPHONE
}
int rawFd() const{
return _sock;
}
private:
int _sock;
#if defined (OS_IPHONE)
void *readStream=NULL;
void *writeStream=NULL;
bool setSocketOfIOS(int socket);
void unsetSocketOfIOS(int socket);
#endif //OS_IPHONE
};
class Socket: public std::enable_shared_from_this<Socket> {
public:
class Buffer {
public:
typedef std::shared_ptr<Buffer> Ptr;
Buffer(uint32_t size) {
_size = size;
_data = new char[size];
}
virtual ~Buffer() {
delete[] _data;
}
const char *data() const {
return _data;
}
uint32_t size() const {
return _size;
}
private:
friend class Socket;
char *_data;
uint32_t _size;
};
typedef std::shared_ptr<Socket> Ptr;
typedef function<void(const Buffer::Ptr &buf, struct sockaddr *addr)> onReadCB;
typedef function<void(const SockException &err)> onErrCB;
typedef function<void(Socket::Ptr &sock)> onAcceptCB;
typedef function<bool()> onFlush;
Socket();
virtual ~Socket();
int rawFD() const{
SockFD::Ptr sock;
{
lock_guard<spin_mutex> lck(_mtx_sockFd);
sock = _sockFd;
}
if(!sock){
return -1;
}
return sock->rawFd();
}
void connect(const string &url, uint16_t port, onErrCB &&connectCB, int timeoutSec = 5);
bool listen(const uint16_t port, const char *localIp = "0.0.0.0", int backLog = 1024);
bool bindUdpSock(const uint16_t port, const char *localIp = "0.0.0.0");
void setOnRead(const onReadCB &cb);
void setOnErr(const onErrCB &cb);
void setOnAccept(const onAcceptCB &cb);
void setOnFlush(const onFlush &cb);
int send(const char *buf, int size = 0,int flags = TCP_DEFAULE_FLAGS);
int send(const string &buf,int flags = TCP_DEFAULE_FLAGS);
int sendTo(const char *buf, int size, struct sockaddr *peerAddr,int flags = UDP_DEFAULE_FLAGS);
int sendTo(const string &buf, struct sockaddr *peerAddr,int flags = UDP_DEFAULE_FLAGS);
bool emitErr(const SockException &err);
void enableRecv(bool enabled);
string get_local_ip();
uint16_t get_local_port();
string get_peer_ip();
uint16_t get_peer_port();
void setSendPktSize(uint32_t iPktSize){
_iMaxSendPktSize = iPktSize;
}
private:
mutable spin_mutex _mtx_sockFd;
SockFD::Ptr _sockFd;
//send buffer
recursive_mutex _mtx_sendBuf;
deque<string> _sendPktBuf;
deque<struct sockaddr> _udpSendPeer;
/////////////////////
std::shared_ptr<Timer> _conTimer;
struct sockaddr _peerAddr;
spin_mutex _mtx_read;
spin_mutex _mtx_err;
spin_mutex _mtx_accept;
spin_mutex _mtx_flush;
onReadCB _readCB;
onErrCB _errCB;
onAcceptCB _acceptCB;
onFlush _flushCB;
Ticker _flushTicker;
int _lastSendFlags = TCP_DEFAULE_FLAGS;
uint32_t _iMaxSendPktSize = MAX_SEND_PKT;
atomic_bool _enableRecv;
void closeSock();
bool setPeerSock(int fd, struct sockaddr *addr);
bool attachEvent(const SockFD::Ptr &pSock,bool isUdp = false);
int onAccept(const SockFD::Ptr &pSock,int event);
int onRead(const SockFD::Ptr &pSock,bool mayEof=true);
void onError(const SockFD::Ptr &pSock);
int realSend(const string &buf, struct sockaddr *peerAddr,int flags);
int onWrite(const SockFD::Ptr &pSock, bool bMainThread,int flags,bool isUdp);
void onConnected(const SockFD::Ptr &pSock, const onErrCB &connectCB);
void onFlushed(const SockFD::Ptr &pSock);
void startWriteEvent(const SockFD::Ptr &pSock);
void stopWriteEvent(const SockFD::Ptr &pSock);
bool sendTimeout(bool isUdp);
SockFD::Ptr makeSock(int sock){
return std::make_shared<SockFD>(sock);
}
static SockException getSockErr(const SockFD::Ptr &pSock,bool tryErrno=true);
};
} // namespace Network
} // namespace ZL
#endif /* Socket_h */

View File

@@ -0,0 +1,106 @@
/*
* TcpClient.h
*
* Created on: 2017年2月13日
* Author: xzl
*/
#ifndef SRC_NETWORK_TCPCLIENT_H_
#define SRC_NETWORK_TCPCLIENT_H_
#include <memory>
#include <functional>
#include "Socket.h"
#include "Util/TimeTicker.h"
#include "Thread/WorkThreadPool.h"
#include "Thread/spin_mutex.h"
using namespace std;
using namespace ZL::Util;
using namespace ZL::Thread;
namespace ZL {
namespace Network {
class TcpClient : public std::enable_shared_from_this<TcpClient> {
public:
typedef std::shared_ptr<TcpClient> Ptr;
TcpClient();
virtual ~TcpClient();
protected:
void startConnect(const string &strUrl, uint16_t iPort, int iTimeOutSec = 3);
void shutdown();
virtual int send(const string &str);
virtual int send(const char *str, int len);
bool alive() {
lock_guard<spin_mutex> lck(m_mutex);
return m_pSock.operator bool();
}
string get_local_ip() {
decltype(m_pSock) sockTmp;
{
lock_guard<spin_mutex> lck(m_mutex);
sockTmp = m_pSock;
}
if(!sockTmp){
return "";
}
return sockTmp->get_local_ip();
}
uint16_t get_local_port() {
decltype(m_pSock) sockTmp;
{
lock_guard<spin_mutex> lck(m_mutex);
sockTmp = m_pSock;
}
if(!sockTmp){
return 0;
}
return sockTmp->get_local_port();
}
string get_peer_ip() {
decltype(m_pSock) sockTmp;
{
lock_guard<spin_mutex> lck(m_mutex);
sockTmp = m_pSock;
}
if(!sockTmp){
return "";
}
return sockTmp->get_peer_ip();
}
uint16_t get_peer_port() {
decltype(m_pSock) sockTmp;
{
lock_guard<spin_mutex> lck(m_mutex);
sockTmp = m_pSock;
}
if(!sockTmp){
return 0;
}
return sockTmp->get_peer_port();
}
uint64_t elapsedTime();
//链接成功后客户端将绑定一个后台线程并且onConnect/onRecv/onSend/onErr事件将在该后台线程触发
virtual void onConnect(const SockException &ex) {}
virtual void onRecv(const Socket::Buffer::Ptr &pBuf) {}
virtual void onSend() {}
virtual void onErr(const SockException &ex) {}
Socket::Ptr m_pSock;
private:
Ticker m_ticker;
spin_mutex m_mutex;
void onSockConnect(const SockException &ex);
void onSockRecv(const Socket::Buffer::Ptr &pBuf);
void onSockSend();
void onSockErr(const SockException &ex);
};
} /* namespace Network */
} /* namespace ZL */
#endif /* SRC_NETWORK_TCPCLIENT_H_ */

View File

@@ -0,0 +1,64 @@
/*
* Session.h
*
* Created on: 2015年10月27日
* Author: root
*/
#ifndef SERVER_LIMITEDSESSION_H_
#define SERVER_LIMITEDSESSION_H_
#include <memory>
#include "Util/logger.h"
#include "TcpSession.h"
using namespace std;
using namespace ZL::Util;
namespace ZL {
namespace Network {
template<int MaxCount>
class TcpLimitedSession: public TcpSession {
public:
TcpLimitedSession(const std::shared_ptr<ThreadPool> &_th, const Socket::Ptr &_sock) :
TcpSession(_th,_sock) {
lock_guard<recursive_mutex> lck(stackMutex());
static uint64_t maxSeq(0);
sessionSeq = maxSeq++;
auto &stack = getStack();
stack.emplace(this);
if(stack.size() > MaxCount){
auto it = stack.begin();
(*it)->safeShutdown();
stack.erase(it);
WarnL << "超过TCP个数限制:" << MaxCount;
}
}
virtual ~TcpLimitedSession() {
lock_guard<recursive_mutex> lck(stackMutex());
getStack().erase(this);
}
private:
uint64_t sessionSeq; //会话栈顺序
struct Comparer {
bool operator()(TcpLimitedSession *x, TcpLimitedSession *y) const {
return x->sessionSeq < y->sessionSeq;
}
};
static recursive_mutex &stackMutex(){
static recursive_mutex mtx;
return mtx;
}
//RTSP会话栈,先创建的在前面
static set<TcpLimitedSession *, Comparer> &getStack(){
static set<TcpLimitedSession *, Comparer> stack;
return stack;
}
};
} /* namespace Session */
} /* namespace ZL */
#endif /* SERVER_LIMITEDSESSION_H_ */

View File

@@ -0,0 +1,134 @@
/*
* TcpServer.h
*
* Created on: 2016年8月9日
* Author: xzl
*/
#ifndef TCPSERVER_TCPSERVER_H_
#define TCPSERVER_TCPSERVER_H_
#include <memory>
#include <exception>
#include <functional>
#include "Socket.h"
#include "Util/util.h"
#include "Util/uv_errno.h"
#include "Util/logger.h"
#include "Poller/Timer.h"
#include "Thread/semaphore.h"
#include "Thread/WorkThreadPool.h"
using namespace std;
using namespace ZL::Util;
using namespace ZL::Poller;
using namespace ZL::Thread;
namespace ZL {
namespace Network {
template<typename Session>
class TcpServer {
public:
typedef std::shared_ptr<TcpServer> Ptr;
TcpServer() {
socket.reset(new Socket());
sessionMap.reset(new typename decltype(sessionMap)::element_type);
}
~TcpServer() {
TraceL << "start clean...";
timer.reset();
socket.reset();
typename decltype(sessionMap)::element_type copyMap;
sessionMap->swap(copyMap);
for (auto it = copyMap.begin(); it != copyMap.end(); ++it) {
auto session = it->second;
it->second->async_first( [session]() {
session->onError(SockException(Err_other,"Tcp server shutdown!"));
});
}
TraceL << "clean completed!";
}
void start(uint16_t port, const std::string& host = "0.0.0.0", uint32_t backlog = 1024) {
bool success = socket->listen(port, host.c_str(), backlog);
if (!success) {
string err = (StrPrinter << "listen on " << host << ":" << port << "] failed:" << get_uv_errmsg(true)).operator <<(endl);
throw std::runtime_error(err);
}
socket->setOnAccept( bind(&TcpServer::onAcceptConnection, this, placeholders::_1));
timer.reset(new Timer(2, [this]()->bool {
this->onManagerSession();
return true;
}));
InfoL << "TCP Server listening on " << host << ":" << port;
}
private:
Socket::Ptr socket;
std::shared_ptr<Timer> timer;
std::shared_ptr<std::unordered_map<Socket *, std::shared_ptr<Session> > > sessionMap;
void onAcceptConnection(const Socket::Ptr & sock) {
// 接收到客户端连接请求
auto session(std::make_shared<Session>(WorkThreadPool::Instance().getWorkThread(), sock));
auto sockPtr(sock.get());
auto sessionMapTmp(sessionMap);
weak_ptr<Session> weakSession(session);
sessionMapTmp->emplace(sockPtr, session);
// 会话接收数据事件
sock->setOnRead([weakSession](const Socket::Buffer::Ptr &buf, struct sockaddr *addr){
//获取会话强应用
auto strongSession=weakSession.lock();
if(!strongSession) {
//会话对象已释放
return;
}
//在会话线程中执行onRecv操作
strongSession->async([weakSession,buf]() {
auto strongSession=weakSession.lock();
if(!strongSession) {
return;
}
strongSession->onRecv(buf);
});
});
//会话接收到错误事件
sock->setOnErr([weakSession,sockPtr,sessionMapTmp](const SockException &err){
//获取会话强应用
auto strongSession=weakSession.lock();
//移除掉会话
sessionMapTmp->erase(sockPtr);
if(!strongSession) {
//会话对象已释放
return;
}
//在会话线程中执行onError操作
strongSession->async_first([strongSession,err]() {
strongSession->onError(err);
});
});
}
void onManagerSession() {
//DebugL<<EventPoller::Instance().isMainThread();
for (auto &pr : *sessionMap) {
weak_ptr<Session> weakSession = pr.second;
pr.second->async([weakSession]() {
auto strongSession=weakSession.lock();
if(!strongSession) {
return;
}
strongSession->onManager();
});
}
}
};
} /* namespace Network */
} /* namespace ZL */
#endif /* TCPSERVER_TCPSERVER_H_ */

View File

@@ -0,0 +1,91 @@
/*
* Session.h
*
* Created on: 2015年10月27日
* Author: root
*/
#ifndef SERVER_SESSION_H_
#define SERVER_SESSION_H_
#include <memory>
#include "Socket.h"
#include "Util/logger.h"
#include "Thread/ThreadPool.h"
using namespace std;
using namespace ZL::Util;
using namespace ZL::Thread;
namespace ZL {
namespace Network {
class TcpSession: public std::enable_shared_from_this<TcpSession> {
public:
TcpSession(const std::shared_ptr<ThreadPool> &_th, const Socket::Ptr &_sock) :
sock(_sock), th(_th) {
localIp = sock->get_local_ip();
peerIp = sock->get_peer_ip();
localPort = sock->get_local_port();
peerPort = sock->get_peer_port();
}
virtual ~TcpSession() {
}
virtual void onRecv(const Socket::Buffer::Ptr &) =0;
virtual void onError(const SockException &err) =0;
virtual void onManager() =0;
template <typename T>
void async(T &&task) {
th->async(std::forward<T>(task));
}
template <typename T>
void async_first(T &&task) {
th->async_first(std::forward<T>(task));
}
protected:
const string& getLocalIp() const {
return localIp;
}
const string& getPeerIp() const {
return peerIp;
}
uint16_t getLocalPort() const {
return localPort;
}
uint16_t getPeerPort() const {
return peerPort;
}
virtual void shutdown() {
sock->emitErr(SockException(Err_other, "self shutdown"));
}
void safeShutdown(){
std::weak_ptr<TcpSession> weakSelf = shared_from_this();
async_first([weakSelf](){
auto strongSelf = weakSelf.lock();
if(strongSelf){
strongSelf->shutdown();
}
});
}
virtual int send(const string &buf) {
return sock->send(buf);
}
virtual int send(const char *buf, int size) {
return sock->send(buf, size);
}
Socket::Ptr sock;
private:
std::shared_ptr<ThreadPool> th;
string localIp;
string peerIp;
uint16_t localPort;
uint16_t peerPort;
};
} /* namespace Session */
} /* namespace ZL */
#endif /* SERVER_SESSION_H_ */

View File

@@ -0,0 +1,86 @@
#ifndef SOCKUTIL_H
#define SOCKUTIL_H
#if defined(_WIN32)
#include <WinSock2.h>
#include <Iphlpapi.h>
#pragma comment (lib,"WS2_32")
#pragma comment(lib,"Iphlpapi.lib")
#else
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif // defined(_WIN32)
#include <string>
#include <string.h>
#include <stdint.h>
using namespace std;
#if defined(_WIN32)
#ifndef socklen_t
#define socklen_t int
#endif //!socklen_t
#ifndef SHUT_RDWR
#define SHUT_RDWR 2
#endif //!SHUT_RDWR
int ioctl(int fd, long cmd, u_long *ptr);
int close(int fd);
#endif // defined(_WIN32)
namespace ZL {
namespace Network {
class SockUtil {
public:
static int connect(const char *host, uint16_t port, bool bAsync = true);
static int listen(const uint16_t port, const char *localIp = "0.0.0.0",
int backLog = 1024);
static int bindUdpSock(const uint16_t port,
const char *localIp = "0.0.0.0");
static int setNoDelay(int sockFd, bool on = true);
static int setNoSigpipe(int sock);
static int setNoBlocked(int sock, bool noblock = true);
static int setRecvBuf(int sock, int size = 256 * 1024);
static int setSendBuf(int sock, int size = 256 * 1024);
static int setReuseable(int sockFd, bool on = true);
static int setBroadcast(int sockFd, bool on = true);
static int setKeepAlive(int sockFd, bool on = true);
//组播相关
static int setMultiTTL(int sockFd, uint8_t ttl = 64);
static int setMultiIF(int sockFd, const char *strLocalIp);
static int setMultiLOOP(int sockFd, bool bAccept = false);
static int joinMultiAddr(int sockFd, const char *strAddr, const char* strLocalIp = "0.0.0.0");
static int leaveMultiAddr(int sockFd, const char *strAddr, const char* strLocalIp = "0.0.0.0");
static int joinMultiAddrFilter(int sockFd, const char* strAddr, const char* strSrcIp, const char* strLocalIp = "0.0.0.0");
static int leaveMultiAddrFilter(int sockFd, const char* strAddr, const char* strSrcIp, const char* strLocalIp = "0.0.0.0");
static int getSockError(int sockFd);
static int setCloseWait(int sockFd, int second = 0);
static string get_local_ip(int fd);
static string get_local_ip();
static uint16_t get_local_port(int fd);
static string get_peer_ip(int fd);
static uint16_t get_peer_port(int fd);
static string get_ifr_name(const char *localIp);
static string get_ifr_mask(const char *ifrName);
static string get_ifr_brdaddr(const char *ifrName);
static bool in_same_lan(const char *myIp, const char *dsrIp);
};
} // namespace Network
} // namespace ZL
#endif // !SOCKUTIL_H

View File

@@ -0,0 +1,123 @@
//
// EventPoller.h
// xzl
//
// Created by xzl on 16/4/12.
//
#ifndef EventPoller_h
#define EventPoller_h
#include <mutex>
#include <thread>
#include <string>
#include <functional>
#include <unordered_map>
#include "PipeWrap.h"
#include "Util/logger.h"
#include "Util/util.h"
using namespace std;
using namespace ZL::Util;
#if defined(__linux__)
#define HAS_EPOLL
#endif //__linux__
namespace ZL {
namespace Poller {
typedef enum {
Event_Read = 1 << 0, //读事件
Event_Write = 1 << 1, //写事件
Event_Error = 1 << 2, //错误事件
Event_LT = 1 << 3,//水平触发
} Poll_Event;
typedef enum {
Sig_Exit = 0, //关闭监听
Sig_Async, //异步
} Sigal_Type;
typedef function<void(int event)> PollEventCB;
typedef function<void(bool success)> PollDelCB;
typedef function<void(void)> PollAsyncCB;
typedef PollAsyncCB PollSyncCB;
#ifndef HAS_EPOLL
typedef struct {
Poll_Event event;
PollEventCB callBack;
int attach;
void operator()(int _event) const{
callBack(_event);
}
void operator()() const{
callBack(attach);
}
} Poll_Record;
#endif //HAS_EPOLL
class EventPoller {
public:
EventPoller(bool enableSelfRun = false);
virtual ~EventPoller();
static EventPoller &Instance(bool enableSelfRun = false) {
static EventPoller *instance(new EventPoller(enableSelfRun));
return *instance;
}
static void Destory() {
delete &EventPoller::Instance();
}
int addEvent(int fd, int event, PollEventCB &&eventCb);
int delEvent(int fd, PollDelCB &&delCb = nullptr);
int modifyEvent(int fd, int event);
void async(PollAsyncCB &&asyncCb);
void sync(PollSyncCB &&syncCb);
void runLoop();
void shutdown();
bool isMainThread();
private:
void initPoll();
inline int sigalPipe(uint64_t type, uint64_t i64_size = 0, uint64_t *buf = NULL);
inline bool handlePipeEvent();
inline Sigal_Type _handlePipeEvent(uint64_t type, uint64_t i64_size, uint64_t *buf);
PipeWrap _pipe;
bool _exitLoop = false;
thread *loopThread = nullptr;
thread::id mainThreadId;
mutex mtx_event_map;
#if defined(HAS_EPOLL)
int epoll_fd = -1;
unordered_map<int, PollEventCB> event_map;
#else
unordered_map<int, Poll_Record> event_map;
#endif //HAS_EPOLL
string pipeBuffer;
};
#define ASYNC_TRACE(...) {\
/*TraceL;*/\
EventPoller::Instance().async(__VA_ARGS__);\
}
#define SYNC_TRACE(...) {\
/*TraceL;*/\
EventPoller::Instance().sync(__VA_ARGS__);\
}
} // namespace Poller
} // namespace ZL
#endif /* EventPoller_h */

View File

@@ -0,0 +1,36 @@
//
// Pipe.h
// xzl
//
// Created by xzl on 16/4/13.
//
#ifndef Pipe_h
#define Pipe_h
#include <stdio.h>
#include <functional>
#include "PipeWrap.h"
#include "EventPoller.h"
using namespace std;
namespace ZL {
namespace Poller {
class Pipe
{
public:
Pipe(function<void(int size,const char *buf)> &&onRead=nullptr);
virtual ~Pipe();
void send(const char *send,int size=0);
private:
std::shared_ptr<PipeWrap> _pipe;
};
} // namespace Poller
} // namespace ZL
#endif /* Pipe_h */

View File

@@ -0,0 +1,32 @@
#ifndef PipeWarp_h
#define PipeWarp_h
namespace ZL {
namespace Poller {
class PipeWrap {
public:
PipeWrap();
~PipeWrap();
int write(const void *buf, int n);
int read(void *buf, int n);
int readFD() const {
return _pipe_fd[0];
}
int writeFD() const {
return _pipe_fd[1];
}
private:
int _pipe_fd[2] = { -1,-1 };
void clearFD();
#if defined(_WIN32)
int _listenerFd = -1;
#endif // defined(_WIN32)
};
} /* namespace Poller */
} /* namespace ZL */
#endif // !PipeWarp_h

View File

@@ -0,0 +1,34 @@
/*
* WinSelect.h
*
* Created on: 2017年3月2日
* Author: Jzan
*/
#ifndef SRC_POLLER_SELECTWRAP_H_
#define SRC_POLLER_SELECTWRAP_H_
namespace ZL {
namespace Poller {
class FdSet
{
public:
FdSet();
virtual ~FdSet();
void fdZero();
void fdSet(int fd);
void fdClr(int fd);
bool isSet(int fd);
void *ptr;
private:
};
} /* namespace Poller */
} /* namespace ZL */
using namespace ZL::Poller;
int zl_select(int cnt,FdSet *read,FdSet *write,FdSet *err,struct timeval *tv);
#endif /* SRC_POLLER_SELECTWRAP_H_ */

View File

@@ -0,0 +1,32 @@
//
// Timer.h
// xzl
//
// Created by xzl on 16/4/13.
//
#ifndef Timer_h
#define Timer_h
#include <stdio.h>
#include <functional>
#include "EventPoller.h"
#include "Thread/AsyncTaskThread.h"
using namespace std;
using namespace ZL::Thread;
namespace ZL {
namespace Poller {
class Timer {
public:
Timer(float second,const function<bool()> &cb);
virtual ~Timer();
private:
std::shared_ptr<bool> canceled;
};
} // namespace Poller
} // namespace ZL
#endif /* Timer_h */

View File

@@ -0,0 +1,77 @@
//
// AsyncTaskThread.h
// xzl
//
// Created by xzl on 15/6/8.
//
#ifndef AsyncTaskThread_h
#define AsyncTaskThread_h
#include <stdio.h>
#include <deque>
#include <mutex>
#include <atomic>
#include <thread>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <condition_variable>
#include "Util/util.h"
using namespace std;
using namespace ZL::Util;
#define TASK_INTERVAL 50
namespace ZL {
namespace Thread {
typedef struct {
uint64_t type;
uint64_t timeLine;
uint64_t tickTime;
function<bool()> task;
} TaskInfo;
class AsyncTaskThread {
public:
//the timer default 30s
AsyncTaskThread(uint64_t millisecond_sleep);
~AsyncTaskThread();
void DoTaskDelay(uint64_t type, uint64_t millisecond, const function<bool()> &func);
void CancelTask(uint64_t type);
static AsyncTaskThread &Instance(uint32_t millisecond_sleep = TASK_INTERVAL) {
static AsyncTaskThread *instance(new AsyncTaskThread(millisecond_sleep));
return *instance;
}
static void Destory(){
delete &AsyncTaskThread::Instance();
}
private:
recursive_mutex _mtx;
unordered_multimap<uint64_t, std::shared_ptr<TaskInfo> > taskMap;
unordered_set<uint64_t> needCancel;
inline uint64_t getNowTime();
thread *taskThread;
void DoTask();
atomic_bool threadExit;
condition_variable_any cond;
uint64_t millisecond_sleep;
};
class AsyncTaskHelper
{
public:
AsyncTaskHelper(uint64_t millisecond,const function<bool()> &task){
AsyncTaskThread::Instance().DoTaskDelay(reinterpret_cast<uint64_t>(this),millisecond,task);
}
virtual ~AsyncTaskHelper(){
AsyncTaskThread::Instance().CancelTask(reinterpret_cast<uint64_t>(this));
}
};
} /* namespace Thread */
} /* namespace ZL */
#endif /* defined(AsyncTaskThread_h) */

View File

@@ -0,0 +1,72 @@
/*
* TaskQueue.h
*
* Created on: 2013-10-11
* Author: root
*/
#ifndef TASKQUEUE_H_
#define TASKQUEUE_H_
#include <deque>
#include <atomic>
#include <mutex>
#include <functional>
#include "spin_mutex.h"
#include "semaphore.h"
using namespace std;
namespace ZL {
namespace Thread {
//实现了一个基于函数对象的任务列队,该列队是线程安全的,任务列队任务数由信号量控制
class TaskQueue {
public:
TaskQueue() {
}
//打入任务至列队
template <typename T>
void push_task(T &&task_func) {
{
lock_guard<spin_mutex> lock(my_mutex);
my_queue.emplace_back(std::forward<T>(task_func));
}
sem.post();
}
template <typename T>
void push_task_first(T &&task_func) {
{
lock_guard<spin_mutex> lock(my_mutex);
my_queue.emplace_front(std::forward<T>(task_func));
}
sem.post();
}
//清空任务列队
void push_exit(unsigned int n) {
sem.post(n);
}
//从列队获取一个任务,由执行线程执行
bool get_task(function<void(void)> &tsk) {
sem.wait();
lock_guard<spin_mutex> lock(my_mutex);
if (my_queue.size() == 0) {
return false;
}
tsk = my_queue.front();
my_queue.pop_front();
return true;
}
uint64_t size() const{
lock_guard<spin_mutex> lock(my_mutex);
return my_queue.size();
}
private:
deque<function<void(void)>> my_queue;
mutable spin_mutex my_mutex;
semaphore sem;
};
} /* namespace Thread */
} /* namespace ZL */
#endif /* TASKQUEUE_H_ */

View File

@@ -0,0 +1,173 @@
/*
* ThreadPool.h
*
* Created on: 2013-10-11
* Author: root
*/
#ifndef THREADPOOL_H_
#define THREADPOOL_H_
#include <assert.h>
#include <vector>
#include "threadgroup.h"
#include "TaskQueue.h"
#include "Util/util.h"
#include "Util/logger.h"
using namespace ZL::Util;
namespace ZL {
namespace Thread {
class ThreadPool {
public:
enum Priority {
PRIORITY_LOWEST = 0,
PRIORITY_LOW,
PRIORITY_NORMAL,
PRIORITY_HIGH,
PRIORITY_HIGHEST
};
//num:线程池线程个数
ThreadPool(int num, Priority _priority = PRIORITY_NORMAL) :
thread_num(num), avaible(true), priority(_priority) {
start();
}
~ThreadPool() {
wait();
}
//把任务打入线程池并异步执行
template <typename T>
bool async(T &&task) {
if (!avaible) {
return false;
}
if (my_thread_group.is_this_thread_in()) {
task();
} else {
my_queue.push_task(std::forward<T>(task));
}
return true;
}
template <typename T>
bool async_first(T &&task) {
if (!avaible) {
return false;
}
if (my_thread_group.is_this_thread_in()) {
task();
} else {
my_queue.push_task_first(std::forward<T>(task));
}
return true;
}
template <typename T>
bool sync(T &&task){
semaphore sem;
bool flag = async([&](){
task();
sem.post();
});
if(flag){
sem.wait();
}
return flag;
}
template <typename T>
bool sync_first(T &&task) {
semaphore sem;
bool flag = async_first([&]() {
task();
sem.post();
});
if (flag) {
sem.wait();
}
return flag;
}
//同步等待线程池执行完所有任务并退出
void wait() {
exit();
my_thread_group.join_all();
}
uint64_t size() const{
return my_queue.size();
}
static ThreadPool &Instance() {
//单例模式
static ThreadPool instance(thread::hardware_concurrency());
return instance;
}
static bool setPriority(Priority _priority = PRIORITY_NORMAL,
thread::native_handle_type threadId = 0) {
// set priority
#if defined(_WIN32)
static int Priorities[] = { THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST };
if (_priority != PRIORITY_NORMAL && SetThreadPriority(GetCurrentThread(), Priorities[_priority]) == 0) {
return false;
}
return true;
#else
static int Min = sched_get_priority_min(SCHED_OTHER);
if (Min == -1) {
return false;
}
static int Max = sched_get_priority_max(SCHED_OTHER);
if (Max == -1) {
return false;
}
static int Priorities[] = { Min, Min + (Max - Min) / 4, Min
+ (Max - Min) / 2, Min + (Max - Min) / 4, Max };
if (threadId == 0) {
threadId = pthread_self();
}
struct sched_param params;
params.sched_priority = Priorities[_priority];
return pthread_setschedparam(threadId, SCHED_OTHER, &params) == 0;
#endif
}
private:
TaskQueue my_queue;
thread_group my_thread_group;
int thread_num;
volatile bool avaible;
Priority priority;
//发送空任务至任务列队,通知线程主动退出
void exit() {
avaible = false;
my_queue.push_exit(thread_num);
}
void start() {
if (thread_num <= 0)
return;
for (int i = 0; i < thread_num; ++i) {
my_thread_group.create_thread(bind(&ThreadPool::run, this));
}
}
void run() {
ThreadPool::setPriority(priority);
function<void(void)> task;
while (true) {
if (my_queue.get_task(task)) {
try {
task();
} catch (std::exception &ex) {
FatalL << ex.what();
}
task = nullptr;
} else {
//空任务,退出线程
break;
}
}
}
}
;
} /* namespace Thread */
} /* namespace ZL */
#endif /* THREADPOOL_H_ */

View File

@@ -0,0 +1,46 @@
/*
* WorkThreadPool.h
*
* Created on: 2015年10月30日
* Author: root
*/
#ifndef UTIL_WORKTHREADPOOL_H_
#define UTIL_WORKTHREADPOOL_H_
#include <map>
#include <thread>
#include <memory>
#include <atomic>
#include <iostream>
#include <unordered_map>
#include "ThreadPool.h"
using namespace std;
namespace ZL {
namespace Thread {
class WorkThreadPool {
public:
WorkThreadPool(int threadnum = thread::hardware_concurrency());
virtual ~WorkThreadPool();
std::shared_ptr<ThreadPool> &getWorkThread();
static WorkThreadPool &Instance() {
static WorkThreadPool *intance(new WorkThreadPool());
return *intance;
}
static void Destory(){
delete &(WorkThreadPool::Instance());
}
private:
int threadnum;
atomic<int> threadPos;
vector <std::shared_ptr<ThreadPool> > threads;
void wait();
};
} /* namespace Thread */
} /* namespace ZL */
#endif /* UTIL_WORKTHREADPOOL_H_ */

View File

@@ -0,0 +1,71 @@
/*
* rwmutex.h
*
* Created on: 2016年1月27日
* Author: 熊子良
*/
#ifndef UTIL_RWMUTEX_H_
#define UTIL_RWMUTEX_H_
#include <mutex>
#include <atomic>
using namespace std;
namespace ZL {
namespace Thread {
class rw_mutex {
public:
rw_mutex() :
reader_cnt(0) {
}
void lock(bool write_mode = true) {
if (write_mode) {
//write thread
mtx_write.lock();
} else {
// read thread
lock_guard<mutex> lck(mtx_reader);
if (reader_cnt++ == 0) {
mtx_write.lock();
}
}
}
void unlock(bool write_mode = true) {
if (write_mode) {
//write thread
mtx_write.unlock();
} else {
// read thread
lock_guard<mutex> lck(mtx_reader);
if (--reader_cnt == 0) {
mtx_write.unlock();
}
}
}
virtual ~rw_mutex() {
}
private:
mutex mtx_write;
mutex mtx_reader;
int reader_cnt;
};
class lock_guard_rw {
public:
lock_guard_rw(rw_mutex &_mtx, bool _write_mode = true) :
mtx(_mtx), write_mode(_write_mode) {
mtx.lock(write_mode);
}
virtual ~lock_guard_rw() {
mtx.unlock(write_mode);
}
private:
rw_mutex &mtx;
bool write_mode;
};
} /* namespace Thread */
} /* namespace ZL */
#endif /* UTIL_RWMUTEX_H_ */

View File

@@ -0,0 +1,78 @@
/*
* semaphore.h
*
* Created on: 2015年8月14日
* Author: root
*/
#ifndef SEMAPHORE_H_
#define SEMAPHORE_H_
/*
* 目前发现信号量在32位的系统上有问题
* 休眠的线程无法被正常唤醒,先禁用之
#if defined(__linux__)
#include <semaphore.h>
#define HAVE_SEM
#endif //HAVE_SEM
*/
#include <mutex>
#include <atomic>
#include <condition_variable>
using namespace std;
namespace ZL {
namespace Thread {
class semaphore {
public:
explicit semaphore(unsigned int initial = 0) {
#if defined(HAVE_SEM)
sem_init(&sem, 0, initial);
#else
count_ = 0;
#endif
}
~semaphore() {
#if defined(HAVE_SEM)
sem_destroy(&sem);
#endif
}
void post(unsigned int n = 1) {
#if defined(HAVE_SEM)
while (n--) {
sem_post(&sem);
}
#else
unique_lock<mutex> lock(mutex_);
count_ += n;
while (n--) {
condition_.notify_one();
}
#endif
}
void wait() {
#if defined(HAVE_SEM)
sem_wait(&sem);
#else
unique_lock<mutex> lock(mutex_);
while (count_ == 0) {
condition_.wait(lock);
}
--count_;
#endif
}
private:
#if defined(HAVE_SEM)
sem_t sem;
#else
atomic_uint count_;
mutex mutex_;
condition_variable_any condition_;
#endif
};
} /* namespace Thread */
} /* namespace ZL */
#endif /* SEMAPHORE_H_ */

View File

@@ -0,0 +1,41 @@
/*
* spinmutex.h
*
* Created on: 2017年3月31日
* Author: xzl
*/
#ifndef SRC_THREAD_SPIN_MUTEX_H_
#define SRC_THREAD_SPIN_MUTEX_H_
#include <atomic>
#include <mutex>
using namespace std;
namespace ZL {
namespace Thread {
#ifndef __ARM_ARCH
class spin_mutex {
std::atomic_flag flag = ATOMIC_FLAG_INIT;
public:
spin_mutex() = default;
spin_mutex(const spin_mutex&) = delete;
spin_mutex& operator= (const spin_mutex&) = delete;
void lock() {
while(flag.test_and_set(std::memory_order_acquire)) ;
}
void unlock() {
flag.clear(std::memory_order_release);
}
};
#else
typedef mutex spin_mutex;
#endif //__ARM_ARCH
} /* namespace Thread */
} /* namespace ZL */
#endif /* SRC_THREAD_SPIN_MUTEX_H_ */

View File

@@ -0,0 +1,93 @@
/*
* threadgroup.h
*
* Created on: 2014-6-23
* Author: root
*/
#ifndef THREADGROUP_H_
#define THREADGROUP_H_
#include <set>
#include <mutex>
#include <thread>
#include <vector>
#include <unordered_map>
using namespace std;
namespace ZL {
namespace Thread {
class thread_group {
private:
thread_group(thread_group const&);
thread_group& operator=(thread_group const&);
public:
thread_group() {
}
~thread_group() {
for (auto &th : threads) {
delete th.second;
}
}
bool is_this_thread_in() {
auto it = threads.find(this_thread::get_id());
return it != threads.end();
}
bool is_thread_in(thread* thrd) {
if (thrd) {
auto it = threads.find(thrd->get_id());
return it != threads.end();
} else {
return false;
}
}
template<typename F>
thread* create_thread(F threadfunc) {
thread *new_thread=new thread(threadfunc);
threads[new_thread->get_id()] = new_thread;
return new_thread;
}
void add_thread(thread* thrd) {
if (thrd) {
if (is_thread_in(thrd)) {
throw runtime_error(
"thread_group: trying to add a duplicated thread");
}
threads[thrd->get_id()] = thrd;
}
}
void remove_thread(thread* thrd) {
auto it = threads.find(thrd->get_id());
if (it != threads.end()) {
threads.erase(it);
}
}
void join_all() {
if (is_this_thread_in()) {
throw runtime_error("thread_group: trying joining itself");
return;
}
for (auto &it : threads) {
if (it.second->joinable()) {
it.second->join(); //等待线程主动退出
}
}
}
size_t size() {
return threads.size();
}
private:
unordered_map<thread::id, thread*> threads;
};
} /* namespace Thread */
} /* namespace ZL */
#endif /* THREADGROUP_H_ */

View File

@@ -0,0 +1,75 @@
/*
* File.h
*
* Created on: 2016年9月22日
* Author: xzl
*/
#ifndef SRC_UTIL_FILE_H_
#define SRC_UTIL_FILE_H_
#if defined(_WIN32)
#include <WinSock2.h>
#pragma comment (lib,"WS2_32")
#endif // WIN32
#include <stdio.h>
#if defined(_WIN32)
#ifndef PATH_MAX
#define PATH_MAX 256
#endif // !PATH_MAX
struct dirent{
long d_ino; /* inode number*/
off_t d_off; /* offset to this dirent*/
unsigned short d_reclen; /* length of this d_name*/
unsigned char d_type; /* the type of d_name*/
char d_name[1]; /* file name (null-terminated)*/
};
typedef struct _dirdesc {
int dd_fd; /** file descriptor associated with directory */
long dd_loc; /** offset in current buffer */
long dd_size; /** amount of data returned by getdirentries */
char *dd_buf; /** data buffer */
int dd_len; /** size of data buffer */
long dd_seek; /** magic cookie returned by getdirentries */
HANDLE handle;
struct dirent *index;
} DIR;
# define __dirfd(dp) ((dp)->dd_fd)
int mkdir(const char *path, int mode);
DIR *opendir(const char *);
int closedir(DIR *);
struct dirent *readdir(DIR *);
#endif // defined(_WIN32)
namespace ZL {
namespace Util {
class File {
public:
// 可读普通文件
static bool isrfile(const char *path) ;
//新建文件,目录文件夹自动生成
static bool createfile_path(const char *file, unsigned int mod);
static FILE *createfile_file(const char *file,const char *mode);
//判断是否为目录
static bool is_dir(const char *path) ;
//判断是否为常规文件
static bool is_file(const char *path) ;
//判断是否是特殊目录(. or ..
static bool is_special_dir(const char *path);
//删除目录或文件
static void delete_file(const char *path) ;
static bool rm_empty_dir(const char *path);
private:
File();
virtual ~File();
};
} /* namespace Util */
} /* namespace ZL */
#endif /* SRC_UTIL_FILE_H_ */

View File

@@ -0,0 +1,74 @@
/*
* MD5.h
*
* Created on: 2016年8月23日
* Author: xzl
*/
#ifndef SRC_UTIL_MD5_H_
#define SRC_UTIL_MD5_H_
#include <string>
#include <iostream>
using namespace std;
namespace ZL {
namespace Util {
// a small class for calculating MD5 hashes of strings or byte arrays
// it is not meant to be fast or secure
//
// usage: 1) feed it blocks of uchars with update()
// 2) finalize()
// 3) get hexdigest() string
// or
// MD5(std::string).hexdigest()
//
// assumes that char is 8 bit and int is 32 bit
class MD5
{
public:
typedef unsigned int size_type; // must be 32bit
MD5();
MD5(const std::string& text);
void update(const unsigned char *buf, size_type length);
void update(const char *buf, size_type length);
MD5& finalize();
std::string hexdigest() const;
friend std::ostream& operator<<(std::ostream&, MD5 md5);
private:
void init();
typedef uint8_t uint1; // 8bit
typedef uint32_t uint4; // 32bit
enum {blocksize = 64}; // VC6 won't eat a const static int here
void transform(const uint1 block[blocksize]);
static void decode(uint4 output[], const uint1 input[], size_type len);
static void encode(uint1 output[], const uint4 input[], size_type len);
bool finalized;
uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
uint4 count[2]; // 64bit counter for number of bits (lo, hi)
uint4 state[4]; // digest so far
uint1 digest[16]; // the result
// low level logic operations
static inline uint4 F(uint4 x, uint4 y, uint4 z);
static inline uint4 G(uint4 x, uint4 y, uint4 z);
static inline uint4 H(uint4 x, uint4 y, uint4 z);
static inline uint4 I(uint4 x, uint4 y, uint4 z);
static inline uint4 rotate_left(uint4 x, int n);
static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
};
} /* namespace Util */
} /* namespace ZL */
#endif /* SRC_UTIL_MD5_H_ */

View File

@@ -0,0 +1,104 @@
/*
* NoticeCenter.h
*
* Created on: 2017年2月17日
* Author: xzl
*/
#ifndef SRC_UTIL_NOTICECENTER_H_
#define SRC_UTIL_NOTICECENTER_H_
#include <mutex>
#include <memory>
#include <string>
#include <exception>
#include <functional>
#include <unordered_map>
#include "function_traits.h"
using namespace std;
namespace ZL {
namespace Util {
class NoticeCenter {
public:
class InterruptException : public std::runtime_error
{
public:
InterruptException():std::runtime_error("InterruptException"){}
virtual ~InterruptException(){}
};
virtual ~NoticeCenter(){}
static NoticeCenter &Instance(){
static NoticeCenter instance;
return instance;
}
template<typename ...ArgsType>
bool emitEvent(const char *strEvent,ArgsType &&...args){
lock_guard<recursive_mutex> lck(_mtxListener);
auto it0 = _mapListener.find(strEvent);
if (it0 == _mapListener.end()) {
return false;
}
for(auto &pr : it0->second){
typedef function<void(ArgsType &&...)> funType;
funType *obj = (funType *)(pr.second.get());
try{
(*obj)(std::forward<ArgsType>(args)...);
}catch(InterruptException &ex){
break;
}
}
return it0->second.size();
}
template<typename FUN>
void addListener(void *tag, const char *strEvent, const FUN &fun) {
typedef typename function_traits<FUN>::stl_function_type funType;
std::shared_ptr<void> pListener(new funType(fun), [](void *ptr) {
funType *obj = (funType *)ptr;
delete obj;
});
lock_guard<recursive_mutex> lck(_mtxListener);
_mapListener[strEvent][tag] = pListener;
}
void delListener(void *tag,const char *strEvent){
lock_guard<recursive_mutex> lck(_mtxListener);
auto it = _mapListener.find(strEvent);
if(it == _mapListener.end()){
return;
}
it->second.erase(tag);
if(it->second.empty()){
_mapListener.erase(it);
}
}
void delListener(void *tag){
lock_guard<recursive_mutex> lck(_mtxListener);
for(auto it = _mapListener.begin();it != _mapListener.end();){
it->second.erase(tag);
if(it->second.empty()){
it = _mapListener.erase(it);
continue;
}
++it;
}
}
private:
NoticeCenter(){}
recursive_mutex _mtxListener;
unordered_map<string,unordered_map<void *,std::shared_ptr<void> > > _mapListener;
};
} /* namespace Util */
} /* namespace ZL */
#endif /* SRC_UTIL_NOTICECENTER_H_ */

View File

@@ -0,0 +1,133 @@
/*
* ResourcePool.h
*
* Created on: 2015年10月29日
* Author: root
*/
#ifndef UTIL_RECYCLEPOOL_H_
#define UTIL_RECYCLEPOOL_H_
#include <mutex>
#include <deque>
#include <memory>
#include <atomic>
#include <functional>
#include <unordered_set>
namespace ZL {
namespace Util {
using namespace std;
template<typename C, int poolSize = 10>
class ResourcePool {
public:
typedef std::shared_ptr<C> ValuePtr;
ResourcePool() {
pool.reset(new _ResourcePool());
}
#if (!defined(__GNUC__)) || (__GNUC__ >= 5)
template<typename ...ArgTypes>
ResourcePool(ArgTypes &&...args) {
pool.reset(new _ResourcePool(std::forward<ArgTypes>(args)...));
}
#endif //(!defined(__GNUC__)) || (__GNUC__ >= 5)
void reSize(int size) {
pool->setSize(size);
}
ValuePtr obtain() {
return pool->obtain();
}
void quit(const ValuePtr &ptr) {
pool->quit(ptr);
}
private:
class _ResourcePool: public enable_shared_from_this<_ResourcePool> {
public:
typedef std::shared_ptr<C> ValuePtr;
_ResourcePool() {
poolsize = poolSize;
allotter = []()->C* {
return new C();
};
}
#if (!defined(__GNUC__)) || (__GNUC__ >= 5)
template<typename ...ArgTypes>
_ResourcePool(ArgTypes &&...args) {
poolsize = poolSize;
allotter = [args...]()->C* {
return new C(args...);
};
}
#endif //(!defined(__GNUC__)) || (__GNUC__ >= 5)
virtual ~_ResourcePool(){
std::lock_guard<mutex> lck(_mutex);
for(auto &ptr : objs){
delete ptr;
}
}
void setSize(int size) {
poolsize = size;
}
ValuePtr obtain() {
std::lock_guard<mutex> lck(_mutex);
C *ptr = nullptr;
if (objs.size() == 0) {
ptr = allotter();
} else {
ptr = objs.front();
objs.pop_front();
}
return ValuePtr(ptr, Deleter(this->shared_from_this()));
}
void quit(const ValuePtr &ptr) {
std::lock_guard<mutex> lck(_mutex);
quitSet.emplace(ptr.get());
}
private:
class Deleter {
public:
Deleter(const std::shared_ptr<_ResourcePool> &pool) {
weakPool = pool;
}
void operator()(C *ptr) {
auto strongPool = weakPool.lock();
if (strongPool) {
strongPool->recycle(ptr);
} else {
delete ptr;
}
}
private:
weak_ptr<_ResourcePool> weakPool;
};
private:
void recycle(C *obj) {
std::lock_guard<mutex> lck(_mutex);
auto it = quitSet.find(obj);
if (it != quitSet.end()) {
delete obj;
quitSet.erase(it);
return;
}
if ((int)objs.size() >= poolsize) {
delete obj;
return;
}
objs.push_back(obj);
}
deque<C*> objs;
unordered_set<C*> quitSet;
function<C*(void)> allotter;
mutex _mutex;
int poolsize;
};
std::shared_ptr<_ResourcePool> pool;
};
} /* namespace util */
} /* namespace im */
#endif /* UTIL_RECYCLEPOOL_H_ */

View File

@@ -0,0 +1,244 @@
/*
* RingBuffer.h
*
* Created on: 2016年8月10日
* Author: xzl
*/
#ifndef UTIL_RINGBUFFER_H_
#define UTIL_RINGBUFFER_H_
#include <atomic>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <condition_variable>
using namespace std;
namespace ZL {
namespace Util {
//实现了一个一写多读得环形缓冲的模板类
template<typename T> class RingBuffer: public enable_shared_from_this<
RingBuffer<T> > {
public:
typedef std::shared_ptr<RingBuffer> Ptr;
class RingReader {
public:
friend class RingBuffer;
typedef std::shared_ptr<RingReader> Ptr;
RingReader(const std::shared_ptr<RingBuffer> &_buffer,bool _useBuffer) {
buffer = _buffer;
curpos = _buffer->ringKeyPos;
useBuffer = _useBuffer;
}
virtual ~RingReader() {
auto strongBuffer = buffer.lock();
if (strongBuffer) {
strongBuffer->release(this);
}
}
//重新定位读取器至最新的数据位置
void reset(bool keypos = true) {
auto strongBuffer = buffer.lock();
if (strongBuffer) {
if(keypos){
curpos = strongBuffer->ringKeyPos; //定位读取器
}else{
curpos = strongBuffer->ringPos; //定位读取器
}
}
}
void setReadCB(const function<void(const T &)> &cb) {
lock_guard<recursive_mutex> lck(mtxCB);
readCB = cb;
reset();
}
void setDetachCB(const function<void()> &cb) {
lock_guard<recursive_mutex> lck(mtxCB);
if (!cb) {
detachCB = []() {};
} else {
detachCB = cb;
}
}
const T* read(){
auto strongBuffer=buffer.lock();
if(!strongBuffer){
return nullptr;
}
return read(strongBuffer.get());
}
private:
void onRead(const T &data) {
lock_guard<recursive_mutex> lck(mtxCB);
if(!readCB){
return;
}
if(!useBuffer){
readCB(data);
}else{
const T *pkt = nullptr;
while((pkt = read())){
readCB(*pkt);
}
}
}
void onDetach() const {
lock_guard<recursive_mutex> lck(mtxCB);
detachCB();
}
//读环形缓冲
const T *read(RingBuffer *ring) {
if (curpos == ring->ringPos) {
return nullptr;
}
const T *data = &(ring->dataRing[curpos]); //返回包
curpos = ring->next(curpos); //更新位置
return data;
}
function<void(const T &)> readCB ;
function<void(void)> detachCB = []() {};
weak_ptr<RingBuffer> buffer;
mutable recursive_mutex mtxCB;
int curpos;
bool useBuffer;
};
friend class RingReader;
RingBuffer(int size = 0) {
if(size <= 0){
size = 32;
canReSize = true;
}
ringSize = size;
dataRing = new T[ringSize];
ringPos = 0;
ringKeyPos = 0;
}
virtual ~RingBuffer() {
decltype(readerMap) mapCopy;
{
lock_guard<recursive_mutex> lck(mtx_reader);
mapCopy.swap(readerMap);
}
for (auto &pr : mapCopy) {
auto reader = pr.second.lock();
if(reader){
reader->onDetach();
}
}
delete[] dataRing;
}
#if defined(ENABLE_RING_USEBUF)
std::shared_ptr<RingReader> attach(bool useBuffer = true) {
#else //ENABLE_RING_USEBUF
std::shared_ptr<RingReader> attach(bool useBuffer = false) {
#endif //ENABLE_RING_USEBUF
std::shared_ptr<RingReader> ptr(new RingReader(this->shared_from_this(),useBuffer));
std::weak_ptr<RingReader> weakPtr = ptr;
lock_guard<recursive_mutex> lck(mtx_reader);
readerMap.emplace(ptr.get(),weakPtr);
return ptr;
}
//写环形缓冲,非线程安全的
void write(const T &in,bool isKey = true) {
computeBestSize(isKey);
dataRing[ringPos] = in;
if (isKey) {
ringKeyPos = ringPos; //设置读取器可以定位的点
}
ringPos = next(ringPos);
decltype(readerMap) mapCopy;
{
lock_guard<recursive_mutex> lck(mtx_reader);
mapCopy = readerMap;
}
for (auto &pr : mapCopy) {
auto reader = pr.second.lock();
if(reader){
reader->onRead(in);
}
}
}
int readerCount(){
lock_guard<recursive_mutex> lck(mtx_reader);
return readerMap.size();
}
private:
T *dataRing;
int ringPos;
int ringKeyPos;
int ringSize;
//计算最佳环形缓存大小的参数
int besetSize = 0;
int totalCnt = 0;
int lastKeyCnt = 0;
bool canReSize = false;
recursive_mutex mtx_reader;
unordered_map<void *,std::weak_ptr<RingReader> > readerMap;
inline int next(int pos) {
//读取器下一位置
if (pos > ringSize - 2) {
return 0;
} else {
return pos + 1;
}
}
void release(RingReader *reader) {
lock_guard<recursive_mutex> lck(mtx_reader);
readerMap.erase(reader);
}
void computeBestSize(bool isKey){
if(!canReSize || besetSize){
return;
}
totalCnt++;
if(!isKey){
return;
}
//关键帧
if(lastKeyCnt){
//计算两个I帧之间的包个数
besetSize = totalCnt - lastKeyCnt;
reSize();
return;
}
lastKeyCnt = totalCnt;
}
void reSize(){
ringSize = besetSize;
delete [] dataRing;
dataRing = new T[ringSize];
ringPos = 0;
ringKeyPos = 0;
decltype(readerMap) mapCopy;
{
lock_guard<recursive_mutex> lck(mtx_reader);
mapCopy = readerMap;
}
for (auto &pr : mapCopy) {
auto reader = pr.second.lock();
if(reader){
reader->reset(true);
}
}
}
};
} /* namespace Util */
} /* namespace ZL */
#endif /* UTIL_RINGBUFFER_H_ */

View File

@@ -0,0 +1,112 @@
/*
* SSLServer.h
*
* Created on: 2016年1月11日
* Author: root
*/
#ifndef CRYPTO_SSLBOX_H_
#define CRYPTO_SSLBOX_H_
#include <fcntl.h>
#include <openssl/bio.h>
#include <openssl/ossl_typ.h>
#include <mutex>
#include <string>
#include <atomic>
#include <functional>
#include "logger.h"
#if defined(_WIN32)
#if defined(_WIN64)
//64bit
#if defined(_DEBUG)
#pragma comment (lib,"libssl64MDd")
#pragma comment (lib,"libcrypto64MDd")
#else
#pragma comment (lib,"libssl64MD")
#pragma comment (lib,"libcrypto64MD")
#endif // defined(_DEBUG)
#else
//32 bit
#if defined(_DEBUG)
#pragma comment (lib,"libssl32MDd")
#pragma comment (lib,"libcrypto32MDd")
#else
#pragma comment (lib,"libssl32MD")
#pragma comment (lib,"libcrypto32MD")
#endif // defined(_DEBUG)
#endif //defined(_WIN64)
#endif // defined(_WIN32)
using namespace std;
namespace ZL {
namespace Util {
class SSL_Initor {
public:
friend class SSL_Box;
static SSL_Initor &Instance() {
static SSL_Initor obj;
return obj;
}
void loadServerPem(const char *keyAndCA_pem, const char *import_pwd = "");
void loadClientPem(const char *keyAndCA_pem, const char *import_pwd = "");
private:
static mutex *_mutexes;
SSL_CTX *ssl_server;
SSL_CTX *ssl_client;
SSL_Initor();
~SSL_Initor();
void setCtx(SSL_CTX *ctx);
void loadPem(SSL_CTX *ctx, const char *keyAndCA_pem,const char *import_pwd);
inline std::string getLastError();
}
;
class SSL_Box {
public:
SSL_Box(bool isServer = true, bool enable = true);
virtual ~SSL_Box();
//收到密文后,调用此函数解密
void onRecv(const char *data, uint32_t data_len);
//需要加密明文调用此函数
void onSend(const char *data, uint32_t data_len);
//设置解密后获取明文的回调
template<typename F>
void setOnDecData(F &&fun) {
onDec = fun;
}
//设置加密后获取密文的回调
template<typename F>
void setOnEncData(F &&fun) {
onEnc = fun;
}
void shutdown();
private:
bool isServer;
bool enable;
bool sendHandshake;
SSL *ssl;
BIO *read_bio, *write_bio;
function<void(const char *data, uint32_t len)> onDec;
function<void(const char *data, uint32_t len)> onEnc;
std::string _bufferOut;
void flush();
void flushWriteBio(char *buf, int bufsize);
void flushReadBio(char *buf, int bufsize);
};
} /* namespace Util */
} /* namespace ZL */
#endif /* CRYPTO_SSLBOX_H_ */

View File

@@ -0,0 +1,145 @@
/*
* SqlConnection.h
*
* Created on: 2015年10月29日
* Author: root
*/
#ifndef SQL_SQLCONNECTION_H_
#define SQL_SQLCONNECTION_H_
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include "Util/logger.h"
#if defined(_WIN32)
#include <mysql.h>
#pragma comment (lib,"libmysql")
#else
#include <mysql/mysql.h>
#endif // defined(_WIN32)
using namespace std;
namespace ZL {
namespace Util {
class SqlConnection {
public:
SqlConnection(const string &url, unsigned short port, const string &dbname,
const string &user, const string &password,const string &character = "utf8mb4");
virtual ~SqlConnection();
template<typename ...Args>
int64_t query(int64_t &rowId, const char *fmt, Args && ...arg) {
check();
string tmp = queryString(fmt, std::forward<Args>(arg)...);
if (mysql_query(&sql, tmp.c_str())) {
WarnL << mysql_error(&sql) << ":" << tmp << endl;
return -1;
}
rowId=mysql_insert_id(&sql);
return mysql_affected_rows(&sql);
}
int64_t query(int64_t &rowId,const char *str) {
check();
if (mysql_query(&sql, str)) {
WarnL << mysql_error(&sql) << ":" << str << endl;
return -1;
}
rowId=mysql_insert_id(&sql);
return mysql_affected_rows(&sql);
}
template<typename ...Args>
int64_t query(int64_t &rowId,vector<vector<string>> &ret, const char *fmt,
Args && ...arg) {
check();
string tmp = queryString(fmt, std::forward<Args>(arg)...);
if (mysql_query(&sql, tmp.c_str())) {
WarnL << mysql_error(&sql) << ":" << tmp << endl;
return -1;
}
ret.clear();
MYSQL_RES *res = mysql_store_result(&sql);
if (!res) {
rowId=mysql_insert_id(&sql);
return mysql_affected_rows(&sql);
}
MYSQL_ROW row;
unsigned int column = mysql_num_fields(res);
while ((row = mysql_fetch_row(res)) != NULL) {
ret.emplace_back();
auto &back = ret.back();
for (unsigned int i = 0; i < column; i++) {
back.emplace_back(row[i] ? row[i] : "");
}
}
mysql_free_result(res);
rowId=mysql_insert_id(&sql);
return mysql_affected_rows(&sql);
}
int64_t query(int64_t &rowId,vector<vector<string>> &ret, const char *str) {
check();
if (mysql_query(&sql, str)) {
WarnL << mysql_error(&sql) << ":" << str << endl;
return -1;
}
ret.clear();
MYSQL_RES *res = mysql_store_result(&sql);
if (!res) {
rowId=mysql_insert_id(&sql);
return mysql_affected_rows(&sql);
}
MYSQL_ROW row;
unsigned int column = mysql_num_fields(res);
while ((row = mysql_fetch_row(res)) != NULL) {
ret.emplace_back();
auto &back = ret.back();
for (unsigned int i = 0; i < column; i++) {
back.emplace_back(row[i] ? row[i] : "" );
}
}
mysql_free_result(res);
rowId=mysql_insert_id(&sql);
return mysql_affected_rows(&sql);
}
template<typename ...Args>
static string queryString(const char *fmt, Args && ...arg) {
char *ptr_out = NULL;
asprintf(&ptr_out, fmt, arg...);
string ret(ptr_out);
if (ptr_out) {
free(ptr_out);
}
return ret;
}
static string queryString(const char *fmt) {
return fmt;
}
string &escape(string &str) {
char *out = new char[str.length() * 2 + 1];
mysql_real_escape_string(&sql, out, str.c_str(), str.size());
str.assign(out);
delete [] out;
return str;
}
private:
MYSQL sql;
inline void check() {
if (mysql_ping(&sql) != 0) {
throw runtime_error("MYSQL连接异常!");
}
}
};
} /* namespace util */
} /* namespace ZL */
#endif /* SQL_SQLCONNECTION_H_ */

View File

@@ -0,0 +1,230 @@
/*
* SqlPool.h
*
* Created on: 2015年10月29日
* Author: root
*/
#ifndef SQL_SQLPOOL_H_
#define SQL_SQLPOOL_H_
#include <deque>
#include <mutex>
#include <memory>
#include <sstream>
#include <functional>
#include "logger.h"
#include "SqlConnection.h"
#include "Thread/ThreadPool.h"
#include "Util/ResourcePool.h"
#include "Thread/AsyncTaskThread.h"
using namespace std;
using namespace ZL::Thread;
namespace ZL {
namespace Util {
template<int poolSize = 10>
class _SqlPool {
public:
typedef ResourcePool<SqlConnection, poolSize> PoolType;
typedef vector<vector<string> > SqlRetType;
static _SqlPool &Instance() {
static _SqlPool *pool(new _SqlPool());
return *pool;
}
static void Destory(){
delete &Instance();
}
void reSize(int size) {
if (size < 0) {
return;
}
poolsize = size;
pool->reSize(size);
threadPool.reset(new ThreadPool(poolsize));
}
template<typename ...Args>
void Init(Args && ...arg) {
pool.reset(new PoolType(std::forward<Args>(arg)...));
pool->obtain();
}
template<typename ...Args>
int64_t query(const char *fmt, Args && ...arg) {
string sql = SqlConnection::queryString(fmt, std::forward<Args>(arg)...);
doQuery(sql);
return 0;
}
int64_t query(const string &sql) {
doQuery(sql);
return 0;
}
template<typename ...Args>
int64_t query(int64_t &rowID,vector<vector<string>> &ret, const char *fmt,
Args && ...arg) {
return _query(rowID,ret, fmt, std::forward<Args>(arg)...);
}
int64_t query(int64_t &rowID,vector<vector<string>> &ret, const string &sql) {
return _query(rowID,ret, sql.c_str());
}
static const string &escape(const string &str) {
try {
//捕获创建对象异常
_SqlPool::Instance().pool->obtain()->escape(
const_cast<string &>(str));
} catch (exception &e) {
WarnL << e.what() << endl;
}
return str;
}
private:
_SqlPool() :
threadPool(new ThreadPool(poolSize)), asyncTaskThread(10 * 1000) {
poolsize = poolSize;
asyncTaskThread.DoTaskDelay(reinterpret_cast<uint64_t>(this), 30 * 1000,
[this]() {
flushError();
return true;
});
}
inline void doQuery(const string &str,int tryCnt = 3) {
auto lam = [this,str,tryCnt]() {
int64_t rowID;
auto cnt = tryCnt - 1;
if(_query(rowID,str.c_str())==-2 && cnt > 0) {
lock_guard<mutex> lk(error_query_mutex);
sqlQuery query(str,cnt);
error_query.push_back(query);
}
};
threadPool->async(lam);
}
template<typename ...Args>
inline int64_t _query(int64_t &rowID,Args &&...arg) {
typename PoolType::ValuePtr mysql;
try {
//捕获执行异常
mysql = pool->obtain();
return mysql->query(rowID,std::forward<Args>(arg)...);
} catch (exception &e) {
pool->quit(mysql);
WarnL << e.what() << endl;
return -2;
}
}
void flushError() {
decltype(error_query) query_copy;
error_query_mutex.lock();
query_copy.swap(error_query);
error_query_mutex.unlock();
if (query_copy.size() == 0) {
return;
}
for (auto &query : query_copy) {
doQuery(query.sql_str,query.tryCnt);
}
}
virtual ~_SqlPool() {
asyncTaskThread.CancelTask(reinterpret_cast<uint64_t>(this));
flushError();
threadPool.reset();
pool.reset();
InfoL;
}
std::shared_ptr<ThreadPool> threadPool;
mutex error_query_mutex;
class sqlQuery
{
public:
sqlQuery(const string &sql,int cnt):sql_str(sql),tryCnt(cnt){}
string sql_str;
int tryCnt = 0;
} ;
deque<sqlQuery> error_query;
std::shared_ptr<PoolType> pool;
AsyncTaskThread asyncTaskThread;
unsigned int poolsize;
}
;
typedef _SqlPool<1> SqlPool;
class SqlStream {
public:
SqlStream(const char *_sql) :
sql(_sql) {
startPos = 0;
}
~SqlStream() {
}
template<typename T>
SqlStream& operator <<(const T& data) {
auto pos = sql.find_first_of('?', startPos);
if (pos == string::npos) {
return *this;
}
str_tmp.str("");
str_tmp << data;
string str = str_tmp.str();
startPos = pos + str.size();
sql.replace(pos, 1, str);
return *this;
}
const string& operator <<(std::ostream&(*f)(std::ostream&)) const {
return sql;
}
private:
stringstream str_tmp;
string sql;
string::size_type startPos;
};
class SqlWriter {
public:
SqlWriter(const char *_sql,bool _throwAble = true) :
sqlstream(_sql),throwAble(_throwAble) {
}
~SqlWriter() {
}
template<typename T>
SqlWriter& operator <<(const T& data) {
sqlstream << data;
return *this;
}
void operator <<(std::ostream&(*f)(std::ostream&)) {
SqlPool::Instance().query(sqlstream << endl);
}
int64_t operator <<(vector<vector<string>> &ret) {
affectedRows = SqlPool::Instance().query(rowId,ret, sqlstream << endl);
if(affectedRows < 0 && throwAble){
throw std::runtime_error("operate database failed");
}
return affectedRows;
}
int64_t getRowID() const {
return rowId;
}
int64_t getAffectedRows() const {
return affectedRows;
}
private:
SqlStream sqlstream;
int64_t rowId = 0;
int64_t affectedRows = -1;
bool throwAble = true;
};
} /* namespace mysql */
} /* namespace im */
#endif /* SQL_SQLPOOL_H_ */

View File

@@ -0,0 +1,116 @@
/*
* TimeTicker.h
*
* Created on: 2015年12月30日
* Author: root
*/
#ifndef UTIL_TIMETICKER_H_
#define UTIL_TIMETICKER_H_
#include "logger.h"
#include "Util/util.h"
namespace ZL {
namespace Util {
class Ticker {
public:
Ticker(int64_t _minMs = 0, const char *_where = "",
LogInfoMaker && _stream = LogInfoMaker(LWarn, __FILE__, "", __LINE__),bool printLog=false) :
stream(_stream) {
if(!printLog){
stream.clear();
}
begin = getNowTime();
created = begin;
minMs = _minMs;
where = _where;
}
virtual ~Ticker() {
int64_t tm = getNowTime() - begin;
if (tm > minMs) {
stream << where << " take time:" << tm << endl;
} else {
stream.clear();
}
}
uint64_t elapsedTime() {
stream.clear();
return getNowTime() - begin;
}
uint64_t createdTime() {
stream.clear();
return getNowTime() - created;
}
void resetTime() {
stream.clear();
begin = getNowTime();
}
private:
inline static uint64_t getNowTime() {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
uint64_t begin;
uint64_t created;
LogInfoMaker stream;
const char *where;
int64_t minMs;
};
class SmoothTicker {
public:
SmoothTicker(uint64_t _resetMs = 10000) {
resetMs = _resetMs;
ticker.resetTime();
}
virtual ~SmoothTicker() {
}
uint64_t elapsedTime() {
auto nowTime = ticker.elapsedTime();
if (firstTime == 0) {
firstTime = nowTime;
lastTime = nowTime;
pktCount = 0;
return nowTime;
}
uint64_t elapseTime = (nowTime - firstTime);
uint64_t retTime = lastTime + elapseTime / ++pktCount;
lastTime = retTime;
if (elapseTime > 10000) {
firstTime = 0;
}
return retTime;
}
void resetTime(){
firstTime = 0;
pktCount = 0;
lastTime = 0;
ticker.resetTime();
}
private:
uint64_t firstTime = 0;
uint64_t pktCount = 0;
uint64_t lastTime = 0;
uint64_t resetMs;
Ticker ticker;
};
#if defined(_DEBUG)
#define TimeTicker() Ticker(5,"",WarnL,true)
#define TimeTicker1(tm) Ticker(tm,"",WarnL,true)
#define TimeTicker2(tm,where) Ticker(tm,where,WarnL,true)
#define TimeTicker3(tm,where,log) Ticker(tm,where,log,true)
#else
#define TimeTicker()
#define TimeTicker1(tm)
#define TimeTicker2(tm,where)
#define TimeTicker3(tm,where,log)
#endif
} /* namespace Util */
} /* namespace ZL */
#endif /* UTIL_TIMETICKER_H_ */

View File

@@ -0,0 +1,64 @@
/*
* functiontraits.h
*
* Created on: 2017年3月15日
* Author: xzl
*/
#ifndef SRC_UTIL_FUNCTION_TRAITS_H_
#define SRC_UTIL_FUNCTION_TRAITS_H_
#include <tuple>
using namespace std;
namespace ZL {
namespace Util {
template<typename T>
struct function_traits;
//普通函数
template<typename Ret, typename... Args>
struct function_traits<Ret(Args...)>
{
public:
enum { arity = sizeof...(Args) };
typedef Ret function_type(Args...);
typedef Ret return_type;
using stl_function_type = std::function<function_type>;
typedef Ret(*pointer)(Args...);
template<size_t I>
struct args
{
static_assert(I < arity, "index is out of range, index must less than sizeof Args");
using type = typename std::tuple_element<I, std::tuple<Args...> >::type;
};
};
//函数指针
template<typename Ret, typename... Args>
struct function_traits<Ret(*)(Args...)> : function_traits<Ret(Args...)>{};
//std::function
template <typename Ret, typename... Args>
struct function_traits<std::function<Ret(Args...)>> : function_traits<Ret(Args...)>{};
//member function
#define FUNCTION_TRAITS(...) \
template <typename ReturnType, typename ClassType, typename... Args>\
struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__> : function_traits<ReturnType(Args...)>{}; \
FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)
//函数对象
template<typename Callable>
struct function_traits : function_traits<decltype(&Callable::operator())>{};
} /* namespace Util */
} /* namespace ZL */
#endif /* SRC_UTIL_FUNCTION_TRAITS_H_ */

View File

@@ -0,0 +1,400 @@
/*
* logger.h
*
* Created on: 2016年8月3日
* Author: xzl
*/
#ifndef UTIL_LOGGER_H_
#define UTIL_LOGGER_H_
#include <iostream>
#include <fstream>
#include <sstream>
#include <deque>
#include <map>
#include <ctime>
#include <string.h>
#include <cstdlib>
#include <thread>
#include <memory>
#include <mutex>
#include <time.h>
#include <condition_variable>
#include "Util/util.h"
#include "Thread/semaphore.h"
using namespace std;
using namespace ZL::Thread;
namespace ZL {
namespace Util {
enum LogLevel {
LTrace = 0, LDebug, LInfo, LWarn, LError, LFatal,
};
static const char *LogLevelStr[] = { "trace", "debug", "info", "warn", "error",
"fatal" };
#define CLEAR_COLOR "\033[0m"
#define UNDERLINE "\033[4m"
static const char *COLOR[6][2] = { { "\033[44;37m", "\033[34m" }, {
"\033[42;37m", "\033[32m" }, { "\033[46;37m", "\033[36m" }, {
"\033[43;37m", "\033[33m" }, { "\033[45;37m", "\033[35m" }, {
"\033[41;37m", "\033[31m" } };
class Logger;
class LogWriter;
class LogChannel;
class LogInfo;
class LogInfoMaker;
typedef std::shared_ptr<LogInfo> LogInfo_ptr;
class LogChannel {
public:
LogChannel(const string& name, LogLevel level = LDebug,
const char* timeFormat = "%Y-%m-%d %H:%M:%S") :
_name(name), _level(level), _timeFormat(timeFormat) {
}
virtual ~LogChannel() {
}
virtual void write(const LogInfo_ptr & stream)=0;
const string &name() const {
return _name;
}
LogLevel level() const {
return _level;
}
const string &timeFormat() const {
return _timeFormat;
}
void setLevel(LogLevel level) {
_level = level;
}
void setDateFormat(const char* format) {
_timeFormat = format;
}
protected:
string _name;
LogLevel _level;
string _timeFormat;
};
class LogWriter {
public:
LogWriter() {
}
virtual ~LogWriter() {
}
virtual void write(const LogInfo_ptr &stream) =0;
};
class Logger {
public:
friend class LogWriter;
friend class AsyncLogWriter;
static Logger& Instance() {
static Logger *logger(new Logger());
return *logger;
}
static void Destory() {
delete &Logger::Instance();
}
void add(const std::shared_ptr<LogChannel> &&channel) {
channels[channel->name()] = channel;
}
void del(const string& name) {
auto it = channels.find(name);
if (it != channels.end()) {
channels.erase(it);
}
}
std::shared_ptr<LogChannel> get(const string& name){
auto it = channels.find(name);
if(it == channels.end()){
return nullptr;
}
return it->second;
}
void setWriter(const std::shared_ptr<LogWriter> &&_writer) {
if (_writer) {
this->writer = _writer;
}
}
void write(const LogInfo_ptr &stream) {
if (writer) {
writer->write(stream);
return;
}
for (auto &chn : channels) {
chn.second->write(stream);
}
}
void setLevel(LogLevel level) {
for (auto &chn : channels) {
chn.second->setLevel(level);
}
}
protected:
Logger() {
}
~Logger() {
}
// Non-copyable and non-movable
Logger(const Logger&); // = delete;
Logger(Logger&&); // = delete;
Logger& operator=(const Logger&); // = delete;
Logger& operator=(Logger&&); // = delete;
map<string, std::shared_ptr<LogChannel> > channels;
std::shared_ptr<LogWriter> writer;
};
class LogInfo {
public:
friend class LogInfoMaker;
void format(ostream& ost, const char *timeFormat = "%Y-%m-%d %H:%M:%S",
bool enableColor = true) {
static string appName = exeName();
ost << appName << " "<< file << " " << line << "\r\n ";
if (enableColor) {
ost << COLOR[level][1];
}
if (timeFormat) {
ost << print(toLocal(ts), timeFormat);
}
ost << " [" << LogLevelStr[level] << "] ";
ost << function << " ";
ost << message.str();
if (enableColor) {
ost << CLEAR_COLOR;
}
ost.flush();
}
LogLevel getLevel() const {
return level;
}
private:
LogInfo(LogLevel _level, const char* _file, const char* _function,
int _line) :
level(_level), line(_line), file(_file), function(_function), ts(
::time(NULL)) {
}
std::string print(const std::tm& dt, const char* fmt) {
/*
#if defined(__WIN32__)
// BOGUS hack done for VS2012: C++11 non-conformant since it SHOULD take a "const struct tm* "
// ref. C++11 standard: ISO/IEC 14882:2011, <20> 27.7.1,
std::ostringstream oss;
oss << std::put_time(const_cast<std::tm*>(&dt), fmt);
return oss.str();
#else // LINUX
*/
const size_t size = 1024;
char buffer[size];
auto success = std::strftime(buffer, size, fmt, &dt);
if (0 == success)
return string(fmt);
return buffer;
//#endif
}
std::tm toLocal(const std::time_t& time) {
std::tm tm_snapshot;
#if defined(_WIN32)
localtime_s(&tm_snapshot, &time); // thread-safe?
#else
localtime_r(&time, &tm_snapshot); // POSIX
#endif //WIN32
return tm_snapshot;
}
LogLevel level;
int line;
string file;
string function;
time_t ts;
ostringstream message;
};
class LogInfoMaker {
public:
LogInfoMaker(LogLevel level, const char* file, const char* function,
int line) :
logInfo(new LogInfo(level, file, function, line)) {
}
LogInfoMaker(LogInfoMaker &&that) {
this->logInfo = that.logInfo;
that.logInfo.reset();
}
LogInfoMaker(const LogInfoMaker &that) {
this->logInfo = that.logInfo;
(const_cast<LogInfoMaker &>(that)).logInfo.reset();
}
~LogInfoMaker() {
*this << endl;
}
template<typename T>
LogInfoMaker& operator <<(const T& data) {
if (!logInfo) {
return *this;
}
logInfo->message << data;
return *this;
}
LogInfoMaker& operator <<(const char *data) {
if (!logInfo) {
return *this;
}
if(data){
logInfo->message << data;
}
return *this;
}
LogInfoMaker& operator <<(ostream&(*f)(ostream&)) {
if (!logInfo) {
return *this;
}
logInfo->message << f;
Logger::Instance().write(logInfo);
logInfo.reset();
return *this;
}
void clear() {
logInfo.reset();
}
private:
LogInfo_ptr logInfo;
};
class AsyncLogWriter: public LogWriter {
public:
AsyncLogWriter() :
exit_flag(false) {
_thread.reset(new thread([this]() {this->run();}));
}
virtual ~AsyncLogWriter() {
exit_flag = true;
sem.post();
_thread->join();
while (_pending.size()) {
auto &next = _pending.front();
realWrite(next);
_pending.pop_front();
}
}
virtual void write(const LogInfo_ptr &stream) {
{
lock_guard<mutex> lock(_mutex);
_pending.push_back(stream);
}
sem.post();
}
protected:
void run() {
while (!exit_flag) {
sem.wait();
{
lock_guard<mutex> lock(_mutex);
if (_pending.size()) {
auto &next = _pending.front();
realWrite(next);
_pending.pop_front();
}
}
}
}
inline void realWrite(const LogInfo_ptr &stream) {
for (auto &chn : Logger::Instance().channels) {
chn.second->write(stream);
}
}
bool exit_flag;
std::shared_ptr<thread> _thread;
deque<LogInfo_ptr> _pending;
semaphore sem;
mutex _mutex;
};
class ConsoleChannel: public LogChannel {
public:
ConsoleChannel(const string& name, LogLevel level = LDebug,
const char* timeFormat = "%Y-%m-%d %H:%M:%S") :
LogChannel(name, level, timeFormat) {
}
virtual ~ConsoleChannel() {
}
void write(const LogInfo_ptr &logInfo) {
if (level() > logInfo->getLevel()) {
return;
}
logInfo->format(std::cout, timeFormat().c_str(), true);
}
};
class FileChannel: public LogChannel {
public:
FileChannel(const string& name, const string& path, LogLevel level = LDebug,
const char* timeFormat = "%Y-%m-%d %H:%M:%S") :
LogChannel(name, level, timeFormat), _path(path) {
}
virtual ~FileChannel() {
close();
}
virtual void write(const std::shared_ptr<LogInfo> &stream) {
if (level() > stream->getLevel()) {
return;
}
if (!_fstream.is_open()) {
open();
}
stream->format(_fstream, timeFormat().c_str(), false);
}
void setPath(const string& path) {
_path = path;
open();
}
const string &path() const {
return _path;
}
protected:
virtual void open() {
// Ensure a path was set
if (_path.empty()) {
throw runtime_error("Log file path must be set.");
}
// Open the file stream
_fstream.close();
_fstream.open(_path.c_str(), ios::out | ios::app);
// Throw on failure
if (!_fstream.is_open()) {
throw runtime_error("Failed to open log file: " + _path);
}
}
virtual void close() {
_fstream.close();
}
ofstream _fstream;
string _path;
};
#define TraceL LogInfoMaker(LTrace, __FILE__,__FUNCTION__, __LINE__)
#define DebugL LogInfoMaker(LDebug, __FILE__,__FUNCTION__, __LINE__)
#define InfoL LogInfoMaker(LInfo, __FILE__,__FUNCTION__, __LINE__)
#define WarnL LogInfoMaker(LWarn,__FILE__, __FUNCTION__, __LINE__)
#define ErrorL LogInfoMaker(LError,__FILE__, __FUNCTION__, __LINE__)
#define FatalL LogInfoMaker(LFatal,__FILE__, __FUNCTION__, __LINE__)
} /* namespace util */
} /* namespace ZL */
#endif /* UTIL_LOGGER_H_ */

View File

@@ -0,0 +1,149 @@
#ifndef UTIL_MINI_H
#define UTIL_MINI_H
#include <map>
#include <string>
#include <vector>
#include <fstream>
#include <cstring>
#include <cassert>
#include <iostream>
#include <exception>
#include "Util/util.h"
using namespace std;
namespace ZL {
namespace Util {
template<typename key, typename variant>
class mINI_basic: public map<key, variant> {
// Public API : existing map<> interface plus following methods
public:
void parse(const string &text) {
// reset, split lines and parse
static auto trim = []( string line ) {
while( line.size() && ( line.back()=='\t' || line.back()==' ' ) ) line.pop_back();
while( line.size() && ( line.front()=='\t' || line.front()==' ' ) ) line.erase(0,1);
return line;
};
vector<string> lines = tokenize(text, "\r\n");
string symbol, tag;
for (auto &line : lines){
// trim blanks
line = trim(line);
// split line into tokens and parse tokens
if(line.empty() || line.front() == ';' || line.front() == '#'){
continue;
}
if (line.size() >= 3 && line.front() == '[' && line.back() == ']') {
tag = trim(line.substr(1, line.size() - 2));
} else {
auto at = line.find_first_of('=');
symbol = trim(tag + "." + line.substr(0, at));
(*this)[symbol] = (at == string::npos ? string() : trim(line.substr(at + 1)));
}
}
}
void parseFile(const string &fileName = exePath() + ".ini") {
ifstream in(fileName, ios::in | ios::binary | ios::ate);
if (!in.good()) {
stringstream ss;
ss << "invalid ini file:" << fileName;
throw invalid_argument(ss.str());
}
long size = in.tellg();
in.seekg(0, ios::beg);
string buf;
buf.resize(size);
in.read((char *) buf.data(), size);
parse(buf);
}
string dump(const string &header = "; auto-generated by mINI class {",
const string &footer = "; } ---") const {
string output(header + (header.empty() ? "" : "\r\n")), tag;
for (auto &pr : *this) {
vector<string> kv = tokenize(pr.first, ".");
if (tag != kv[0]) {
output += "\r\n[" + (tag = kv[0]) + "]\r\n";
}
output += kv[1] + "=" + pr.second + "\r\n";
}
return output + "\r\n" + footer + (footer.empty() ? "" : "\r\n");
}
void dumpFile(const string &fileName = exePath() + ".ini") {
ofstream out(fileName, ios::out | ios::binary | ios::trunc);
auto dmp = dump();
out.write(dmp.data(),dmp.size());
}
static mINI_basic &Instance(){
static mINI_basic instance;
return instance;
}
private:
vector<string> tokenize(const string &self, const string &chars) const {
vector<string> tokens(1);
string map(256, '\0');
for (const unsigned char &ch : chars) {
map[ch] = '\1';
}
for (const unsigned char &ch : self) {
if (!map.at(ch)) {
tokens.back().push_back(char(ch));
} else if (tokens.back().size()) {
tokens.push_back(string());
}
}
while (tokens.size() && tokens.back().empty()) {
tokens.pop_back();
}
return tokens;
}
};
// handy variant class as key/values
struct variant: public string {
template<typename T>
variant(const T &t) :
string(to_string(t)) {
}
template<size_t N>
variant(const char (&s)[N]) :
string(s, N) {
}
variant(const char *cstr) :
string(cstr) {
}
variant(const string &other = string()) :
string(other) {
}
template<typename T>
operator T() const {
T t;
stringstream ss;
return ss << *this && ss >> t ? t : T();
}
template<typename T> bool operator ==(const T &t) const {
return 0 == this->compare(variant(t));
}
bool operator ==(const char *t) const {
return this->compare(t) == 0;
}
template<typename T>
T as() const {
return (T) (*this);
}
};
using mINI = mINI_basic<string, variant>;
} // namespace Util
} // namespace ZL
#endif //UTIL_MINI_H

View File

@@ -0,0 +1,44 @@
/*
* onceToken.h
*
* Created on: 2016年8月10日
* Author: xzl
*/
#ifndef UTIL_ONCETOKEN_H_
#define UTIL_ONCETOKEN_H_
#include "functional"
using namespace std;
namespace ZL {
namespace Util {
class onceToken {
public:
typedef function<void(void)> task;
onceToken(const task &onConstructed, const task &_onDestructed) {
if (onConstructed) {
onConstructed();
}
onDestructed = _onDestructed;
}
virtual ~onceToken() {
if (onDestructed) {
onDestructed();
}
}
private:
onceToken();
onceToken(const onceToken &);
onceToken(onceToken &&);
onceToken &operator =(const onceToken &);
onceToken &operator =(onceToken &&);
task onDestructed;
};
} /* namespace Util */
} /* namespace ZL */
#endif /* UTIL_ONCETOKEN_H_ */

View File

@@ -0,0 +1,79 @@
/*
* util.h
*
* Created on: 2016年8月4日
* Author: xzl
*/
#ifndef UTIL_UTIL_H_
#define UTIL_UTIL_H_
#if defined(_WIN32)
#include <WinSock2.h>
#pragma comment (lib,"WS2_32")
#else
#include <unistd.h>
#include <sys/time.h>
#endif // defined(_WIN32)
#include <stdio.h>
#include <string.h>
#include <string>
#include <sstream>
using namespace std;
namespace ZL {
namespace Util {
class _StrPrinter {
public:
_StrPrinter() {
}
template<typename T>
_StrPrinter& operator <<(const T& data) {
ss << data;
return *this;
}
string operator <<(std::ostream&(*f)(std::ostream&)) const {
return ss.str();
}
private:
stringstream ss;
};
#define StrPrinter _StrPrinter()
string makeRandStr(int sz, bool printable = true);
string hexdump(const void *buf, size_t len);
string exePath();
string exeDir();
string exeName();
void setExePath(const string &path);
#ifndef bzero
#define bzero(ptr,size) memset((ptr),0,(size));
#endif //bzero
#if defined(ANDROID)
template <typename T>
std::string to_string(T value){
std::ostringstream os ;
os << std::forward<T>(value);
return os.str() ;
}
#endif//ANDROID
#if defined(_WIN32)
int gettimeofday(struct timeval *tp, void *tzp);
int strcasecmp(const char *strA,const char *strB);
void usleep(int micro_seconds);
void sleep(int second);
#endif //WIN32
} // namespace Util
} // namespace ZL
#endif /* UTIL_UTIL_H_ */

View File

@@ -0,0 +1,522 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef UV_ERRNO_H_
#define UV_ERRNO_H_
#include <errno.h>
#define UV__EOF (-4095)
#define UV__UNKNOWN (-4094)
#define UV__EAI_ADDRFAMILY (-3000)
#define UV__EAI_AGAIN (-3001)
#define UV__EAI_BADFLAGS (-3002)
#define UV__EAI_CANCELED (-3003)
#define UV__EAI_FAIL (-3004)
#define UV__EAI_FAMILY (-3005)
#define UV__EAI_MEMORY (-3006)
#define UV__EAI_NODATA (-3007)
#define UV__EAI_NONAME (-3008)
#define UV__EAI_OVERFLOW (-3009)
#define UV__EAI_SERVICE (-3010)
#define UV__EAI_SOCKTYPE (-3011)
#define UV__EAI_BADHINTS (-3013)
#define UV__EAI_PROTOCOL (-3014)
/* Only map to the system errno on non-Windows platforms. It's apparently
* a fairly common practice for Windows programmers to redefine errno codes.
*/
#if defined(E2BIG) && !defined(_WIN32)
# define UV__E2BIG (-E2BIG)
#else
# define UV__E2BIG (-4093)
#endif
#if defined(EACCES) && !defined(_WIN32)
# define UV__EACCES (-EACCES)
#else
# define UV__EACCES (-4092)
#endif
#if defined(EADDRINUSE) && !defined(_WIN32)
# define UV__EADDRINUSE (-EADDRINUSE)
#else
# define UV__EADDRINUSE (-4091)
#endif
#if defined(EADDRNOTAVAIL) && !defined(_WIN32)
# define UV__EADDRNOTAVAIL (-EADDRNOTAVAIL)
#else
# define UV__EADDRNOTAVAIL (-4090)
#endif
#if defined(EAFNOSUPPORT) && !defined(_WIN32)
# define UV__EAFNOSUPPORT (-EAFNOSUPPORT)
#else
# define UV__EAFNOSUPPORT (-4089)
#endif
#if defined(EAGAIN) && !defined(_WIN32)
# define UV__EAGAIN (-EAGAIN)
#else
# define UV__EAGAIN (-4088)
#endif
#if defined(EALREADY) && !defined(_WIN32)
# define UV__EALREADY (-EALREADY)
#else
# define UV__EALREADY (-4084)
#endif
#if defined(EBADF) && !defined(_WIN32)
# define UV__EBADF (-EBADF)
#else
# define UV__EBADF (-4083)
#endif
#if defined(EBUSY) && !defined(_WIN32)
# define UV__EBUSY (-EBUSY)
#else
# define UV__EBUSY (-4082)
#endif
#if defined(ECANCELED) && !defined(_WIN32)
# define UV__ECANCELED (-ECANCELED)
#else
# define UV__ECANCELED (-4081)
#endif
#if defined(ECHARSET) && !defined(_WIN32)
# define UV__ECHARSET (-ECHARSET)
#else
# define UV__ECHARSET (-4080)
#endif
#if defined(ECONNABORTED) && !defined(_WIN32)
# define UV__ECONNABORTED (-ECONNABORTED)
#else
# define UV__ECONNABORTED (-4079)
#endif
#if defined(ECONNREFUSED) && !defined(_WIN32)
# define UV__ECONNREFUSED (-ECONNREFUSED)
#else
# define UV__ECONNREFUSED (-4078)
#endif
#if defined(ECONNRESET) && !defined(_WIN32)
# define UV__ECONNRESET (-ECONNRESET)
#else
# define UV__ECONNRESET (-4077)
#endif
#if defined(EDESTADDRREQ) && !defined(_WIN32)
# define UV__EDESTADDRREQ (-EDESTADDRREQ)
#else
# define UV__EDESTADDRREQ (-4076)
#endif
#if defined(EEXIST) && !defined(_WIN32)
# define UV__EEXIST (-EEXIST)
#else
# define UV__EEXIST (-4075)
#endif
#if defined(EFAULT) && !defined(_WIN32)
# define UV__EFAULT (-EFAULT)
#else
# define UV__EFAULT (-4074)
#endif
#if defined(EHOSTUNREACH) && !defined(_WIN32)
# define UV__EHOSTUNREACH (-EHOSTUNREACH)
#else
# define UV__EHOSTUNREACH (-4073)
#endif
#if defined(EINTR) && !defined(_WIN32)
# define UV__EINTR (-EINTR)
#else
# define UV__EINTR (-4072)
#endif
#if defined(EINVAL) && !defined(_WIN32)
# define UV__EINVAL (-EINVAL)
#else
# define UV__EINVAL (-4071)
#endif
#if defined(EIO) && !defined(_WIN32)
# define UV__EIO (-EIO)
#else
# define UV__EIO (-4070)
#endif
#if defined(EISCONN) && !defined(_WIN32)
# define UV__EISCONN (-EISCONN)
#else
# define UV__EISCONN (-4069)
#endif
#if defined(EISDIR) && !defined(_WIN32)
# define UV__EISDIR (-EISDIR)
#else
# define UV__EISDIR (-4068)
#endif
#if defined(ELOOP) && !defined(_WIN32)
# define UV__ELOOP (-ELOOP)
#else
# define UV__ELOOP (-4067)
#endif
#if defined(EMFILE) && !defined(_WIN32)
# define UV__EMFILE (-EMFILE)
#else
# define UV__EMFILE (-4066)
#endif
#if defined(EMSGSIZE) && !defined(_WIN32)
# define UV__EMSGSIZE (-EMSGSIZE)
#else
# define UV__EMSGSIZE (-4065)
#endif
#if defined(ENAMETOOLONG) && !defined(_WIN32)
# define UV__ENAMETOOLONG (-ENAMETOOLONG)
#else
# define UV__ENAMETOOLONG (-4064)
#endif
#if defined(ENETDOWN) && !defined(_WIN32)
# define UV__ENETDOWN (-ENETDOWN)
#else
# define UV__ENETDOWN (-4063)
#endif
#if defined(ENETUNREACH) && !defined(_WIN32)
# define UV__ENETUNREACH (-ENETUNREACH)
#else
# define UV__ENETUNREACH (-4062)
#endif
#if defined(ENFILE) && !defined(_WIN32)
# define UV__ENFILE (-ENFILE)
#else
# define UV__ENFILE (-4061)
#endif
#if defined(ENOBUFS) && !defined(_WIN32)
# define UV__ENOBUFS (-ENOBUFS)
#else
# define UV__ENOBUFS (-4060)
#endif
#if defined(ENODEV) && !defined(_WIN32)
# define UV__ENODEV (-ENODEV)
#else
# define UV__ENODEV (-4059)
#endif
#if defined(ENOENT) && !defined(_WIN32)
# define UV__ENOENT (-ENOENT)
#else
# define UV__ENOENT (-4058)
#endif
#if defined(ENOMEM) && !defined(_WIN32)
# define UV__ENOMEM (-ENOMEM)
#else
# define UV__ENOMEM (-4057)
#endif
#if defined(ENONET) && !defined(_WIN32)
# define UV__ENONET (-ENONET)
#else
# define UV__ENONET (-4056)
#endif
#if defined(ENOSPC) && !defined(_WIN32)
# define UV__ENOSPC (-ENOSPC)
#else
# define UV__ENOSPC (-4055)
#endif
#if defined(ENOSYS) && !defined(_WIN32)
# define UV__ENOSYS (-ENOSYS)
#else
# define UV__ENOSYS (-4054)
#endif
#if defined(ENOTCONN) && !defined(_WIN32)
# define UV__ENOTCONN (-ENOTCONN)
#else
# define UV__ENOTCONN (-4053)
#endif
#if defined(ENOTDIR) && !defined(_WIN32)
# define UV__ENOTDIR (-ENOTDIR)
#else
# define UV__ENOTDIR (-4052)
#endif
#if defined(ENOTEMPTY) && !defined(_WIN32)
# define UV__ENOTEMPTY (-ENOTEMPTY)
#else
# define UV__ENOTEMPTY (-4051)
#endif
#if defined(ENOTSOCK) && !defined(_WIN32)
# define UV__ENOTSOCK (-ENOTSOCK)
#else
# define UV__ENOTSOCK (-4050)
#endif
#if defined(ENOTSUP) && !defined(_WIN32)
# define UV__ENOTSUP (-ENOTSUP)
#else
# define UV__ENOTSUP (-4049)
#endif
#if defined(EPERM) && !defined(_WIN32)
# define UV__EPERM (-EPERM)
#else
# define UV__EPERM (-4048)
#endif
#if defined(EPIPE) && !defined(_WIN32)
# define UV__EPIPE (-EPIPE)
#else
# define UV__EPIPE (-4047)
#endif
#if defined(EPROTO) && !defined(_WIN32)
# define UV__EPROTO (-EPROTO)
#else
# define UV__EPROTO (-4046)
#endif
#if defined(EPROTONOSUPPORT) && !defined(_WIN32)
# define UV__EPROTONOSUPPORT (-EPROTONOSUPPORT)
#else
# define UV__EPROTONOSUPPORT (-4045)
#endif
#if defined(EPROTOTYPE) && !defined(_WIN32)
# define UV__EPROTOTYPE (-EPROTOTYPE)
#else
# define UV__EPROTOTYPE (-4044)
#endif
#if defined(EROFS) && !defined(_WIN32)
# define UV__EROFS (-EROFS)
#else
# define UV__EROFS (-4043)
#endif
#if defined(ESHUTDOWN) && !defined(_WIN32)
# define UV__ESHUTDOWN (-ESHUTDOWN)
#else
# define UV__ESHUTDOWN (-4042)
#endif
#if defined(ESPIPE) && !defined(_WIN32)
# define UV__ESPIPE (-ESPIPE)
#else
# define UV__ESPIPE (-4041)
#endif
#if defined(ESRCH) && !defined(_WIN32)
# define UV__ESRCH (-ESRCH)
#else
# define UV__ESRCH (-4040)
#endif
#if defined(ETIMEDOUT) && !defined(_WIN32)
# define UV__ETIMEDOUT (-ETIMEDOUT)
#else
# define UV__ETIMEDOUT (-4039)
#endif
#if defined(ETXTBSY) && !defined(_WIN32)
# define UV__ETXTBSY (-ETXTBSY)
#else
# define UV__ETXTBSY (-4038)
#endif
#if defined(EXDEV) && !defined(_WIN32)
# define UV__EXDEV (-EXDEV)
#else
# define UV__EXDEV (-4037)
#endif
#if defined(EFBIG) && !defined(_WIN32)
# define UV__EFBIG (-EFBIG)
#else
# define UV__EFBIG (-4036)
#endif
#if defined(ENOPROTOOPT) && !defined(_WIN32)
# define UV__ENOPROTOOPT (-ENOPROTOOPT)
#else
# define UV__ENOPROTOOPT (-4035)
#endif
#if defined(ERANGE) && !defined(_WIN32)
# define UV__ERANGE (-ERANGE)
#else
# define UV__ERANGE (-4034)
#endif
#if defined(ENXIO) && !defined(_WIN32)
# define UV__ENXIO (-ENXIO)
#else
# define UV__ENXIO (-4033)
#endif
#if defined(EMLINK) && !defined(_WIN32)
# define UV__EMLINK (-EMLINK)
#else
# define UV__EMLINK (-4032)
#endif
/* EHOSTDOWN is not visible on BSD-like systems when _POSIX_C_SOURCE is
* defined. Fortunately, its value is always 64 so it's possible albeit
* icky to hard-code it.
*/
#if defined(EHOSTDOWN) && !defined(_WIN32)
# define UV__EHOSTDOWN (-EHOSTDOWN)
#elif defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
defined(__NetBSD__) || \
defined(__OpenBSD__)
# define UV__EHOSTDOWN (-64)
#else
# define UV__EHOSTDOWN (-4031)
#endif
#if defined(EREMOTEIO) && !defined(_WIN32)
# define UV__EREMOTEIO (-EREMOTEIO)
#else
# define UV__EREMOTEIO (-4030)
#endif
#define UV_ERRNO_MAP(XX) \
XX(E2BIG, "argument list too long") \
XX(EACCES, "permission denied") \
XX(EADDRINUSE, "address already in use") \
XX(EADDRNOTAVAIL, "address not available") \
XX(EAFNOSUPPORT, "address family not supported") \
XX(EAGAIN, "resource temporarily unavailable") \
XX(EAI_ADDRFAMILY, "address family not supported") \
XX(EAI_AGAIN, "temporary failure") \
XX(EAI_BADFLAGS, "bad ai_flags value") \
XX(EAI_BADHINTS, "invalid value for hints") \
XX(EAI_CANCELED, "request canceled") \
XX(EAI_FAIL, "permanent failure") \
XX(EAI_FAMILY, "ai_family not supported") \
XX(EAI_MEMORY, "out of memory") \
XX(EAI_NODATA, "no address") \
XX(EAI_NONAME, "unknown node or service") \
XX(EAI_OVERFLOW, "argument buffer overflow") \
XX(EAI_PROTOCOL, "resolved protocol is unknown") \
XX(EAI_SERVICE, "service not available for socket type") \
XX(EAI_SOCKTYPE, "socket type not supported") \
XX(EALREADY, "connection already in progress") \
XX(EBADF, "bad file descriptor") \
XX(EBUSY, "resource busy or locked") \
XX(ECANCELED, "operation canceled") \
XX(ECHARSET, "invalid Unicode character") \
XX(ECONNABORTED, "software caused connection abort") \
XX(ECONNREFUSED, "connection refused") \
XX(ECONNRESET, "connection reset by peer") \
XX(EDESTADDRREQ, "destination address required") \
XX(EEXIST, "file already exists") \
XX(EFAULT, "bad address in system call argument") \
XX(EFBIG, "file too large") \
XX(EHOSTUNREACH, "host is unreachable") \
XX(EINTR, "interrupted system call") \
XX(EINVAL, "invalid argument") \
XX(EIO, "i/o error") \
XX(EISCONN, "socket is already connected") \
XX(EISDIR, "illegal operation on a directory") \
XX(ELOOP, "too many symbolic links encountered") \
XX(EMFILE, "too many open files") \
XX(EMSGSIZE, "message too long") \
XX(ENAMETOOLONG, "name too long") \
XX(ENETDOWN, "network is down") \
XX(ENETUNREACH, "network is unreachable") \
XX(ENFILE, "file table overflow") \
XX(ENOBUFS, "no buffer space available") \
XX(ENODEV, "no such device") \
XX(ENOENT, "no such file or directory") \
XX(ENOMEM, "not enough memory") \
XX(ENONET, "machine is not on the network") \
XX(ENOPROTOOPT, "protocol not available") \
XX(ENOSPC, "no space left on device") \
XX(ENOSYS, "function not implemented") \
XX(ENOTCONN, "socket is not connected") \
XX(ENOTDIR, "not a directory") \
XX(ENOTEMPTY, "directory not empty") \
XX(ENOTSOCK, "socket operation on non-socket") \
XX(ENOTSUP, "operation not supported on socket") \
XX(EPERM, "operation not permitted") \
XX(EPIPE, "broken pipe") \
XX(EPROTO, "protocol error") \
XX(EPROTONOSUPPORT, "protocol not supported") \
XX(EPROTOTYPE, "protocol wrong type for socket") \
XX(ERANGE, "result too large") \
XX(EROFS, "read-only file system") \
XX(ESHUTDOWN, "cannot send after transport endpoint shutdown") \
XX(ESPIPE, "invalid seek") \
XX(ESRCH, "no such process") \
XX(ETIMEDOUT, "connection timed out") \
XX(ETXTBSY, "text file is busy") \
XX(EXDEV, "cross-device link not permitted") \
XX(UNKNOWN, "unknown error") \
XX(EOF, "end of file") \
XX(ENXIO, "no such device or address") \
XX(EMLINK, "too many links") \
XX(EHOSTDOWN, "host is down") \
XX(EREMOTEIO, "remote I/O error") \
typedef enum {
#define XX(code, _) UV_ ## code = UV__ ## code,
UV_ERRNO_MAP(XX)
#undef XX
UV_ERRNO_MAX = UV__EOF - 1
} uv_errno_t;
const char* uv_err_name(int err);
const char* uv_strerror(int err);
int uv_translate_posix_error(int err);
int get_uv_error(bool netErr = false);
const char* get_uv_errmsg(bool netErr = false);
#endif /* UV_ERRNO_H_ */