VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/DataStreamImpl.cpp@ 74776

Last change on this file since 74776 was 74776, checked in by vboxsync, 6 years ago

Main: Started implementing the IDataStream interface

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: DataStreamImpl.cpp 74776 2018-10-11 17:30:59Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox COM class implementation: DataStream
5 */
6
7/*
8 * Copyright (C) 2018 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19
20/*********************************************************************************************************************************
21* Header Files *
22*********************************************************************************************************************************/
23#include "DataStreamImpl.h"
24
25#include "AutoCaller.h"
26#include "Logging.h"
27
28
29/*********************************************************************************************************************************
30* Structures and Typedefs *
31*********************************************************************************************************************************/
32
33
34/*********************************************************************************************************************************
35* Boilerplate constructor & destructor *
36*********************************************************************************************************************************/
37
38DEFINE_EMPTY_CTOR_DTOR(DataStream)
39
40HRESULT DataStream::FinalConstruct()
41{
42 LogFlowThisFunc(("\n"));
43 return BaseFinalConstruct();
44}
45
46void DataStream::FinalRelease()
47{
48 LogFlowThisFuncEnter();
49 uninit();
50 BaseFinalRelease();
51 LogFlowThisFuncLeave();
52}
53
54
55/*********************************************************************************************************************************
56* Initializer & uninitializer *
57*********************************************************************************************************************************/
58
59/**
60 * Initializes the DataStream object.
61 *
62 * @param aBufferSize Size of the intermediate buffer.
63 *
64 */
65HRESULT DataStream::init(unsigned long aBufferSize)
66{
67 LogFlowThisFunc(("cbBuffer=%zu\n", aBufferSize));
68
69 /*
70 * Enclose the state transition NotReady->InInit->Ready
71 */
72 AutoInitSpan autoInitSpan(this);
73 AssertReturn(autoInitSpan.isOk(), E_FAIL);
74
75 /*
76 * Allocate data instance.
77 */
78 HRESULT hrc = S_OK;
79
80 m_aBufferSize = aBufferSize;
81 m_hSemEvtDataAvail = NIL_RTSEMEVENT;
82 m_hSemEvtBufSpcAvail = NIL_RTSEMEVENT;
83 int vrc = RTSemEventCreate(&m_hSemEvtDataAvail);
84 if (RT_SUCCESS(vrc))
85 vrc = RTSemEventCreate(&m_hSemEvtBufSpcAvail);
86
87 if (RT_FAILURE(vrc))
88 hrc = setErrorBoth(E_FAIL, vrc, tr("Failed to initialize data stream object (%Rrc)"), vrc);
89
90 /*
91 * Done. Just update object readiness state.
92 */
93 if (SUCCEEDED(hrc))
94 autoInitSpan.setSucceeded();
95 else
96 autoInitSpan.setFailed(hrc);
97
98 LogFlowThisFunc(("returns %Rhrc\n", hrc));
99 return hrc;
100}
101
102/**
103 * Uninitializes the instance (called from FinalRelease()).
104 */
105void DataStream::uninit()
106{
107 LogFlowThisFuncEnter();
108
109 /* Enclose the state transition Ready->InUninit->NotReady */
110 AutoUninitSpan autoUninitSpan(this);
111 if (!autoUninitSpan.uninitDone())
112 {
113 m_aBuffer.clear();
114 if (m_hSemEvtDataAvail != NIL_RTSEMEVENT)
115 RTSemEventDestroy(m_hSemEvtDataAvail);
116 if (m_hSemEvtBufSpcAvail != NIL_RTSEMEVENT)
117 RTSemEventDestroy(m_hSemEvtBufSpcAvail);
118 m_hSemEvtDataAvail = NIL_RTSEMEVENT;
119 m_hSemEvtBufSpcAvail = NIL_RTSEMEVENT;
120 }
121
122 LogFlowThisFuncLeave();
123}
124
125
126/*********************************************************************************************************************************
127* IDataStream attributes *
128*********************************************************************************************************************************/
129
130HRESULT DataStream::getReadSize(ULONG *aReadSize)
131{
132 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
133 *aReadSize = (ULONG)m_aBuffer.size();
134 return S_OK;
135}
136
137
138/*********************************************************************************************************************************
139* IDataStream methods *
140*********************************************************************************************************************************/
141
142HRESULT DataStream::read(ULONG aSize, ULONG aTimeoutMS, std::vector<BYTE> &aData)
143{
144 /*
145 * Allocate return buffer.
146 */
147 try
148 {
149 aData.resize(aSize);
150 }
151 catch (std::bad_alloc &)
152 {
153 return E_OUTOFMEMORY;
154 }
155
156 /*
157 * Do the reading. To play safe we exclusivly lock the object while doing this.
158 */
159 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
160
161 int vrc = VINF_SUCCESS;
162 while ( !m_aBuffer.size()
163 && !m_fEos
164 && RT_SUCCESS(vrc))
165 {
166 /* Wait for something to become available. */
167 alock.release();
168 vrc = RTSemEventWait(m_hSemEvtDataAvail, aTimeoutMS == 0 ? RT_INDEFINITE_WAIT : aTimeoutMS);
169 alock.acquire();
170 }
171
172 /*
173 * Manage the result.
174 */
175 HRESULT hrc;
176 if ( RT_SUCCESS(vrc)
177 && m_aBuffer.size())
178 {
179 size_t cbCopy = RT_MIN(aSize, m_aBuffer.size());
180 if (cbCopy != aSize)
181 {
182 Assert(cbCopy < aSize);
183 aData.resize(cbCopy);
184 }
185 aData.insert(aData.begin(), m_aBuffer.begin(), m_aBuffer.begin() + cbCopy);
186 m_aBuffer.erase(m_aBuffer.begin(), m_aBuffer.begin() + cbCopy);
187 vrc = RTSemEventSignal(m_hSemEvtBufSpcAvail);
188 AssertRC(vrc);
189 hrc = S_OK;
190 }
191 else
192 {
193 Assert( RT_FAILURE(vrc)
194 || ( m_fEos
195 && !m_aBuffer.size()));
196
197 aData.resize(0);
198 if (vrc == VERR_TIMEOUT)
199 hrc = VBOX_E_TIMEOUT;
200 else if (RT_FAILURE(vrc))
201 hrc = setErrorBoth(E_FAIL, vrc, tr("Error reading %u bytes: %Rrc"), aSize, vrc);
202 }
203
204 return hrc;
205}
206
207
208/*********************************************************************************************************************************
209* DataStream internal methods *
210*********************************************************************************************************************************/
211
212/**
213 * Writes the given data into the temporary buffer blocking if it is full.
214 *
215 * @returns IPRT status code.
216 * @param pvBuf The data to write.
217 * @param cbWrite How much to write.
218 * @param pcbWritten Where to store the amount of data written.
219 */
220int DataStream::i_write(const void *pvBuf, size_t cbWrite, size_t *pcbWritten)
221{
222 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
223 AssertReturn(!m_fEos, VERR_INVALID_STATE);
224
225 int vrc = VINF_SUCCESS;
226 while ( m_aBuffer.size() == m_aBufferSize
227 && RT_SUCCESS(vrc))
228 {
229 /* Wait for space to become available. */
230 alock.release();
231 vrc = RTSemEventWait(m_hSemEvtBufSpcAvail, RT_INDEFINITE_WAIT);
232 alock.acquire();
233 }
234
235 if (RT_SUCCESS(vrc))
236 {
237 Assert(m_aBuffer.size() < m_aBufferSize);
238 size_t cbCopy = RT_MIN(cbWrite, m_aBufferSize - m_aBuffer.size());
239 if (m_aBuffer.capacity() < m_aBuffer.size() + cbWrite)
240 m_aBuffer.reserve(m_aBuffer.size() + cbWrite);
241 memcpy(&m_aBuffer.front() + m_aBuffer.size(), pvBuf, cbCopy);
242 *pcbWritten = cbCopy;
243 RTSemEventSignal(m_hSemEvtDataAvail);
244 }
245
246 return vrc;
247}
248
249/**
250 * Marks the end of the stream.
251 *
252 * @returns IPRT status code.
253 */
254int DataStream::i_close()
255{
256 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
257 m_fEos = true;
258 RTSemEventSignal(m_hSemEvtDataAvail);
259 return VINF_SUCCESS;
260}
261
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette