1 /*
2  * Part of WCM Commander
3  * https://github.com/corporateshark/WCMCommander
4  * wcm@linderdaum.com
5  */
6 
7 #pragma once
8 
9 #include "swl.h"
10 
11 using namespace wal;
12 
13 
14 typedef int ( * volatile OperCallback )( void* cbData );
15 
16 class OperThreadWin;
17 
18 class OperThreadNode
19 {
20 	friend class OperThreadWin;
21 	friend void* __123___OperThread( void* );
22 
23 	OperThreadWin* volatile win;
24 
25 	std::string threadInfo; //++volatile !!!
26 	OperThreadNode* volatile prev;
27 	OperThreadNode* volatile next;
28 	volatile bool stopped;
29 	Mutex mutex;
30 	void* volatile data;
31 
32 	void* volatile cbData;
33 	Cond cbCond;
34 	volatile int  cbRet;
35 	OperCallback cbFunc;
36 public:
OperThreadNode(OperThreadWin * w,const char * info,void * d)37 	OperThreadNode( OperThreadWin* w, const char* info, void* d )
38 		:  win( w ), threadInfo( info ), prev( 0 ), next( 0 ),
39 		   stopped( false ), data( d ),
40 		   cbData( 0 ), cbRet( -1 ), cbFunc( 0 )
41 	{}
42 
GetMutex()43 	Mutex* GetMutex() { return &mutex; }
44 
Data()45 	void* Data() { return data; } //можно вызывать и работать с данными только заблакировав mutex получаемый через GetMutex
NBStopped()46 	bool NBStopped() { return stopped; } //можно вызывать только заблакировав mutex получаемый через GetMutex
47 
48 	int CallBack( OperCallback f, void* data ); // ret < 0 if stopped
49 
50 	//!!! id >= 2
SendSignal(int id)51 	bool SendSignal( int id ) //обязательно запускать при НЕзалоченном mutex
52 	{ MutexLock lock( &mutex ); if ( stopped || id <= 1 ) { return false; } return WinThreadSignal( id ); }
53 
54 	~OperThreadNode();
55 private:
OperThreadNode()56 	OperThreadNode() {}
57 	CLASS_COPY_PROTECTION( OperThreadNode );
58 };
59 
60 //ф-ция потока, не должна пропускать исключений
61 //поток может посылать сигналы только через tData
62 typedef void ( *OperThreadFunc )( OperThreadNode* node );
63 
64 
65 class OperThreadWin: public Win
66 {
67 	friend void* __123___OperThread( void* );
68 	int nextThreadId;
NewThreadID()69 	int NewThreadID() { int n = nextThreadId; nextThreadId = ( ( nextThreadId + 1 ) % 0x10000 ); return n + 1; }
70 
71 	int threadId;
72 	OperThreadNode* tNode;
73 	bool cbExecuted;
74 public:
75 	OperThreadWin( WTYPE t, unsigned hints = 0, int nId = 0, Win* _parent = nullptr, const crect* rect = nullptr )
Win(t,hints,_parent,rect,nId)76 		: Win( t, hints, _parent, rect, nId ), nextThreadId( 0 ), tNode( 0 ), cbExecuted( false ) {}
77 
78 	void RunNewThread( const char* info, OperThreadFunc f, void* data ); //может быть исключение
79 	virtual void OperThreadSignal( int info );
80 	virtual void OperThreadStopped();
81 
82 	void StopThread();
83 	void SetStopFlag();
84 
85 	static void DBGPrintStoppingList();
86 
87 	virtual void ThreadSignal( int id, int data );
88 	virtual void ThreadStopped( int id, void* data );
89 	virtual ~OperThreadWin();
90 };
91