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