1*f6dc9357SAndroid Build Coastguard Worker // StreamBinder.h 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_STREAM_BINDER_H 4*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_STREAM_BINDER_H 5*f6dc9357SAndroid Build Coastguard Worker 6*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/Synchronization.h" 7*f6dc9357SAndroid Build Coastguard Worker 8*f6dc9357SAndroid Build Coastguard Worker #include "../IStream.h" 9*f6dc9357SAndroid Build Coastguard Worker 10*f6dc9357SAndroid Build Coastguard Worker /* 11*f6dc9357SAndroid Build Coastguard Worker We can use one from two code versions here: with Event or with Semaphore to unlock Writer thread 12*f6dc9357SAndroid Build Coastguard Worker The difference for cases where Reading must be closed before Writing closing 13*f6dc9357SAndroid Build Coastguard Worker 14*f6dc9357SAndroid Build Coastguard Worker 1) Event Version: _canWrite_Event 15*f6dc9357SAndroid Build Coastguard Worker We call _canWrite_Event.Set() without waiting _canRead_Event in CloseRead() function. 16*f6dc9357SAndroid Build Coastguard Worker The writer thread can get (_readingWasClosed) status in one from two iterations. 17*f6dc9357SAndroid Build Coastguard Worker It's ambiguity of processing flow. But probably it's SAFE to use, if Event functions provide memory barriers. 18*f6dc9357SAndroid Build Coastguard Worker reader thread: 19*f6dc9357SAndroid Build Coastguard Worker _canWrite_Event.Set(); 20*f6dc9357SAndroid Build Coastguard Worker _readingWasClosed = true; 21*f6dc9357SAndroid Build Coastguard Worker _canWrite_Event.Set(); 22*f6dc9357SAndroid Build Coastguard Worker writer thread: 23*f6dc9357SAndroid Build Coastguard Worker _canWrite_Event.Wait() 24*f6dc9357SAndroid Build Coastguard Worker if (_readingWasClosed) 25*f6dc9357SAndroid Build Coastguard Worker 26*f6dc9357SAndroid Build Coastguard Worker 2) Semaphore Version: _canWrite_Semaphore 27*f6dc9357SAndroid Build Coastguard Worker writer thread always will detect closing of reading in latest iteration after all data processing iterations 28*f6dc9357SAndroid Build Coastguard Worker */ 29*f6dc9357SAndroid Build Coastguard Worker 30*f6dc9357SAndroid Build Coastguard Worker class CStreamBinder 31*f6dc9357SAndroid Build Coastguard Worker { 32*f6dc9357SAndroid Build Coastguard Worker NWindows::NSynchronization::CAutoResetEvent _canRead_Event; 33*f6dc9357SAndroid Build Coastguard Worker // NWindows::NSynchronization::CAutoResetEvent _canWrite_Event; 34*f6dc9357SAndroid Build Coastguard Worker NWindows::NSynchronization::CSemaphore _canWrite_Semaphore; 35*f6dc9357SAndroid Build Coastguard Worker 36*f6dc9357SAndroid Build Coastguard Worker // bool _readingWasClosed; // set it in reader thread and check it in write thread 37*f6dc9357SAndroid Build Coastguard Worker bool _readingWasClosed2; // use it in writer thread 38*f6dc9357SAndroid Build Coastguard Worker // bool WritingWasCut; 39*f6dc9357SAndroid Build Coastguard Worker bool _waitWrite; // use it in reader thread 40*f6dc9357SAndroid Build Coastguard Worker UInt32 _bufSize; 41*f6dc9357SAndroid Build Coastguard Worker const void *_buf; 42*f6dc9357SAndroid Build Coastguard Worker public: 43*f6dc9357SAndroid Build Coastguard Worker UInt64 ProcessedSize; // the size that was read by reader thread 44*f6dc9357SAndroid Build Coastguard Worker 45*f6dc9357SAndroid Build Coastguard Worker void CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream); 46*f6dc9357SAndroid Build Coastguard Worker 47*f6dc9357SAndroid Build Coastguard Worker HRESULT Create_ReInit(); 48*f6dc9357SAndroid Build Coastguard Worker 49*f6dc9357SAndroid Build Coastguard Worker HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); 50*f6dc9357SAndroid Build Coastguard Worker HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); 51*f6dc9357SAndroid Build Coastguard Worker CloseRead_CallOnce()52*f6dc9357SAndroid Build Coastguard Worker void CloseRead_CallOnce() 53*f6dc9357SAndroid Build Coastguard Worker { 54*f6dc9357SAndroid Build Coastguard Worker // call it only once: for example, in destructor 55*f6dc9357SAndroid Build Coastguard Worker 56*f6dc9357SAndroid Build Coastguard Worker /* 57*f6dc9357SAndroid Build Coastguard Worker _readingWasClosed = true; 58*f6dc9357SAndroid Build Coastguard Worker _canWrite_Event.Set(); 59*f6dc9357SAndroid Build Coastguard Worker */ 60*f6dc9357SAndroid Build Coastguard Worker 61*f6dc9357SAndroid Build Coastguard Worker /* 62*f6dc9357SAndroid Build Coastguard Worker We must relase Semaphore only once !!! 63*f6dc9357SAndroid Build Coastguard Worker we must release at least 2 items of Semaphore: 64*f6dc9357SAndroid Build Coastguard Worker one item to unlock partial Write(), if Read() have read some items 65*f6dc9357SAndroid Build Coastguard Worker then additional item to stop writing (_bufSize will be 0) 66*f6dc9357SAndroid Build Coastguard Worker */ 67*f6dc9357SAndroid Build Coastguard Worker _canWrite_Semaphore.Release(2); 68*f6dc9357SAndroid Build Coastguard Worker } 69*f6dc9357SAndroid Build Coastguard Worker CloseWrite()70*f6dc9357SAndroid Build Coastguard Worker void CloseWrite() 71*f6dc9357SAndroid Build Coastguard Worker { 72*f6dc9357SAndroid Build Coastguard Worker _buf = NULL; 73*f6dc9357SAndroid Build Coastguard Worker _bufSize = 0; 74*f6dc9357SAndroid Build Coastguard Worker _canRead_Event.Set(); 75*f6dc9357SAndroid Build Coastguard Worker } 76*f6dc9357SAndroid Build Coastguard Worker }; 77*f6dc9357SAndroid Build Coastguard Worker 78*f6dc9357SAndroid Build Coastguard Worker #endif 79