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