1370b324cSopenharmony_ci// StreamBinder.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../Common/MyCom.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "StreamBinder.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_ciZ7_CLASS_IMP_COM_1(
10370b324cSopenharmony_ci  CBinderInStream
11370b324cSopenharmony_ci  , ISequentialInStream
12370b324cSopenharmony_ci)
13370b324cSopenharmony_ci  CStreamBinder *_binder;
14370b324cSopenharmony_cipublic:
15370b324cSopenharmony_ci  ~CBinderInStream() { _binder->CloseRead_CallOnce(); }
16370b324cSopenharmony_ci  CBinderInStream(CStreamBinder *binder): _binder(binder) {}
17370b324cSopenharmony_ci};
18370b324cSopenharmony_ci
19370b324cSopenharmony_ciZ7_COM7F_IMF(CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
20370b324cSopenharmony_ci  { return _binder->Read(data, size, processedSize); }
21370b324cSopenharmony_ci
22370b324cSopenharmony_ci
23370b324cSopenharmony_ciZ7_CLASS_IMP_COM_1(
24370b324cSopenharmony_ci  CBinderOutStream
25370b324cSopenharmony_ci  , ISequentialOutStream
26370b324cSopenharmony_ci)
27370b324cSopenharmony_ci  CStreamBinder *_binder;
28370b324cSopenharmony_cipublic:
29370b324cSopenharmony_ci  ~CBinderOutStream() { _binder->CloseWrite(); }
30370b324cSopenharmony_ci  CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
31370b324cSopenharmony_ci};
32370b324cSopenharmony_ci
33370b324cSopenharmony_ciZ7_COM7F_IMF(CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
34370b324cSopenharmony_ci  { return _binder->Write(data, size, processedSize); }
35370b324cSopenharmony_ci
36370b324cSopenharmony_ci
37370b324cSopenharmony_cistatic HRESULT Event_Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event)
38370b324cSopenharmony_ci{
39370b324cSopenharmony_ci  const WRes wres = event.CreateIfNotCreated_Reset();
40370b324cSopenharmony_ci  return HRESULT_FROM_WIN32(wres);
41370b324cSopenharmony_ci}
42370b324cSopenharmony_ci
43370b324cSopenharmony_ciHRESULT CStreamBinder::Create_ReInit()
44370b324cSopenharmony_ci{
45370b324cSopenharmony_ci  RINOK(Event_Create_or_Reset(_canRead_Event))
46370b324cSopenharmony_ci  // RINOK(Event_Create_or_Reset(_canWrite_Event))
47370b324cSopenharmony_ci
48370b324cSopenharmony_ci  // _canWrite_Semaphore.Close();
49370b324cSopenharmony_ci  // we need at least 3 items of maxCount: 1 for normal unlock in Read(), 2 items for unlock in CloseRead_CallOnce()
50370b324cSopenharmony_ci  _canWrite_Semaphore.OptCreateInit(0, 3);
51370b324cSopenharmony_ci
52370b324cSopenharmony_ci  // _readingWasClosed = false;
53370b324cSopenharmony_ci  _readingWasClosed2 = false;
54370b324cSopenharmony_ci
55370b324cSopenharmony_ci  _waitWrite = true;
56370b324cSopenharmony_ci  _bufSize = 0;
57370b324cSopenharmony_ci  _buf = NULL;
58370b324cSopenharmony_ci  ProcessedSize = 0;
59370b324cSopenharmony_ci  // WritingWasCut = false;
60370b324cSopenharmony_ci  return S_OK;
61370b324cSopenharmony_ci}
62370b324cSopenharmony_ci
63370b324cSopenharmony_ci
64370b324cSopenharmony_civoid CStreamBinder::CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream)
65370b324cSopenharmony_ci{
66370b324cSopenharmony_ci  inStream = new CBinderInStream(this);
67370b324cSopenharmony_ci  outStream = new CBinderOutStream(this);
68370b324cSopenharmony_ci}
69370b324cSopenharmony_ci
70370b324cSopenharmony_ci// (_canRead_Event && _bufSize == 0) means that stream is finished.
71370b324cSopenharmony_ci
72370b324cSopenharmony_ciHRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
73370b324cSopenharmony_ci{
74370b324cSopenharmony_ci  if (processedSize)
75370b324cSopenharmony_ci    *processedSize = 0;
76370b324cSopenharmony_ci  if (size != 0)
77370b324cSopenharmony_ci  {
78370b324cSopenharmony_ci    if (_waitWrite)
79370b324cSopenharmony_ci    {
80370b324cSopenharmony_ci      WRes wres = _canRead_Event.Lock();
81370b324cSopenharmony_ci      if (wres != 0)
82370b324cSopenharmony_ci        return HRESULT_FROM_WIN32(wres);
83370b324cSopenharmony_ci      _waitWrite = false;
84370b324cSopenharmony_ci    }
85370b324cSopenharmony_ci    if (size > _bufSize)
86370b324cSopenharmony_ci      size = _bufSize;
87370b324cSopenharmony_ci    if (size != 0)
88370b324cSopenharmony_ci    {
89370b324cSopenharmony_ci      memcpy(data, _buf, size);
90370b324cSopenharmony_ci      _buf = ((const Byte *)_buf) + size;
91370b324cSopenharmony_ci      ProcessedSize += size;
92370b324cSopenharmony_ci      if (processedSize)
93370b324cSopenharmony_ci        *processedSize = size;
94370b324cSopenharmony_ci      _bufSize -= size;
95370b324cSopenharmony_ci
96370b324cSopenharmony_ci      /*
97370b324cSopenharmony_ci      if (_bufSize == 0), then we have read whole buffer
98370b324cSopenharmony_ci      we have two ways here:
99370b324cSopenharmony_ci        - if we       check (_bufSize == 0) here, we unlock Write only after full data Reading - it reduces the number of syncs
100370b324cSopenharmony_ci        - if we don't check (_bufSize == 0) here, we unlock Write after partial data Reading
101370b324cSopenharmony_ci      */
102370b324cSopenharmony_ci      if (_bufSize == 0)
103370b324cSopenharmony_ci      {
104370b324cSopenharmony_ci        _waitWrite = true;
105370b324cSopenharmony_ci        // _canWrite_Event.Set();
106370b324cSopenharmony_ci        _canWrite_Semaphore.Release();
107370b324cSopenharmony_ci      }
108370b324cSopenharmony_ci    }
109370b324cSopenharmony_ci  }
110370b324cSopenharmony_ci  return S_OK;
111370b324cSopenharmony_ci}
112370b324cSopenharmony_ci
113370b324cSopenharmony_ci
114370b324cSopenharmony_ciHRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
115370b324cSopenharmony_ci{
116370b324cSopenharmony_ci  if (processedSize)
117370b324cSopenharmony_ci    *processedSize = 0;
118370b324cSopenharmony_ci  if (size == 0)
119370b324cSopenharmony_ci    return S_OK;
120370b324cSopenharmony_ci
121370b324cSopenharmony_ci  if (!_readingWasClosed2)
122370b324cSopenharmony_ci  {
123370b324cSopenharmony_ci    _buf = data;
124370b324cSopenharmony_ci    _bufSize = size;
125370b324cSopenharmony_ci    _canRead_Event.Set();
126370b324cSopenharmony_ci
127370b324cSopenharmony_ci    /*
128370b324cSopenharmony_ci    _canWrite_Event.Lock();
129370b324cSopenharmony_ci    if (_readingWasClosed)
130370b324cSopenharmony_ci      _readingWasClosed2 = true;
131370b324cSopenharmony_ci    */
132370b324cSopenharmony_ci
133370b324cSopenharmony_ci    _canWrite_Semaphore.Lock();
134370b324cSopenharmony_ci
135370b324cSopenharmony_ci    // _bufSize : is remain size that was not read
136370b324cSopenharmony_ci    size -= _bufSize;
137370b324cSopenharmony_ci
138370b324cSopenharmony_ci    // size : is size of data that was read
139370b324cSopenharmony_ci    if (size != 0)
140370b324cSopenharmony_ci    {
141370b324cSopenharmony_ci      // if some data was read, then we report that size and return
142370b324cSopenharmony_ci      if (processedSize)
143370b324cSopenharmony_ci        *processedSize = size;
144370b324cSopenharmony_ci      return S_OK;
145370b324cSopenharmony_ci    }
146370b324cSopenharmony_ci    _readingWasClosed2 = true;
147370b324cSopenharmony_ci  }
148370b324cSopenharmony_ci
149370b324cSopenharmony_ci  // WritingWasCut = true;
150370b324cSopenharmony_ci  return k_My_HRESULT_WritingWasCut;
151370b324cSopenharmony_ci}
152