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