这是我的一个简单例子,目前不够完善。
需要后续的优化,如,线程锁的更换,selector模式的加入,以及每个Chan依赖一个独立的线程,性能问题(一个线程管理多个Chan)。chan如何主动结束,程序结束时chan如何结束(通过数据未处理完)等等情况。阻塞式通道和非阻塞通道的设计!!!
Lock.h
#pragma once
#if defined(__cplusplus) && (__cplusplus >= 201103)
#include
typedef std::thread::id TID;
#else
// #error "not support c++11"
#if defined(WIN32) || defined(WIN64)
#include
typedef DWORD TID;
#elif defined(__linux__)
#include // 需要 -pthread
#include
typedef pthread_t TID ;
#endif
#endif
#if defined(__cplusplus) && (__cplusplus >= 201103)
#include
class VLock {
std::mutex m_Lock;
public:
void Lock() {m_Lock.lock();}
void UnLock() {m_Lock.unlock();};
bool TryLock() {return m_Lock.try_lock();};
};
#else
//#error "not support c++11"
#if defined(WIN32) || defined(WIN64)
class VLock {
CRITICAL_SECTION m_Lock ;
public:
VLock() {InitializeCriticalSection(&m_Lock);}
~VLock() {DeleteCriticalSection(&m_Lock);}
void Lock() {EnterCriticalSection(&m_Lock);}
void UnLock() {LeaveCriticalSection(&m_Lock);};
};
#elif defined(__linux__)
class VLock {
pthread_mutex_t m_Mutex;
public:
VLock() {pthread_mutex_init( &m_Mutex , NULL );}
~VLock() {pthread_mutex_destroy( &m_Mutex) ;}
void Lock() {pthread_mutex_lock(&m_Mutex);}
void UnLock() {pthread_mutex_unlock(&m_Mutex);};
};
#endif
#endif
//自动加锁解锁器
class AutoLock_T
{
public:
AutoLock_T(VLock& rLock)
{
m_pLock = &rLock;
m_pLock->Lock();
}
~AutoLock_T()
{
m_pLock->UnLock();
}
protected:
private:
AutoLock_T();
VLock* m_pLock;
};
//当前线程挂起一定时间
extern void VSleep( unsigned int millionseconds = 0 ) ;
//获得当前线程ID
extern TID VGetCurrentThreadId( ) ;
Lock.cpp
#include "Lock.h"
void VSleep( unsigned int millionseconds ) {
#if defined(__cplusplus) && (__cplusplus >= 201103)
std::this_thread::sleep_for(std::chrono::milliseconds(millionseconds));
#else
// #error "not support c++11"
#if defined(WIN32) || defined(WIN64)
Sleep( millionseconds ) ;
#elif defined(__linux__)
usleep( millionseconds*1000 ) ;
#endif
#endif
}
TID VGetCurrentThreadId() {
#if defined(__cplusplus) && (__cplusplus >= 201103)
return std::this_thread::get_id();
#else
// #error "not support c++11"
#if defined(WIN32) || defined(WIN64)
return GetCurrentThreadId( ) ;
#elif defined(__linux__)
return pthread_self();
#endif
#endif
}
#pragma once
#include "Lock.h"
//当定义此宏时,所有线程将只执行一次后就推出。
//#define _EXEONECE 10
#if defined(WIN32) || defined(WIN64)
DWORD WINAPI MyThreadProcess( void* derivedThread );
#elif defined(__linux__)
void* MyThreadProcess ( void * derivedThread );
#endif
class Thread {
public :
enum ThreadStatus
{
READY , // 当前线程处于准备状态
RUNNING , // 处于运行状态
EXITING , // 线程正在退出
EXIT // 已经退出
};
public :
Thread ( ) ;
virtual ~Thread () ;
public :
void start () ;
virtual void stop () ;
void exit ( void * retval = NULL ) ;
virtual void run () ;
public :
TID getTID () const { return m_TID; }
ThreadStatus getStatus () const { return m_Status; }
void setStatus ( ThreadStatus status ) { m_Status = status; }
#if defined(__cplusplus) && (__cplusplus >= 201103)
bool joinable() const {
return m_hThread->joinable();
}
#endif
#if defined(__cplusplus) && (__cplusplus >= 201103)
void join() {
return m_hThread->join();
}
#endif
private :
TID m_TID;
ThreadStatus m_Status;
#if defined(__cplusplus) && (__cplusplus >= 201103)
std::thread* m_hThread;
#else
// #error "not support c++11"
#if defined(WIN32) || defined(WIN64)
HANDLE m_hThread ;
#endif
#endif
};
extern unsigned int g_QuitThreadCount ;
#include "Thread.h"
unsigned int g_QuitThreadCount = 0 ;
VLock g_thread_lock ;
Thread::Thread ( ) {
try {
#if defined(__cplusplus) && (__cplusplus >= 201103)
#else
m_TID = 0 ;
#endif
m_Status = Thread::READY ;
#if defined(__cplusplus) && (__cplusplus >= 201103)
m_hThread = new std::thread(MyThreadProcess, this);
m_TID = m_hThread->get_id();
#else
// #error "not support c++11"
#if defined(WIN32) || defined(WIN64)
m_hThread = NULL ;
#elif defined(__linux__)
#endif
#endif
} catch (...) {
}
}
Thread::~Thread () {
}
void Thread::start() {
try {
if ( m_Status != Thread::READY )
return ;
m_Status = Thread::RUNNING;
#if defined(__cplusplus) && (__cplusplus >= 201103)
m_hThread->detach();
#else
// #error "not support c++11"
#if defined(WIN32) || defined(WIN64)
m_hThread = CreateThread( NULL, 0, MyThreadProcess , this, 0, &m_TID ) ;
#elif defined(__linux__)
pthread_create( &m_TID, NULL , MyThreadProcess , this );
#endif
#endif
} catch (...) {
}
}
void Thread::stop() {
}
void Thread::exit(void* retval) {
try {
#if defined(__cplusplus) && (__cplusplus >= 201103)
delete m_hThread;
m_hThread = NULL;
#else
// #error "not support c++11"
#if defined(WIN32) || defined(WIN64)
CloseHandle( m_hThread ) ;
#elif defined(__linux__)
pthread_exit( retval );
#endif
#endif
} catch (...) {
}
}
void Thread::run( ) {
}
//===================
#if defined(WIN32) || defined(WIN64)
DWORD WINAPI MyThreadProcess( VOID* derivedThread )
{
try
{
Thread * thread = (Thread *) derivedThread;
if( thread == NULL )
return 0;
thread->run();
thread->setStatus(Thread::EXIT);
thread->exit(NULL);
g_thread_lock.Lock() ;
g_QuitThreadCount++ ;
g_thread_lock.UnLock() ;
} catch (...) {
}
return 0; // avoid compiler's warning
}
#elif defined(__linux__)
void * MyThreadProcess ( void * derivedThread ) {
try {
Thread * thread = (Thread *)derivedThread;
if( thread==NULL )
return NULL;
thread->run();
thread->setStatus(Thread::EXIT);
//INT ret = 0;
//thread->exit(&ret);
g_thread_lock.Lock() ;
g_QuitThreadCount++ ;
g_thread_lock.UnLock() ;
} catch (...) {
}
return NULL; // avoid compiler's warning
}
#endif
#include "Thread.h"
/*
* File: Chain.h
* Author: Vicky.H
* Email: [email protected]
*
* Created on 2014年4月22日, 下午3:46
*/
#pragma once
#include "Thread.h"
#include
template
class ICommand {
public:
virtual void action (T* pResult) {}
};
extern bool g_ChanState;
extern VLock g_ChanStateLock;
// 通道
template
class Chan : public Thread {
template
friend void operator< (Chan& chan, ICommand* pCommand);
template
friend bool operator> (Chan& chan, E** ppResult);
public:
Chan() {
start();
}
void run() {
g_ChanStateLock.Lock();
bool _chanState = g_ChanState;
g_ChanStateLock.UnLock();
while (_chanState) {
m_Lock.Lock();
std::list*>::iterator it = m_Commands.begin();
while (it != m_Commands.end()) {
T* pResult = new T;
(*it)->action(pResult);
m_Results.push_back(pResult);
it++;
}
m_Commands.clear();
VSleep(10L);
m_Lock.UnLock();
g_ChanStateLock.Lock();
_chanState = g_ChanState;
g_ChanStateLock.UnLock();
}
}
private:
VLock m_Lock;
std::list m_Results;
std::list *> m_Commands;
};
template
void operator< (Chan& chan, ICommand* pCommand) {
chan.m_Lock.Lock();
chan.m_Commands.push_back(pCommand);
chan.m_Lock.UnLock();
}
template
bool operator> (Chan& chan, E** ppResult) {
for (;;) {
chan.m_Lock.Lock();
if (!chan.m_Results.empty()) {
break;
}
chan.m_Lock.UnLock();
VSleep(10L);
}
AutoLock_T __lock(chan.m_Lock);
if (chan.m_Results.empty()) {
return false;
}
*ppResult = *(chan.m_Results.begin());
chan.m_Results.pop_front();
return true;
}
#include "Thread.h"
/*
* File: Chain.h
* Author: Vicky.H
* Email: [email protected]
*
* Created on 2014年4月22日, 下午3:46
*/
#pragma once
#include "Thread.h"
#include
template
class ICommand {
public:
virtual void action (T* pResult) {}
};
extern bool g_ChanState;
extern VLock g_ChanStateLock;
// 通道
template
class Chan : public Thread {
template
friend void operator< (Chan& chan, ICommand* pCommand);
template
friend bool operator> (Chan& chan, E** ppResult);
public:
Chan() {
start();
}
void run() {
g_ChanStateLock.Lock();
bool _chanState = g_ChanState;
g_ChanStateLock.UnLock();
while (_chanState) {
m_Lock.Lock();
std::list*>::iterator it = m_Commands.begin();
while (it != m_Commands.end()) {
T* pResult = new T;
(*it)->action(pResult);
m_Results.push_back(pResult);
it++;
}
m_Commands.clear();
VSleep(10L);
m_Lock.UnLock();
g_ChanStateLock.Lock();
_chanState = g_ChanState;
g_ChanStateLock.UnLock();
}
}
private:
VLock m_Lock;
std::list m_Results;
std::list *> m_Commands;
};
template
void operator< (Chan& chan, ICommand* pCommand) {
chan.m_Lock.Lock();
chan.m_Commands.push_back(pCommand);
chan.m_Lock.UnLock();
}
template
bool operator> (Chan& chan, E** ppResult) {
for (;;) {
chan.m_Lock.Lock();
if (!chan.m_Results.empty()) {
break;
}
chan.m_Lock.UnLock();
VSleep(10L);
}
AutoLock_T __lock(chan.m_Lock);
if (chan.m_Results.empty()) {
return false;
}
*ppResult = *(chan.m_Results.begin());
chan.m_Results.pop_front();
return true;
}
简单测试:
main.cpp
/*
* File: main.cpp
* Author: Vicky.H
* Email: [email protected]
*/
#include "Chan.h"
#include
#include
extern bool g_ChanState;
void exitHook() {
g_ChanState = false;
}
template<>
class ICommand {
public:
virtual void action (int* pResult) {
std::cout << "Thread:" << VGetCurrentThreadId( ) << " SayHelloChain action ..." << std::endl;
*pResult = i++;
// VSleep(1000L);
}
private:
static int i;
};
int ICommand::i = 0;
class AddCommand : public ICommand {
public:
AddCommand(int i, int j) :i (i), j(j) {
}
void action (int* pResult) {
if (i > j) {
int _tmp = i;
i = j;
j = _tmp;
}
int _sum = 0;
for (int index = i; index < j; index++) {
_sum += index;
}
*pResult = _sum;
std::cout << "sum : " << _sum << std::endl;
}
private:
int i;
int j;
};
/*
*
*/
int main(void) {
// 测试1
// Chain chan1;
//
// ICommand *pC1 = new ICommand;
// ICommand *pC2 = new ICommand;
// ICommand *pC3 = new ICommand;
// ICommand *pC4 = new ICommand;
// ICommand *pC5 = new ICommand;
// ICommand *pC6 = new ICommand;
// chan1 < pC1;
// chan1 < pC2;
// chan1 < pC3;
// chan1 < pC4;
// chan1 < pC5;
// chan1 < pC6;
//
// std::thread t1([&chan1](){
// int* pResult = new int;
// while (chan1 > &pResult) {
// std::cout << "result : " << *pResult << std::endl;
// }
// });
// t1.detach();
// 测试2
// Chain chan2;
// AddCommand* p1 = new AddCommand(0, 100);
// AddCommand* p2 = new AddCommand(101, 200);
// AddCommand* p3 = new AddCommand(201, 300);
// AddCommand* p4 = new AddCommand(301, 400);
// AddCommand* p5 = new AddCommand(401, 500);
// AddCommand* p6 = new AddCommand(501, 600);
// AddCommand* p7 = new AddCommand(601, 700);
// AddCommand* p8 = new AddCommand(701, 800);
// AddCommand* p9 = new AddCommand(801, 900);
// AddCommand* p0 = new AddCommand(901, 1000);
//
// chan2 < p1;
// chan2 < p2;
// chan2 < p3;
// chan2 < p4;
// chan2 < p5;
// chan2 < p6;
// chan2 < p7;
// chan2 < p8;
// chan2 < p9;
// chan2 < p0;
//
// std::thread t2([&chan2](){
// int sum = 0;
// int* pResult = new int;
// while (chan2 > &pResult) {
// sum += *pResult;
// std::cout << "sum : " << sum << std::endl;
// }
// });
// t2.detach();
// 测试3
Chan chan1;
Chan chan2;
Chan chan3;
AddCommand* p1 = new AddCommand(0, 100);
AddCommand* p2 = new AddCommand(101, 200);
AddCommand* p3 = new AddCommand(201, 300);
int sum = 0;
std::thread t1([&chan1, &sum](){
int* pResult = new int;
while (chan1 > &pResult) {
sum += *pResult;
// std::cout << "sum 1 : " << sum << std::endl;
}
});
t1.detach();
std::thread t2([&chan2, &sum](){
int* pResult = new int;
while (chan2 > &pResult) {
sum += *pResult;
// std::cout << "sum 2 : " << sum << std::endl;
}
});
t2.detach();
std::thread t3([&chan3, &sum](){
int* pResult = new int;
while (chan3 > &pResult) {
sum += *pResult;
// std::cout << "sum 3 : " << sum << std::endl;
}
});
t3.detach();
chan1 < p1;
chan2 < p2;
chan3 < p3;
// 执行 < 很快,但执行 > 却非常慢!!!需要优化。可以考虑回调结构,或者pipe?
VSleep(500L);
// 打印主函数线程
for (;;) {
// std::cout << "Thread:" << VGetCurrentThreadId( ) << std::endl;
VSleep(1000L);
}
atexit(exitHook);
return 0;
}