add husky

This commit is contained in:
wyy 2013-10-27 05:51:57 -07:00
parent 51e160bf1d
commit b2d6fbbbe5
13 changed files with 958 additions and 4 deletions

View File

@ -2,7 +2,6 @@ CXX := g++
LD := g++
AR := ar rc
INCS := -I../limonp
DEBUG_CXXFLAGS := -g -Wall -DDEBUG
RELEASE_CXXFLAGS := -Wall -O3
@ -15,7 +14,9 @@ else
LDFLAGS := ${RELEASE_LDFLAGS}
endif
DOLINK := $(LD) $(LDFLAGS)
INCS := -I../limonp
LINK := -lpthread
SOURCES := $(wildcard *.cpp)
OBJS := $(patsubst %.cpp,%.o,$(SOURCES))
DEMOS := $(patsubst %.cpp,%.demo,$(SOURCES))
@ -23,19 +24,26 @@ DEMOS := $(patsubst %.cpp,%.demo,$(SOURCES))
CPPJIEBADIR := ../cppjieba
LIBCPPJIEBA := $(CPPJIEBADIR)/libcppjieba.a
HUSKYDIR := ../husky
LIBHUSKYA := $(HUSKYDIR)/libhusky.a
.PHONY: clean $(LIBCPPJIEBA)
all: $(DEMOS)
%.demo: %.cpp $(LIBCPPJIEBA)
$(CXX) -o $@ $(CXXFLAGS) $^ $(INCS)
%.demo: %.cpp $(LIBCPPJIEBA) $(LIBHUSKYA)
$(CXX) -o $@ $(CXXFLAGS) $^ $(INCS) $(LINK)
$(LIBCPPJIEBA):
cd $(CPPJIEBADIR) && $(MAKE)
$(LIBHUSKYA):
cd $(HUSKYDIR) && $(MAKE)
clean:
rm -f *.o *.ut *.d *.d.* $(DEMOS)
cd $(CPPJIEBADIR) && make clean
cd $(HUSKYDIR) && make clean
sinclude $(SOURCES:.cpp=.d)
%.d:%.cpp

4
demo/restart.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
sh start.sh
sh stop.sh

59
demo/server.cpp Normal file
View File

@ -0,0 +1,59 @@
#include <unistd.h>
#include <algorithm>
#include <string>
#include <ctype.h>
#include <string.h>
#include <ArgvContext.hpp>
#include "../husky/Daemon.h"
#include "../husky/ServerFrame.h"
#include "../cppjieba/MPSegment.h"
#include "../cppjieba/HMMSegment.h"
#include "../cppjieba/MixSegment.h"
using namespace Husky;
using namespace CppJieba;
const char * const DEFAULT_DICTPATH = "../dicts/jieba.dict.utf8";
const char * const DEFAULT_MODELPATH = "../dicts/hmm_model.utf8";
class ServerDemo: public IRequestHandler
{
public:
ServerDemo(){};
virtual ~ServerDemo(){};
virtual bool init(){return _segment.init(DEFAULT_DICTPATH, DEFAULT_MODELPATH);};
virtual bool dispose(){return _segment.dispose();};
public:
virtual bool do_GET(const HttpReqInfo& httpReq, string& strSnd)
{
//HttpReqInfo info = httpReq;
strSnd = httpReq.toString();
return true;
}
private:
MixSegment _segment;
};
int main(int argc,char* argv[])
{
if(argc != 7)
{
printf("usage: %s -n THREAD_NUMBER -p LISTEN_PORT -k start|stop\n",argv[0]);
return -1;
}
ArgvContext arg(argc, argv);
unsigned int port = atoi(arg["-p"].c_str());
unsigned int threadNum = atoi(arg["-n"].c_str());
ServerDemo s;
Daemon daemon(&s);
if(arg["-k"] == "start")
{
return !daemon.Start(port, threadNum);
}
else
{
return !daemon.Stop();
}
}

2
demo/start.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/sh
./server.demo -n 4 -p 11258 -k start >> run.log 2>&1 &

2
demo/stop.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/sh
./server.demo -n 4 -p 11258 -k stop

196
husky/Daemon.cpp Normal file
View File

@ -0,0 +1,196 @@
#include "Daemon.h"
namespace Husky
{
IRequestHandler * Daemon::m_pHandler;
ServerFrame Daemon::m_ServerFrame;
int Daemon::m_nChildPid = 0;
bool Daemon::isAbnormalExit(int pid, int status)
{
bool bRestart = true;
if (WIFEXITED(status)) //exit()or return
{
LogDebug("child normal termination, exit pid = %d, status = %d", pid, WEXITSTATUS(status));
bRestart = false;
}
else if (WIFSIGNALED(status)) //signal方式退出
{
LogError("abnormal termination, pid = %d, signal number = %d%s", pid, WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? " (core file generated)" :
#endif
"");
if (WTERMSIG(status) == SIGKILL)
{
bRestart = false;
LogError("has been killed by user , exit pid = %d, status = %d", pid, WEXITSTATUS(status));
}
}
else if (WIFSTOPPED(status)) //暂停的子进程退出
{
LogError("child stopped, pid = %d, signal number = %d", pid, WSTOPSIG(status));
}
else
{
LogError("child other reason quit, pid = %d, signal number = %d", pid, WSTOPSIG(status));
}
return bRestart;
}
bool Daemon::Start(unsigned int port, unsigned int threadNum)
{
string masterPidStr = loadFile2Str(MASTER_PID_FILE);
int masterPid = atoi(masterPidStr.c_str());
if(masterPid)
{
if (kill(masterPid, 0) == 0)
{
LogError("Another instance exist, ready to quit!");
return false;
}
}
initAsDaemon();
char buf[64];
sprintf(buf, "%d", getpid());
if (!WriteStr2File(MASTER_PID_FILE,buf ,"w"))
{
LogFatal("Write master pid fail!");
}
while(true)
{
pid_t pid = fork();
if (0 == pid)// child process do
{
signal(SIGUSR1, sigChildHandler);
signal(SIGPIPE, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
if(!m_pHandler->init())
{
LogFatal("m_pHandler init failed!");
return false;
}
if (!m_ServerFrame.CreateServer(port, threadNum, m_pHandler))
{
LogFatal("m_ServerFrame CreateServer(%d, %d, m_pHandler) fail!", port, threadNum);
return false;
}
#ifdef DEBUG
LogDebug("Worker init ok pid = %d",(int)getpid());
#endif
if (!m_ServerFrame.RunServer())
{
LogError("m_ServerFrame.RunServer finish -fail!");
return false;
}
#ifdef DEBUG
LogDebug("run finish -ok!");
#endif
if(!m_pHandler->dispose())
{
LogError("m_pHandler.dispose -fail!");
return false;
}
#ifdef DEBUG
LogDebug("Worker dispose -ok!");
#endif
exit(0);
}
m_nChildPid=pid;
int status;
pid = wait(&status);
if (!isAbnormalExit(pid, status))
{
LogDebug("child exit normally! and Daemon exit");
break;
}
}
return true;
}
bool Daemon::Stop()
{
string masterPidStr = loadFile2Str(MASTER_PID_FILE);
int masterPid = atoi(masterPidStr.c_str());
if(masterPid)
{
#ifdef DEBUG
LogDebug("read last masterPid[%d]",masterPid);
#endif
if (kill(masterPid, 0) == 0)
{
#ifdef DEBUG
LogDebug("find previous daemon pid= %d, current pid= %d", masterPid, getpid());
#endif
kill(masterPid, SIGTERM);
int tryTime = 200;
while (kill(masterPid, 0) == 0 && --tryTime)
{
sleep(1);
}
if (!tryTime && kill(masterPid, 0) == 0)
{
LogError("Time out shutdown fail!");
return false;
}
LogInfo("previous daemon pid[%d] shutdown ok.", masterPid);
return true;
}
}
LogError("Another instance doesn't exist, ready to quit!");
return false;
}
void Daemon::initAsDaemon()
{
if (fork() > 0)
exit(0);
setsid();
signal(SIGPIPE, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
signal(SIGTERM, sigMasterHandler);
signal(SIGINT, sigMasterHandler);
signal(SIGQUIT, sigMasterHandler);
signal(SIGKILL, sigMasterHandler);
}
void Daemon::sigMasterHandler(int sig)
{
kill(m_nChildPid,SIGUSR1);
LogDebug("master = %d sig child =%d!",getpid(),m_nChildPid);
}
void Daemon::sigChildHandler(int sig)
{
if (sig == SIGUSR1)
{
m_ServerFrame.CloseServer();
LogDebug("master = %d signal accept current pid =%d!",getppid(),getpid());
}
}
}

40
husky/Daemon.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef HUSKY_DAEMON_H_
#define HUSKY_DAEMON_H_
#include "globals.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <signal.h>
#include <logger.hpp>
#include "ServerFrame.h"
namespace Husky
{
using namespace Limonp;
class Daemon
{
public:
Daemon(IRequestHandler * pHandler)
{
m_pHandler = pHandler;
}
~Daemon(){};
public:
bool Start(unsigned int port, unsigned int threadNum);
bool Stop();
public:
static void initAsDaemon();
static void sigMasterHandler(int sig);
static void sigChildHandler(int sig);
static bool isAbnormalExit(int pid, int status);
private:
static IRequestHandler* m_pHandler;
static ServerFrame m_ServerFrame;
static int m_nChildPid;
};
}
#endif

172
husky/HttpReqInfo.hpp Normal file
View File

@ -0,0 +1,172 @@
#ifndef HUSKY_HTTP_REQINFO_H
#define HUSKY_HTTP_REQINFO_H
#include <iostream>
#include <string>
#include "globals.h"
#include <str_functs.hpp>
#include <logger.hpp>
#include <map_functs.hpp>
namespace Husky
{
using namespace Limonp;
static const char* const KEY_METHOD = "METHOD";
static const char* const KEY_PATH = "PATH";
static const char* const KEY_PROTOCOL = "PROTOCOL";
class HttpReqInfo
{
public:
bool load(const string& headerStr)
{
size_t lpos = 0, rpos = 0;
vector<string> buf;
rpos = headerStr.find("\n", lpos);
if(string::npos == rpos)
{
LogFatal("headerStr illegal.");
return false;
}
string firstline(headerStr, lpos, rpos - lpos);
trim(firstline);
if(!splitStr(firstline, buf, " ") || 3 != buf.size())
{
LogFatal("parse header first line failed.");
return false;
}
_headerMap[KEY_METHOD] = trim(buf[0]);
_headerMap[KEY_PATH] = trim(buf[1]);
_headerMap[KEY_PROTOCOL] = trim(buf[2]);
//first request line end
//parse path to _methodGetMap
if("GET" == _headerMap[KEY_METHOD])
{
_parseUrl(firstline, _methodGetMap);
}
lpos = rpos + 1;
if(lpos >= headerStr.size())
{
LogFatal("headerStr illegal");
return false;
}
//message header begin
while(lpos < headerStr.size() && string::npos != (rpos = headerStr.find('\n', lpos)) && rpos > lpos)
{
string s(headerStr, lpos, rpos - lpos);
size_t p = s.find(':');
if(string::npos == p)
{
break;//encounter empty line
}
string k(s, 0, p);
string v(s, p+1);
trim(k);
trim(v);
if(k.empty()||v.empty())
{
LogFatal("headerStr illegal.");
return false;
}
_headerMap[upperStr(k)] = v;
lpos = rpos + 1;
}
//message header end
//body begin
return true;
}
public:
string& operator[] (const string& key)
{
return _headerMap[key];
}
bool find(const string& key, string& res)const
{
return _find(_headerMap, key, res);
}
bool GET(const string& argKey, string& res)const
{
return _find(_methodGetMap, argKey, res);
}
bool POST(const string& argKey, string& res)const
{
return _find(_methodPostMap, argKey, res);
}
private:
HashMap<string, string> _headerMap;
HashMap<string, string> _methodGetMap;
HashMap<string, string> _methodPostMap;
private:
bool _find(const HashMap<string, string>& mp, const string& key, string& res)const
{
HashMap<string, string>::const_iterator it = mp.find(key);
if(it == mp.end())
{
return false;
}
res = it->second;
return true;
}
public:
//string toString() const;// function for debug because of heavy time consuming
string toString() const
{
string res("{");
res += HashMapToString(_headerMap);
res += ",";
res += HashMapToString(_methodGetMap);
res += ",";
res += HashMapToString(_methodPostMap);
res += "}";
return res;
}
private:
bool _parseUrl(const string& url, HashMap<string, string>& mp)
{
if(url.empty())
{
return false;
}
uint pos = url.find('?');
if(string::npos == pos)
{
return false;
}
uint kleft = 0, kright = 0;
uint vleft = 0, vright = 0;
for(uint i = pos + 1; i < url.size();)
{
kleft = i;
while(i < url.size() && url[i] != '=')
{
i++;
}
if(i >= url.size())
{
break;
}
kright = i;
i++;
vleft = i;
while(i < url.size() && url[i] != '&' && url[i] != ' ')
{
i++;
}
vright = i;
mp[url.substr(kleft, kright - kleft)] = url.substr(vleft, vright - vleft);
i++;
}
return true;
}
};
}
#endif

42
husky/Makefile Normal file
View File

@ -0,0 +1,42 @@
CXX := g++
LD := g++
AR := ar rc
DEBUG_CXXFLAGS := -g -Wall -DDEBUG
RELEASE_CXXFLAGS := -Wall -O3
ifeq (YES, ${RELEASE})
CXXFLAGS := ${RELEASE_CXXFLAGS}
LDFLAGS := ${RELEASE_LDFLAGS}
else
CXXFLAGS := ${DEBUG_CXXFLAGS}
LDFLAGS := ${DEBUG_LDFLAGS}
endif
DOLINK := $(LD) $(LDFLAGS) -o $@ $^
DOPACK := $(AR)
SOURCES = $(wildcard *.cpp)
OBJS := $(patsubst %.cpp,%.o,$(SOURCES))
INC := -I../limonp
LIBA := libhusky.a
.PHONY: clean
all: $(LIBA)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< $(INC)
${LIBA}: $(OBJS)
$(DOPACK) $@ $(OBJS)
clean:
rm -f *.o *.d *.d.* $(LIBA)
sinclude $(SOURCES:.cpp=.d)
%.d:%.cpp
@set -e; rm -f $@; \
$(CXX) -MM $< > $@.$$$$; \
sed 's,\($*\).o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$

227
husky/ServerFrame.cpp Normal file
View File

@ -0,0 +1,227 @@
#include "ServerFrame.h"
namespace Husky
{
const struct timeval ServerFrame::m_timev = {SOCKET_TIMEOUT, 0};
pthread_mutex_t ServerFrame::m_pmAccept;
bool ServerFrame::m_bShutdown = false;
bool ServerFrame::CloseServer()
{
m_bShutdown=true;
if (SOCKET_ERROR==closesocket(m_lsnSock))
{
LogError("error [%s]", strerror(errno));
return false;
}
int sockfd;
struct sockaddr_in dest;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
LogError("error [%s]", strerror(errno));
return false;
}
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(m_nLsnPort);
if (inet_aton("127.0.0.1", (struct in_addr *) &dest.sin_addr.s_addr) == 0)
{
LogError("error [%s]", strerror(errno));
return false;
}
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) < 0)
{
LogError("error [%s]", strerror(errno));
}
close(sockfd);
LogInfo("CloseServer ok.");
return true;
}
bool ServerFrame::RunServer()
{
if(SOCKET_ERROR==listen(m_lsnSock,LISEN_QUEUR_LEN))
{
LogError("error [%s]", strerror(errno));
return false;
}
ThreadManager thrMngr;
int i;
SPara para;
para.hSock=m_lsnSock;
para.pHandler=m_pHandler;
for (i=0;i<m_nThreadCount;i++)
{
if (0!=thrMngr.CreateThread(ServerThread, &para))
{
break;
}
}
LogDebug("expect thread count %d, real count %d",m_nThreadCount,i);
if(i==0)
{
LogError("error [%s]", strerror(errno));
return false;
}
LogInfo("server start to run.........");
if (thrMngr.WaitMultipleThread()!=0)
{
return false;
}
return true;
}
void* ServerFrame::ServerThread(void *lpParameter )
{
SPara *pPara=(SPara*)lpParameter;
SOCKET hSockLsn=pPara->hSock;
IRequestHandler *pHandler=pPara->pHandler;
int nRetCode;
linger lng;
char chRecvBuf[RECV_BUFFER];
SOCKET hClientSock;
string strHttpResp;
sockaddr_in clientaddr;
socklen_t nSize = sizeof(clientaddr);
while(!m_bShutdown)
{
HttpReqInfo httpReq;
pthread_mutex_lock(&m_pmAccept);
hClientSock=accept(hSockLsn,(sockaddr *)&clientaddr, &nSize);
pthread_mutex_unlock(&m_pmAccept);
if(hClientSock==SOCKET_ERROR)
{
if(!m_bShutdown)
LogError("error [%s]", strerror(errno));
continue;
}
httpReq[CLIENT_IP_K] = inet_ntoa(clientaddr.sin_addr);// inet_ntoa is not thread safety at some version
lng.l_linger=1;
lng.l_onoff=1;
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_LINGER,(char*)&lng,sizeof(lng)))
{
LogError("error [%s]", strerror(errno));
}
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_RCVTIMEO,(char*)&m_timev,sizeof(m_timev)))
{
LogError("error [%s]", strerror(errno));
}
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_SNDTIMEO,(char*)&m_timev,sizeof(m_timev)))
{
LogError("error [%s]", strerror(errno));
}
string strRec;
string strSnd;
memset(chRecvBuf,0,sizeof(chRecvBuf));
nRetCode = recv(hClientSock, chRecvBuf, RECV_BUFFER, 0);
strRec = chRecvBuf;
#ifdef DEBUG
LogDebug("response[%s]", strRec.c_str());
#endif
if(SOCKET_ERROR==nRetCode)
{
LogError("error [%s]", strerror(errno));
closesocket(hClientSock);
continue;
}
if(0==nRetCode)
{
LogDebug("connection has been gracefully closed");
closesocket(hClientSock);
continue;
}
httpReq.load(strRec);
pHandler->do_GET(httpReq, strSnd);
char chHttpHeader[2048];
sprintf(chHttpHeader, RESPONSE_FORMAT, RESPONSE_CHARSET_UTF8, strSnd.length());
strHttpResp=chHttpHeader;
strHttpResp+=strSnd;
if (SOCKET_ERROR==send(hClientSock,strHttpResp.c_str(),strHttpResp.length(),0))
{
LogError("error [%s]", strerror(errno));
}
#ifdef DEBUG
LogDebug("send response [%s] ", strHttpResp.c_str());
#endif
closesocket(hClientSock);
}
return 0;
}
bool ServerFrame::CreateServer(u_short nPort,u_short nThreadCount,IRequestHandler *pHandler)
{
m_nLsnPort=nPort;
m_nThreadCount=nThreadCount;
m_pHandler=pHandler;
if (!BindToLocalHost(m_lsnSock,m_nLsnPort))
{
return false;
}
pthread_mutex_init(&m_pmAccept,NULL);
LogInfo("CreatServer ok {port:%d, threadNum:%d}", nPort, nThreadCount);
return true;
}
bool ServerFrame::BindToLocalHost(SOCKET &sock,u_short nPort)
{
sock=socket(AF_INET,SOCK_STREAM,0);
if(INVALID_SOCKET==sock)
{
LogError("error [%s]", strerror(errno));
return false;
}
/* ʹµØÖ·ÂíÉÏ¿ÉÒÔÖØÓà */
int nRet = 1;
if(SOCKET_ERROR==setsockopt(m_lsnSock, SOL_SOCKET, SO_REUSEADDR, (char*)&nRet, sizeof(nRet)))
{
LogError("error [%s]", strerror(errno));
}
struct sockaddr_in addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(nPort);
addrSock.sin_addr.s_addr=htonl(INADDR_ANY);
int retval;
retval=bind(sock,(sockaddr*)&addrSock,sizeof(sockaddr));
if(SOCKET_ERROR==retval)
{
LogError("error [%s]", strerror(errno));
closesocket(sock);
return false;
}
return true;
}
}

78
husky/ServerFrame.h Normal file
View File

@ -0,0 +1,78 @@
#ifndef HUSKY_SERVERFRAME_H
#define HUSKY_SERVERFRAME_H
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <vector>
#include "globals.h"
#include "ThreadManager.hpp"
#include "HttpReqInfo.hpp"
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#define RECV_BUFFER 10240
#define LISEN_QUEUR_LEN 1024
namespace Husky
{
using namespace Limonp;
typedef int SOCKET;
class IRequestHandler
{
public:
virtual ~IRequestHandler(){};
public:
virtual bool init() = 0;
virtual bool dispose() = 0;
virtual bool do_GET(const HttpReqInfo& httpReq, string& res) = 0;
};
struct SPara
{
SOCKET hSock;
IRequestHandler * pHandler;
};
class ServerFrame
{
public:
ServerFrame(){};
~ServerFrame(){pthread_mutex_destroy(&m_pmAccept);};
bool CreateServer(u_short nPort,u_short nThreadCount,IRequestHandler *pHandler);
bool CloseServer();
bool RunServer();
protected:
bool BindToLocalHost(SOCKET &sock,u_short nPort);
static void * ServerThread(void * lpParameter );
private:
u_short m_nLsnPort;
u_short m_nThreadCount;
SOCKET m_lsnSock;
IRequestHandler *m_pHandler;
static bool m_bShutdown;
static pthread_mutex_t m_pmAccept;
static const struct timeval m_timev;
};
}
#endif

98
husky/ThreadManager.hpp Normal file
View File

@ -0,0 +1,98 @@
#ifndef HUSKY_THREAD_MANAGER_H
#define HUSKY_THREAD_MANAGER_H
#include <pthread.h>
#include <algorithm>
#include <vector>
#include <map>
#define INFINITE 0
namespace Husky
{
using namespace std;
class ThreadManager
{
private:
typedef int HANDLE;
typedef int DWORD;
typedef void *(* PThreadFunc)(void* param);
public:
ThreadManager(){;}
~ThreadManager(){}
unsigned int HandleCount(){return m_vecHandle.size();}
void clear()
{
m_vecHandle.clear();
}
HANDLE CreateThread( PThreadFunc pFunc,void *pPara)
{
pthread_t pt;
int nErrorCode=pthread_create(&pt,NULL,pFunc,pPara);
if(nErrorCode!=0)
return nErrorCode;
m_vecHandle.push_back(pt); //加入线程列表 为WaitForMultipleObjects准备
return nErrorCode;
}
//hThread (thread handler) : 为0时为默认最后一个加入管理器的线程句柄
//dwMilliseconds等待时间 : 单位毫秒,默认值无穷时间
//return value : -1句柄无效其他值 WaitForSingleObject函数的返回值
DWORD Wait(HANDLE hThread=0,DWORD dwMilliseconds=INFINITE )
{
if( hThread==0)//最后一个加入的线程
{
if(!m_vecHandle.empty())
{
return pthread_join(m_vecHandle.back(),NULL);
}
else
return -1;
}
else
{
if (find(m_vecHandle.begin(),m_vecHandle.end(),hThread)==m_vecHandle.end())//不存在此句柄
{
return -1;
}
return pthread_join(hThread, NULL);
}
}
//等待所有线程执行完毕
//bWaitAll是否所有线程 : 默认值1等待所有线程,0有任何线程结束此函数返回
//dwMilliseconds : 单位毫秒,默认值无穷时间
//return value : -1没有任何句柄其他值 WaitForMultipleObjects函数的返回值
DWORD WaitMultipleThread( bool bWaitAll=1,DWORD dwMilliseconds=INFINITE)
{
if (m_vecHandle.empty())
return -1;
int nErrorcode;
for (uint i=0;i<m_vecHandle.size();++i)
{
nErrorcode=pthread_join(m_vecHandle[i], NULL);
if (nErrorcode!=0)
return nErrorcode;
}
return 0;
}
private:
vector<pthread_t> m_vecHandle;
private:
ThreadManager(const ThreadManager&){;}// copy forbidden
void operator=(const ThreadManager &){}// copy forbidden
};
}
#endif

26
husky/globals.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef HUSKY_GLOBALS_H
#define HUSKY_GLOBALS_H
#include <string>
#include <vector>
#include <set>
#include <string>
#include <stdlib.h>
namespace Husky
{
const char* const MASTER_PID_FILE= "masterDaemon.pid";
const char* const RESPONSE_CHARSET_UTF8 = "UTF-8";
const char* const RESPONSE_CHARSET_GB2312 = "GB2312";
const char* const CLIENT_IP_K = "CLIENT_IP";
const unsigned int SOCKET_TIMEOUT = 2;
const char* const RESPONSE_FORMAT = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: FrameServer/1.0.0\r\nContent-Type: text/json; charset=%s\r\nContent-Length: %d\r\n\r\n";
typedef unsigned short u_short;
typedef unsigned int u_int;
}
#endif