1*f6dc9357SAndroid Build Coastguard Worker // StreamBinder.cpp 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h" 4*f6dc9357SAndroid Build Coastguard Worker 5*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyCom.h" 6*f6dc9357SAndroid Build Coastguard Worker 7*f6dc9357SAndroid Build Coastguard Worker #include "StreamBinder.h" 8*f6dc9357SAndroid Build Coastguard Worker 9*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1( 10*f6dc9357SAndroid Build Coastguard Worker CBinderInStream 11*f6dc9357SAndroid Build Coastguard Worker , ISequentialInStream 12*f6dc9357SAndroid Build Coastguard Worker ) 13*f6dc9357SAndroid Build Coastguard Worker CStreamBinder *_binder; 14*f6dc9357SAndroid Build Coastguard Worker public: 15*f6dc9357SAndroid Build Coastguard Worker ~CBinderInStream() { _binder->CloseRead_CallOnce(); } 16*f6dc9357SAndroid Build Coastguard Worker CBinderInStream(CStreamBinder *binder): _binder(binder) {} 17*f6dc9357SAndroid Build Coastguard Worker }; 18*f6dc9357SAndroid Build Coastguard Worker 19*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 20*f6dc9357SAndroid Build Coastguard Worker { return _binder->Read(data, size, processedSize); } 21*f6dc9357SAndroid Build Coastguard Worker 22*f6dc9357SAndroid Build Coastguard Worker 23*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1( 24*f6dc9357SAndroid Build Coastguard Worker CBinderOutStream 25*f6dc9357SAndroid Build Coastguard Worker , ISequentialOutStream 26*f6dc9357SAndroid Build Coastguard Worker ) 27*f6dc9357SAndroid Build Coastguard Worker CStreamBinder *_binder; 28*f6dc9357SAndroid Build Coastguard Worker public: 29*f6dc9357SAndroid Build Coastguard Worker ~CBinderOutStream() { _binder->CloseWrite(); } 30*f6dc9357SAndroid Build Coastguard Worker CBinderOutStream(CStreamBinder *binder): _binder(binder) {} 31*f6dc9357SAndroid Build Coastguard Worker }; 32*f6dc9357SAndroid Build Coastguard Worker 33*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) 34*f6dc9357SAndroid Build Coastguard Worker { return _binder->Write(data, size, processedSize); } 35*f6dc9357SAndroid Build Coastguard Worker 36*f6dc9357SAndroid Build Coastguard Worker 37*f6dc9357SAndroid Build Coastguard Worker static HRESULT Event_Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event) 38*f6dc9357SAndroid Build Coastguard Worker { 39*f6dc9357SAndroid Build Coastguard Worker const WRes wres = event.CreateIfNotCreated_Reset(); 40*f6dc9357SAndroid Build Coastguard Worker return HRESULT_FROM_WIN32(wres); 41*f6dc9357SAndroid Build Coastguard Worker } 42*f6dc9357SAndroid Build Coastguard Worker 43*f6dc9357SAndroid Build Coastguard Worker HRESULT CStreamBinder::Create_ReInit() 44*f6dc9357SAndroid Build Coastguard Worker { 45*f6dc9357SAndroid Build Coastguard Worker RINOK(Event_Create_or_Reset(_canRead_Event)) 46*f6dc9357SAndroid Build Coastguard Worker // RINOK(Event_Create_or_Reset(_canWrite_Event)) 47*f6dc9357SAndroid Build Coastguard Worker 48*f6dc9357SAndroid Build Coastguard Worker // _canWrite_Semaphore.Close(); 49*f6dc9357SAndroid Build Coastguard Worker // we need at least 3 items of maxCount: 1 for normal unlock in Read(), 2 items for unlock in CloseRead_CallOnce() 50*f6dc9357SAndroid Build Coastguard Worker _canWrite_Semaphore.OptCreateInit(0, 3); 51*f6dc9357SAndroid Build Coastguard Worker 52*f6dc9357SAndroid Build Coastguard Worker // _readingWasClosed = false; 53*f6dc9357SAndroid Build Coastguard Worker _readingWasClosed2 = false; 54*f6dc9357SAndroid Build Coastguard Worker 55*f6dc9357SAndroid Build Coastguard Worker _waitWrite = true; 56*f6dc9357SAndroid Build Coastguard Worker _bufSize = 0; 57*f6dc9357SAndroid Build Coastguard Worker _buf = NULL; 58*f6dc9357SAndroid Build Coastguard Worker ProcessedSize = 0; 59*f6dc9357SAndroid Build Coastguard Worker // WritingWasCut = false; 60*f6dc9357SAndroid Build Coastguard Worker return S_OK; 61*f6dc9357SAndroid Build Coastguard Worker } 62*f6dc9357SAndroid Build Coastguard Worker 63*f6dc9357SAndroid Build Coastguard Worker 64*f6dc9357SAndroid Build Coastguard Worker void CStreamBinder::CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream) 65*f6dc9357SAndroid Build Coastguard Worker { 66*f6dc9357SAndroid Build Coastguard Worker inStream = new CBinderInStream(this); 67*f6dc9357SAndroid Build Coastguard Worker outStream = new CBinderOutStream(this); 68*f6dc9357SAndroid Build Coastguard Worker } 69*f6dc9357SAndroid Build Coastguard Worker 70*f6dc9357SAndroid Build Coastguard Worker // (_canRead_Event && _bufSize == 0) means that stream is finished. 71*f6dc9357SAndroid Build Coastguard Worker 72*f6dc9357SAndroid Build Coastguard Worker HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) 73*f6dc9357SAndroid Build Coastguard Worker { 74*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 75*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0; 76*f6dc9357SAndroid Build Coastguard Worker if (size != 0) 77*f6dc9357SAndroid Build Coastguard Worker { 78*f6dc9357SAndroid Build Coastguard Worker if (_waitWrite) 79*f6dc9357SAndroid Build Coastguard Worker { 80*f6dc9357SAndroid Build Coastguard Worker WRes wres = _canRead_Event.Lock(); 81*f6dc9357SAndroid Build Coastguard Worker if (wres != 0) 82*f6dc9357SAndroid Build Coastguard Worker return HRESULT_FROM_WIN32(wres); 83*f6dc9357SAndroid Build Coastguard Worker _waitWrite = false; 84*f6dc9357SAndroid Build Coastguard Worker } 85*f6dc9357SAndroid Build Coastguard Worker if (size > _bufSize) 86*f6dc9357SAndroid Build Coastguard Worker size = _bufSize; 87*f6dc9357SAndroid Build Coastguard Worker if (size != 0) 88*f6dc9357SAndroid Build Coastguard Worker { 89*f6dc9357SAndroid Build Coastguard Worker memcpy(data, _buf, size); 90*f6dc9357SAndroid Build Coastguard Worker _buf = ((const Byte *)_buf) + size; 91*f6dc9357SAndroid Build Coastguard Worker ProcessedSize += size; 92*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 93*f6dc9357SAndroid Build Coastguard Worker *processedSize = size; 94*f6dc9357SAndroid Build Coastguard Worker _bufSize -= size; 95*f6dc9357SAndroid Build Coastguard Worker 96*f6dc9357SAndroid Build Coastguard Worker /* 97*f6dc9357SAndroid Build Coastguard Worker if (_bufSize == 0), then we have read whole buffer 98*f6dc9357SAndroid Build Coastguard Worker we have two ways here: 99*f6dc9357SAndroid Build Coastguard Worker - if we check (_bufSize == 0) here, we unlock Write only after full data Reading - it reduces the number of syncs 100*f6dc9357SAndroid Build Coastguard Worker - if we don't check (_bufSize == 0) here, we unlock Write after partial data Reading 101*f6dc9357SAndroid Build Coastguard Worker */ 102*f6dc9357SAndroid Build Coastguard Worker if (_bufSize == 0) 103*f6dc9357SAndroid Build Coastguard Worker { 104*f6dc9357SAndroid Build Coastguard Worker _waitWrite = true; 105*f6dc9357SAndroid Build Coastguard Worker // _canWrite_Event.Set(); 106*f6dc9357SAndroid Build Coastguard Worker _canWrite_Semaphore.Release(); 107*f6dc9357SAndroid Build Coastguard Worker } 108*f6dc9357SAndroid Build Coastguard Worker } 109*f6dc9357SAndroid Build Coastguard Worker } 110*f6dc9357SAndroid Build Coastguard Worker return S_OK; 111*f6dc9357SAndroid Build Coastguard Worker } 112*f6dc9357SAndroid Build Coastguard Worker 113*f6dc9357SAndroid Build Coastguard Worker 114*f6dc9357SAndroid Build Coastguard Worker HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) 115*f6dc9357SAndroid Build Coastguard Worker { 116*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 117*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0; 118*f6dc9357SAndroid Build Coastguard Worker if (size == 0) 119*f6dc9357SAndroid Build Coastguard Worker return S_OK; 120*f6dc9357SAndroid Build Coastguard Worker 121*f6dc9357SAndroid Build Coastguard Worker if (!_readingWasClosed2) 122*f6dc9357SAndroid Build Coastguard Worker { 123*f6dc9357SAndroid Build Coastguard Worker _buf = data; 124*f6dc9357SAndroid Build Coastguard Worker _bufSize = size; 125*f6dc9357SAndroid Build Coastguard Worker _canRead_Event.Set(); 126*f6dc9357SAndroid Build Coastguard Worker 127*f6dc9357SAndroid Build Coastguard Worker /* 128*f6dc9357SAndroid Build Coastguard Worker _canWrite_Event.Lock(); 129*f6dc9357SAndroid Build Coastguard Worker if (_readingWasClosed) 130*f6dc9357SAndroid Build Coastguard Worker _readingWasClosed2 = true; 131*f6dc9357SAndroid Build Coastguard Worker */ 132*f6dc9357SAndroid Build Coastguard Worker 133*f6dc9357SAndroid Build Coastguard Worker _canWrite_Semaphore.Lock(); 134*f6dc9357SAndroid Build Coastguard Worker 135*f6dc9357SAndroid Build Coastguard Worker // _bufSize : is remain size that was not read 136*f6dc9357SAndroid Build Coastguard Worker size -= _bufSize; 137*f6dc9357SAndroid Build Coastguard Worker 138*f6dc9357SAndroid Build Coastguard Worker // size : is size of data that was read 139*f6dc9357SAndroid Build Coastguard Worker if (size != 0) 140*f6dc9357SAndroid Build Coastguard Worker { 141*f6dc9357SAndroid Build Coastguard Worker // if some data was read, then we report that size and return 142*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 143*f6dc9357SAndroid Build Coastguard Worker *processedSize = size; 144*f6dc9357SAndroid Build Coastguard Worker return S_OK; 145*f6dc9357SAndroid Build Coastguard Worker } 146*f6dc9357SAndroid Build Coastguard Worker _readingWasClosed2 = true; 147*f6dc9357SAndroid Build Coastguard Worker } 148*f6dc9357SAndroid Build Coastguard Worker 149*f6dc9357SAndroid Build Coastguard Worker // WritingWasCut = true; 150*f6dc9357SAndroid Build Coastguard Worker return k_My_HRESULT_WritingWasCut; 151*f6dc9357SAndroid Build Coastguard Worker } 152