xref: /aosp_15_r20/external/lzma/CPP/7zip/Common/StreamBinder.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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