VirtualBox

source: vbox/trunk/src/VBox/Main/include/ProgressImpl.h@ 24961

Last change on this file since 24961 was 24961, checked in by vboxsync, 16 years ago

Main: Added a timeout property to IProgress that can be used to automatically time out an operation. This is to make life simpler on the client side.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.1 KB
Line 
1/* $Id: ProgressImpl.h 24961 2009-11-25 16:02:32Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox COM class implementation
5 */
6
7/*
8 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#ifndef ____H_PROGRESSIMPL
24#define ____H_PROGRESSIMPL
25
26#include "VirtualBoxBase.h"
27
28#include <VBox/com/SupportErrorInfo.h>
29
30#include <iprt/semaphore.h>
31
32#include <vector>
33
34class VirtualBox;
35
36////////////////////////////////////////////////////////////////////////////////
37
38/**
39 * Base component class for progress objects.
40 */
41class ATL_NO_VTABLE ProgressBase :
42 public VirtualBoxBase,
43 public com::SupportErrorInfoBase,
44 public VirtualBoxSupportTranslation<ProgressBase>,
45 VBOX_SCRIPTABLE_IMPL(IProgress)
46{
47protected:
48
49 VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT (ProgressBase)
50
51 DECLARE_EMPTY_CTOR_DTOR (ProgressBase)
52
53 HRESULT FinalConstruct();
54
55 // protected initializer/uninitializer for internal purposes only
56 HRESULT protectedInit (AutoInitSpan &aAutoInitSpan,
57#if !defined (VBOX_COM_INPROC)
58 VirtualBox *aParent,
59#endif
60 IUnknown *aInitiator,
61 CBSTR aDescription, OUT_GUID aId = NULL);
62 HRESULT protectedInit (AutoInitSpan &aAutoInitSpan);
63 void protectedUninit (AutoUninitSpan &aAutoUninitSpan);
64
65public:
66
67 // IProgress properties
68 STDMETHOD(COMGETTER(Id)) (BSTR *aId);
69 STDMETHOD(COMGETTER(Description)) (BSTR *aDescription);
70 STDMETHOD(COMGETTER(Initiator)) (IUnknown **aInitiator);
71
72 // IProgress properties
73 STDMETHOD(COMGETTER(Cancelable)) (BOOL *aCancelable);
74 STDMETHOD(COMGETTER(Percent)) (ULONG *aPercent);
75 STDMETHOD(COMGETTER(TimeRemaining)) (LONG *aTimeRemaining);
76 STDMETHOD(COMGETTER(Completed)) (BOOL *aCompleted);
77 STDMETHOD(COMGETTER(Canceled)) (BOOL *aCanceled);
78 STDMETHOD(COMGETTER(ResultCode)) (LONG *aResultCode);
79 STDMETHOD(COMGETTER(ErrorInfo)) (IVirtualBoxErrorInfo **aErrorInfo);
80 STDMETHOD(COMGETTER(OperationCount)) (ULONG *aOperationCount);
81 STDMETHOD(COMGETTER(Operation)) (ULONG *aCount);
82 STDMETHOD(COMGETTER(OperationDescription)) (BSTR *aOperationDescription);
83 STDMETHOD(COMGETTER(OperationPercent)) (ULONG *aOperationPercent);
84 STDMETHOD(COMSETTER(Timeout)) (ULONG aTimeout);
85 STDMETHOD(COMGETTER(Timeout)) (ULONG *aTimeout);
86
87 // public methods only for internal purposes
88
89 static HRESULT setErrorInfoOnThread (IProgress *aProgress);
90 bool setCancelCallback(void (*pfnCallback)(void *), void *pvUser);
91
92
93 // unsafe inline public methods for internal purposes only (ensure there is
94 // a caller and a read lock before calling them!)
95
96 BOOL completed() const { return mCompleted; }
97 HRESULT resultCode() const { return mResultCode; }
98 double calcTotalPercent();
99
100protected:
101
102#if !defined (VBOX_COM_INPROC)
103 /** Weak parent. */
104 const ComObjPtr<VirtualBox, ComWeakRef> mParent;
105#endif
106
107 const ComPtr<IUnknown> mInitiator;
108
109 const Guid mId;
110 const Bstr mDescription;
111
112 uint64_t m_ullTimestamp; // progress object creation timestamp, for ETA computation
113
114 void (*m_pfnCancelCallback)(void *);
115 void *m_pvCancelUserArg;
116
117 /* The fields below are to be properly initalized by subclasses */
118
119 BOOL mCompleted;
120 BOOL mCancelable;
121 BOOL mCanceled;
122 HRESULT mResultCode;
123 ComPtr<IVirtualBoxErrorInfo> mErrorInfo;
124
125 ULONG m_cOperations; // number of operations (so that progress dialog can display something like 1/3)
126 ULONG m_ulTotalOperationsWeight; // sum of weights of all operations, given to constructor
127
128 ULONG m_ulOperationsCompletedWeight; // summed-up weight of operations that have been completed; initially 0
129
130 ULONG m_ulCurrentOperation; // operations counter, incremented with each setNextOperation()
131 Bstr m_bstrOperationDescription; // name of current operation; initially from constructor, changed with setNextOperation()
132 ULONG m_ulCurrentOperationWeight; // weight of current operation, given to setNextOperation()
133 ULONG m_ulOperationPercent; // percentage of current operation, set with setCurrentOperationProgress()
134 ULONG m_cMsTimeout; /**< Automatic timeout value. 0 means none. */
135};
136
137////////////////////////////////////////////////////////////////////////////////
138
139/**
140 * Normal progress object.
141 */
142class ATL_NO_VTABLE Progress :
143 public com::SupportErrorInfoDerived<ProgressBase, Progress, IProgress>,
144 public VirtualBoxSupportTranslation<Progress>
145{
146
147public:
148
149 VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE (Progress)
150
151 DECLARE_NOT_AGGREGATABLE (Progress)
152
153 DECLARE_PROTECT_FINAL_CONSTRUCT()
154
155 BEGIN_COM_MAP (Progress)
156 COM_INTERFACE_ENTRY (ISupportErrorInfo)
157 COM_INTERFACE_ENTRY (IProgress)
158 COM_INTERFACE_ENTRY2 (IDispatch, IProgress)
159 END_COM_MAP()
160
161 HRESULT FinalConstruct();
162 void FinalRelease();
163
164 // public initializer/uninitializer for internal purposes only
165
166 /**
167 * Simplified constructor for progress objects that have only one
168 * operation as a task.
169 * @param aParent
170 * @param aInitiator
171 * @param aDescription
172 * @param aCancelable
173 * @param aId
174 * @return
175 */
176 HRESULT init(
177#if !defined (VBOX_COM_INPROC)
178 VirtualBox *aParent,
179#endif
180 IUnknown *aInitiator,
181 CBSTR aDescription,
182 BOOL aCancelable,
183 OUT_GUID aId = NULL)
184 {
185 return init(
186#if !defined (VBOX_COM_INPROC)
187 aParent,
188#endif
189 aInitiator,
190 aDescription,
191 aCancelable,
192 1, // cOperations
193 1, // ulTotalOperationsWeight
194 aDescription, // bstrFirstOperationDescription
195 1, // ulFirstOperationWeight
196 aId);
197 }
198
199 /**
200 * Not quite so simplified constructor for progress objects that have
201 * more than one operation, but all sub-operations are weighed the same.
202 * @param aParent
203 * @param aInitiator
204 * @param aDescription
205 * @param aCancelable
206 * @param cOperations
207 * @param bstrFirstOperationDescription
208 * @param aId
209 * @return
210 */
211 HRESULT init(
212#if !defined (VBOX_COM_INPROC)
213 VirtualBox *aParent,
214#endif
215 IUnknown *aInitiator,
216 CBSTR aDescription, BOOL aCancelable,
217 ULONG cOperations,
218 CBSTR bstrFirstOperationDescription,
219 OUT_GUID aId = NULL)
220 {
221 return init(
222#if !defined (VBOX_COM_INPROC)
223 aParent,
224#endif
225 aInitiator,
226 aDescription,
227 aCancelable,
228 cOperations, // cOperations
229 cOperations, // ulTotalOperationsWeight = cOperations
230 bstrFirstOperationDescription, // bstrFirstOperationDescription
231 1, // ulFirstOperationWeight: weigh them all the same
232 aId);
233 }
234
235 HRESULT init(
236#if !defined (VBOX_COM_INPROC)
237 VirtualBox *aParent,
238#endif
239 IUnknown *aInitiator,
240 CBSTR aDescription,
241 BOOL aCancelable,
242 ULONG cOperations,
243 ULONG ulTotalOperationsWeight,
244 CBSTR bstrFirstOperationDescription,
245 ULONG ulFirstOperationWeight,
246 OUT_GUID aId = NULL);
247
248 HRESULT init(BOOL aCancelable,
249 ULONG aOperationCount,
250 CBSTR aOperationDescription);
251
252 void uninit();
253
254 // IProgress methods
255 STDMETHOD(WaitForCompletion)(LONG aTimeout);
256 STDMETHOD(WaitForOperationCompletion)(ULONG aOperation, LONG aTimeout);
257 STDMETHOD(Cancel)();
258
259 STDMETHOD(SetCurrentOperationProgress)(ULONG aPercent);
260 STDMETHOD(SetNextOperation)(IN_BSTR bstrNextOperationDescription, ULONG ulNextOperationsWeight);
261
262 // public methods only for internal purposes
263
264 HRESULT setResultCode(HRESULT aResultCode);
265
266 HRESULT notifyComplete(HRESULT aResultCode);
267 HRESULT notifyComplete(HRESULT aResultCode,
268 const GUID &aIID,
269 const Bstr &aComponent,
270 const char *aText, ...);
271 bool notifyPointOfNoReturn(void);
272
273 /** For com::SupportErrorInfoImpl. */
274 static const char *ComponentName() { return "Progress"; }
275
276private:
277
278 RTSEMEVENTMULTI mCompletedSem;
279 ULONG mWaitersCount;
280};
281
282////////////////////////////////////////////////////////////////////////////////
283
284/**
285 * The CombinedProgress class allows to combine several progress objects to a
286 * single progress component. This single progress component will treat all
287 * operations of individual progress objects as a single sequence of operations
288 * that follow each other in the same order as progress objects are passed to
289 * the #init() method.
290 *
291 * Individual progress objects are sequentially combined so that this progress
292 * object:
293 *
294 * - is cancelable only if all progresses are cancelable.
295 * - is canceled once a progress that follows next to successfully completed
296 * ones reports it was canceled.
297 * - is completed successfully only after all progresses are completed
298 * successfully.
299 * - is completed unsuccessfully once a progress that follows next to
300 * successfully completed ones reports it was completed unsuccessfully;
301 * the result code and error info of the unsuccessful progress
302 * will be reported as the result code and error info of this progress.
303 * - returns N as the operation number, where N equals to the number of
304 * operations in all successfully completed progresses starting from the
305 * first one plus the operation number of the next (not yet complete)
306 * progress; the operation description of the latter one is reported as
307 * the operation description of this progress object.
308 * - returns P as the percent value, where P equals to the sum of percents
309 * of all successfully completed progresses starting from the
310 * first one plus the percent value of the next (not yet complete)
311 * progress, normalized to 100%.
312 *
313 * @note It's the respoisibility of the combined progress object creator to
314 * complete individual progresses in the right order: if, let's say, the
315 * last progress is completed before all previous ones,
316 * #WaitForCompletion(-1) will most likely give 100% CPU load because it
317 * will be in a loop calling a method that returns immediately.
318 */
319class ATL_NO_VTABLE CombinedProgress :
320 public com::SupportErrorInfoDerived<ProgressBase, CombinedProgress, IProgress>,
321 public VirtualBoxSupportTranslation<CombinedProgress>
322{
323
324public:
325
326 VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE (CombinedProgress)
327
328 DECLARE_NOT_AGGREGATABLE (CombinedProgress)
329
330 DECLARE_PROTECT_FINAL_CONSTRUCT()
331
332 BEGIN_COM_MAP (CombinedProgress)
333 COM_INTERFACE_ENTRY (ISupportErrorInfo)
334 COM_INTERFACE_ENTRY (IProgress)
335 COM_INTERFACE_ENTRY2 (IDispatch, IProgress)
336 END_COM_MAP()
337
338 HRESULT FinalConstruct();
339 void FinalRelease();
340
341 // public initializer/uninitializer for internal purposes only
342
343 HRESULT init (
344#if !defined (VBOX_COM_INPROC)
345 VirtualBox *aParent,
346#endif
347 IUnknown *aInitiator,
348 CBSTR aDescription,
349 IProgress *aProgress1, IProgress *aProgress2,
350 OUT_GUID aId = NULL);
351
352 /**
353 * Initializes the combined progress object given the first and the last
354 * normal progress object from the list.
355 *
356 * @param aParent See ProgressBase::init().
357 * @param aInitiator See ProgressBase::init().
358 * @param aDescription See ProgressBase::init().
359 * @param aFirstProgress Iterator of the first normal progress object.
360 * @param aSecondProgress Iterator of the last normal progress object.
361 * @param aId See ProgressBase::init().
362 */
363 template <typename InputIterator>
364 HRESULT init (
365#if !defined (VBOX_COM_INPROC)
366 VirtualBox *aParent,
367#endif
368 IUnknown *aInitiator,
369 CBSTR aDescription,
370 InputIterator aFirstProgress, InputIterator aLastProgress,
371 OUT_GUID aId = NULL)
372 {
373 /* Enclose the state transition NotReady->InInit->Ready */
374 AutoInitSpan autoInitSpan (this);
375 AssertReturn (autoInitSpan.isOk(), E_FAIL);
376
377 mProgresses = ProgressVector (aFirstProgress, aLastProgress);
378
379 HRESULT rc = protectedInit (autoInitSpan,
380#if !defined (VBOX_COM_INPROC)
381 aParent,
382#endif
383 aInitiator, aDescription, aId);
384
385 /* Confirm a successful initialization when it's the case */
386 if (SUCCEEDED (rc))
387 autoInitSpan.setSucceeded();
388
389 return rc;
390 }
391
392protected:
393
394 HRESULT protectedInit (AutoInitSpan &aAutoInitSpan,
395#if !defined (VBOX_COM_INPROC)
396 VirtualBox *aParent,
397#endif
398 IUnknown *aInitiator,
399 CBSTR aDescription, OUT_GUID aId);
400
401public:
402
403 void uninit();
404
405 // IProgress properties
406 STDMETHOD(COMGETTER(Percent)) (ULONG *aPercent);
407 STDMETHOD(COMGETTER(Completed)) (BOOL *aCompleted);
408 STDMETHOD(COMGETTER(Canceled)) (BOOL *aCanceled);
409 STDMETHOD(COMGETTER(ResultCode)) (LONG *aResultCode);
410 STDMETHOD(COMGETTER(ErrorInfo)) (IVirtualBoxErrorInfo **aErrorInfo);
411 STDMETHOD(COMGETTER(Operation)) (ULONG *aCount);
412 STDMETHOD(COMGETTER(OperationDescription)) (BSTR *aOperationDescription);
413 STDMETHOD(COMGETTER(OperationPercent)) (ULONG *aOperationPercent);
414 STDMETHOD(COMSETTER(Timeout)) (ULONG aTimeout);
415 STDMETHOD(COMGETTER(Timeout)) (ULONG *aTimeout);
416
417 // IProgress methods
418 STDMETHOD(WaitForCompletion) (LONG aTimeout);
419 STDMETHOD(WaitForOperationCompletion) (ULONG aOperation, LONG aTimeout);
420 STDMETHOD(Cancel)();
421
422 STDMETHOD(SetCurrentOperationProgress)(ULONG aPercent)
423 {
424 NOREF(aPercent);
425 return E_NOTIMPL;
426 }
427
428 STDMETHOD(SetNextOperation)(IN_BSTR bstrNextOperationDescription, ULONG ulNextOperationsWeight)
429 {
430 NOREF(bstrNextOperationDescription); NOREF(ulNextOperationsWeight);
431 return E_NOTIMPL;
432 }
433
434 // public methods only for internal purposes
435
436 /** For com::SupportErrorInfoImpl. */
437 static const char *ComponentName() { return "CombinedProgress"; }
438
439private:
440
441 HRESULT checkProgress();
442
443 typedef std::vector <ComPtr<IProgress> > ProgressVector;
444 ProgressVector mProgresses;
445
446 size_t mProgress;
447 ULONG mCompletedOperations;
448};
449
450#endif /* ____H_PROGRESSIMPL */
451
Note: See TracBrowser for help on using the repository browser.

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