This is a creation in Article, where the information may have evolved or changed.
This is a simple example of mine and is not perfect at the moment.
Subsequent optimizations are required, such as the replacement of the thread lock, the addition of the selector mode, and each Chan relies on a separate thread for performance issues (one thread manages multiple Chan). Chan How to end it, how Chan ended it (through data not finished) and so on when the program ended. Design of blocking channels and non-blocking channels!!!
Lock.h
#pragma once#if defined (__cplusplus) && (__cplusplus >= 201103) #include <thread>typedef std::thread:: ID TID; #else//#error "not support c++11" #if defined (WIN32) | | Defined (WIN64) #include <windows.h>typedef DWORD TID; #elif defined (__linux__) #include <pthread.h>//Need- Pthread#include <unistd.h>typedef pthread_t TID; #endif #endif#if defined (__cplusplus) && (__cplusplus >= 201103) #include <mutex>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;p ublic: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//automatic Lock Unlock 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;};/ /When the front thread hangs for a certain time extern void Vsleep (unsigned int millionseconds = 0);//Get current threads Idextern 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}
Thread.h
#pragma once#include "Lock.h"//When this macro is defined, all threads will be rolled out once only once. #define _EXEONECE 10#if defined (WIN32) | | Defined (WIN64) DWORD WINAPI mythreadprocess (void* derivedthread); #elif defined (__linux__) void* mythreadprocess (void * derivedthread); #endifclass Thread {public:enum threadstatus {ready,//When the front thread is in the prepared state running,//is in a running state exiting,//thread is exiting Exi t//has exited};p Ublic:thread (), Virtual ~thread ();p ublic:void start (), virtual void Stop (), void exit (void * retval NULL); virtual void run ();p Ublic: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 ();} #endifprivate: TID M_tid; Threadstatus m_status, #if defined (__cplusplus) && (__cplusplus >= 201103) std::thread* M_hthread, #else//#error "not c++11" #if defined (WIN32) | | Defined (WIN64) HANDLE m_hthread; #endif #endif};extern unsigned int g_quitthreadcount;
Thread.cpp
#include "Thread.h" unsigned int g_quitthreadcount = 0; VLock G_thread_lock; Thread::thread () {try {#if defined (__cplusplus) && (__cplusplus >= 201103) #elsem_TID = 0; #endifm_Status = thre Ad::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//#err or "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 (thre AD = = 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 {Threa d * 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
Chan.h
#include "Thread.h"/* * file:chain.h * author:vicky.h * email:eclipser@163.com * * Created on April 22, 2014, 3:46 */ #pragma once#include "Thread.h" #include <list>template<typename t>class ICommand {public:virtual void acti On (t* pResult) {}};extern bool G_chanstate;extern VLock g_chanstatelock;//channel Template<typename T>class Chan:publi C Thread {template<typename e>friend void operator< (chan<e>& Chan, icommand<e>* PCommand); Template<typename e>friend bool Operator> (chan<e>& Chan, e** ppresult);p Ublic:chan () {Star T (); } void Run () {g_chanstatelock.lock (); bool _chanstate = G_chanstate;g_chanstatelock.unlock (); while (_chanstate) {m_lock.lock (); Std::list<icommand<t>*>::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<t*> m_results; Std::list<icommand<t> *> m_commands;}; Template<typename e>void operator< (chan<e>& Chan, icommand<e>* pCommand) {Chan.m_Lock.Lock ( ); Chan.m_Commands.push_back (pcommand); Chan.m_Lock.UnLock ();} Template<typename e>bool operator> (chan<e>& 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;}
Chan.cpp
#include "Thread.h"/* * file:chain.h * author:vicky.h * email:eclipser@163.com * * Created on April 22, 2014, 3:46 */ #pragma once#include "Thread.h" #include <list>template<typename t>class ICommand {public:virtual void acti On (t* pResult) {}};extern bool G_chanstate;extern VLock g_chanstatelock;//channel Template<typename T>class Chan:publi C Thread {template<typename e>friend void operator< (chan<e>& Chan, icommand<e>* PCommand); Template<typename e>friend bool Operator> (chan<e>& Chan, e** ppresult);p Ublic:chan () {Star T (); } void Run () {g_chanstatelock.lock (); bool _chanstate = G_chanstate;g_chanstatelock.unlock (); while (_chanstate) {m_lock.lock (); Std::list<icommand<t>*>::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<t*> m_results; Std::list<icommand<t> *> m_commands;}; Template<typename e>void operator< (chan<e>& Chan, icommand<e>* pCommand) {Chan.m_Lock.Lock ( ); Chan.m_Commands.push_back (pcommand); Chan.m_Lock.UnLock ();} Template<typename e>bool operator> (chan<e>& 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;}
Simple test:
Main.cpp
/* * File:main.cpp * author:vicky.h * email:eclipser@163.com */#include "Chan.h" #include <iostream> #include & lt;thread>extern bool G_chanstate;void Exithook () {g_chanstate = false;} Template<>class icommand<int> {public:virtual void action (int* pResult) {std::cout << "Thread:" <& Lt Vgetcurrentthreadid () << "sayhellochain action ..." << Std::endl;*presult = i++;//vsleep (1000L);} private:static int i;}; int icommand<int>::i = 0;class addcommand:public icommand<int> {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) {//Test 1//chain<int> chan1;////icommand<int> *PC1 = new icommand<int>;//ICo mmand<int> *PC2 = new icommand<int>;icommand<int> *PC3 = new icommand<int>;//icommand<int> *pc4 = new icommand<int>;//ICOMMAND&L t;int> *pc5 = new icommand<int>;//icommand<int> *pc6 = new icommand<int>;//Chan1 < pC1;//chan1 < pc2;//Chan1 < pc3;//chan1 < pc4;//chan1 < pc5;//chan1 < pc6;////Std::thread T1 ([&chan1] () {//In t* PResult = new int;//while (Chan1 > &presult) {//Std::cout << "Result:" << *presult << std: : endl;//}//});//T1.detach ();//test 2//chain<int> chan2;//addcommand* p1 = new AddCommand (0, +);//addcommand* P 2 = new AddCommand (101, max);//addcommand* P3 = new AddCommand (201);//addcommand* P4 = new AddCommand (301, 400);// addcommand* P5 = new AddCommand (401, $);//addcommand* P6 = new AddCommand (501, +);//addcommand* P7 = new AddCommand ( 601),//addcommand* P8 = new AddCommand (701, +);//addcommand* p9 = new AddCommand (801, n);//addcommand* P0 = NE W 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 ();//test 3chan<int> chan1; Chan<int> chan2; Chan<int> chan3; addcommand* P1 = new AddCommand (0, 100); addcommand* P2 = new AddCommand (101, 200); addcommand* p3 = new AddCommand (201), 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 + = *presul t;//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 << "s Um 3: "<< sum << Std::endl;}}); T3.detach (); Chan1 < p1;chan2 < P2;chan3 < p3;//execution < very fast, but execution > is very slow!!! needs to be optimized. Can you consider a callback structure, or pipe? Vsleep (500L); Print main function thread for (;;) {//Std::cout << "Thread:" << vgetcurrentthreadid () << Std::endl; Vsleep (1000L);} Atexit (exithook); return 0;}