VirtualBox

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

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

Main: rework IProgress internals to optionally handle weighted operations; rename some internal IProgress methods; change percentage APIs to use ULONGs instead of LONGs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.0 KB
Line 
1/* $Id: ProgressImpl.h 18269 2009-03-25 18:01:07Z 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.215389.xyz. 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 VirtualBoxBaseNEXT,
43 public com::SupportErrorInfoBase,
44 public VirtualBoxSupportTranslation <ProgressBase>,
45 public 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)) (OUT_GUID 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(Completed)) (BOOL *aCompleted);
76 STDMETHOD(COMGETTER(Canceled)) (BOOL *aCanceled);
77 STDMETHOD(COMGETTER(ResultCode)) (HRESULT *aResultCode);
78 STDMETHOD(COMGETTER(ErrorInfo)) (IVirtualBoxErrorInfo **aErrorInfo);
79 STDMETHOD(COMGETTER(OperationCount)) (ULONG *aOperationCount);
80 STDMETHOD(COMGETTER(Operation)) (ULONG *aCount);
81 STDMETHOD(COMGETTER(OperationDescription)) (BSTR *aOperationDescription);
82 STDMETHOD(COMGETTER(OperationPercent)) (ULONG *aOperationPercent);
83
84 // public methods only for internal purposes
85
86 static HRESULT setErrorInfoOnThread (IProgress *aProgress);
87
88 // unsafe inline public methods for internal purposes only (ensure there is
89 // a caller and a read lock before calling them!)
90
91 BOOL completed() const { return mCompleted; }
92 HRESULT resultCode() const { return mResultCode; }
93
94protected:
95
96#if !defined (VBOX_COM_INPROC)
97 /** Weak parent. */
98 const ComObjPtr <VirtualBox, ComWeakRef> mParent;
99#endif
100
101 const ComPtr <IUnknown> mInitiator;
102
103 const Guid mId;
104 const Bstr mDescription;
105
106 /* The fields below are to be properly initalized by subclasses */
107
108 BOOL mCompleted;
109 BOOL mCancelable;
110 BOOL mCanceled;
111 HRESULT mResultCode;
112 ComPtr <IVirtualBoxErrorInfo> mErrorInfo;
113
114 ULONG m_cOperations; // number of operations (so that progress dialog can display something like 1/3)
115 ULONG m_ulTotalOperationsWeight; // sum of weights of all operations, given to constructor
116
117 ULONG m_ulOperationsCompletedWeight; // summed-up weight of operations that have been completed; initially 0
118
119 ULONG m_ulCurrentOperation; // operations counter, incremented with each setNextOperation()
120 Bstr m_bstrOperationDescription; // name of current operation; initially from constructor, changed with setNextOperation()
121 ULONG m_ulCurrentOperationWeight; // weight of current operation, given to setNextOperation()
122 ULONG m_ulOperationPercent; // percentage of current operation, set with setCurrentOperationProgress()
123};
124
125////////////////////////////////////////////////////////////////////////////////
126
127/**
128 * Normal progress object.
129 */
130class ATL_NO_VTABLE Progress :
131 public com::SupportErrorInfoDerived <ProgressBase, Progress, IProgress>,
132 public VirtualBoxSupportTranslation <Progress>
133{
134
135public:
136
137 VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE (Progress)
138
139 DECLARE_NOT_AGGREGATABLE (Progress)
140
141 DECLARE_PROTECT_FINAL_CONSTRUCT()
142
143 BEGIN_COM_MAP (Progress)
144 COM_INTERFACE_ENTRY (ISupportErrorInfo)
145 COM_INTERFACE_ENTRY (IProgress)
146 END_COM_MAP()
147
148 NS_DECL_ISUPPORTS
149
150 HRESULT FinalConstruct();
151 void FinalRelease();
152
153 // public initializer/uninitializer for internal purposes only
154
155 /**
156 * Simplified constructor for progress objects that have only one
157 * operation as a task.
158 * @param aParent
159 * @param aInitiator
160 * @param aDescription
161 * @param aCancelable
162 * @param aId
163 * @return
164 */
165 HRESULT init(
166#if !defined (VBOX_COM_INPROC)
167 VirtualBox *aParent,
168#endif
169 IUnknown *aInitiator,
170 CBSTR aDescription, BOOL aCancelable,
171 OUT_GUID aId = NULL)
172 {
173 return init(
174#if !defined (VBOX_COM_INPROC)
175 aParent,
176#endif
177 aInitiator,
178 aDescription,
179 aCancelable,
180 1, // cOperations
181 1, // ulTotalOperationsWeight
182 aDescription, // bstrFirstOperationDescription
183 1, // ulFirstOperationWeight
184 aId);
185 }
186
187 /**
188 * Not quite so simplified constructor for progress objects that have
189 * more than one operation, but all sub-operations are weighed the same.
190 * @param aParent
191 * @param aInitiator
192 * @param aDescription
193 * @param aCancelable
194 * @param cOperations
195 * @param bstrFirstOperationDescription
196 * @param aId
197 * @return
198 */
199 HRESULT init(
200#if !defined (VBOX_COM_INPROC)
201 VirtualBox *aParent,
202#endif
203 IUnknown *aInitiator,
204 CBSTR aDescription, BOOL aCancelable,
205 ULONG cOperations,
206 CBSTR bstrFirstOperationDescription,
207 OUT_GUID aId = NULL)
208 {
209 return init(
210#if !defined (VBOX_COM_INPROC)
211 aParent,
212#endif
213 aInitiator,
214 aDescription,
215 aCancelable,
216 cOperations, // cOperations
217 cOperations, // ulTotalOperationsWeight = cOperations
218 bstrFirstOperationDescription, // bstrFirstOperationDescription
219 1, // ulFirstOperationWeight: weigh them all the same
220 aId);
221 }
222
223 HRESULT init(
224#if !defined (VBOX_COM_INPROC)
225 VirtualBox *aParent,
226#endif
227 IUnknown *aInitiator,
228 CBSTR aDescription, BOOL aCancelable,
229 ULONG cOperations, ULONG ulTotalOperationsWeight,
230 CBSTR bstrFirstOperationDescription, ULONG ulFirstOperationWeight,
231 OUT_GUID aId = NULL);
232
233 HRESULT init (BOOL aCancelable, ULONG aOperationCount,
234 CBSTR aOperationDescription);
235
236 void uninit();
237
238 // IProgress methods
239 STDMETHOD(WaitForCompletion)(LONG aTimeout);
240 STDMETHOD(WaitForOperationCompletion)(ULONG aOperation, LONG aTimeout);
241 STDMETHOD(Cancel)();
242
243 // public methods only for internal purposes
244
245 HRESULT setCurrentOperationProgress(ULONG aPercent);
246 HRESULT setNextOperation(CBSTR bstrNextOperationDescription, ULONG ulNextOperationsWeight);
247
248 HRESULT notifyComplete(HRESULT aResultCode);
249 HRESULT notifyComplete(HRESULT aResultCode, const GUID &aIID,
250 const Bstr &aComponent,
251 const char *aText, ...);
252 HRESULT notifyCompleteBstr(HRESULT aResultCode, const GUID &aIID,
253 const Bstr &aComponent, const Bstr &aText);
254
255 /** For com::SupportErrorInfoImpl. */
256 static const char *ComponentName() { return "Progress"; }
257
258private:
259
260 RTSEMEVENTMULTI mCompletedSem;
261 ULONG mWaitersCount;
262};
263
264////////////////////////////////////////////////////////////////////////////////
265
266/**
267 * The CombinedProgress class allows to combine several progress objects to a
268 * single progress component. This single progress component will treat all
269 * operations of individual progress objects as a single sequence of operations
270 * that follow each other in the same order as progress objects are passed to
271 * the #init() method.
272 *
273 * Individual progress objects are sequentially combined so that this progress
274 * object:
275 *
276 * - is cancelable only if all progresses are cancelable.
277 * - is canceled once a progress that follows next to successfully completed
278 * ones reports it was canceled.
279 * - is completed successfully only after all progresses are completed
280 * successfully.
281 * - is completed unsuccessfully once a progress that follows next to
282 * successfully completed ones reports it was completed unsuccessfully;
283 * the result code and error info of the unsuccessful progress
284 * will be reported as the result code and error info of this progress.
285 * - returns N as the operation number, where N equals to the number of
286 * operations in all successfully completed progresses starting from the
287 * first one plus the operation number of the next (not yet complete)
288 * progress; the operation description of the latter one is reported as
289 * the operation description of this progress object.
290 * - returns P as the percent value, where P equals to the sum of percents
291 * of all successfully completed progresses starting from the
292 * first one plus the percent value of the next (not yet complete)
293 * progress, normalized to 100%.
294 *
295 * @note It's the respoisibility of the combined progress object creator to
296 * complete individual progresses in the right order: if, let's say, the
297 * last progress is completed before all previous ones,
298 * #WaitForCompletion(-1) will most likely give 100% CPU load because it
299 * will be in a loop calling a method that returns immediately.
300 */
301class ATL_NO_VTABLE CombinedProgress :
302 public com::SupportErrorInfoDerived <ProgressBase, CombinedProgress, IProgress>,
303 public VirtualBoxSupportTranslation <CombinedProgress>
304{
305
306public:
307
308 VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE (CombinedProgress)
309
310 DECLARE_NOT_AGGREGATABLE (CombinedProgress)
311
312 DECLARE_PROTECT_FINAL_CONSTRUCT()
313
314 BEGIN_COM_MAP (CombinedProgress)
315 COM_INTERFACE_ENTRY (ISupportErrorInfo)
316 COM_INTERFACE_ENTRY (IProgress)
317 END_COM_MAP()
318
319 NS_DECL_ISUPPORTS
320
321 HRESULT FinalConstruct();
322 void FinalRelease();
323
324 // public initializer/uninitializer for internal purposes only
325
326 HRESULT init (
327#if !defined (VBOX_COM_INPROC)
328 VirtualBox *aParent,
329#endif
330 IUnknown *aInitiator,
331 CBSTR aDescription,
332 IProgress *aProgress1, IProgress *aProgress2,
333 OUT_GUID aId = NULL);
334
335 /**
336 * Initializes the combined progress object given the first and the last
337 * normal progress object from the list.
338 *
339 * @param aParent See ProgressBase::init().
340 * @param aInitiator See ProgressBase::init().
341 * @param aDescription See ProgressBase::init().
342 * @param aFirstProgress Iterator of the first normal progress object.
343 * @param aSecondProgress Iterator of the last normal progress object.
344 * @param aId See ProgressBase::init().
345 */
346 template <typename InputIterator>
347 HRESULT init (
348#if !defined (VBOX_COM_INPROC)
349 VirtualBox *aParent,
350#endif
351 IUnknown *aInitiator,
352 CBSTR aDescription,
353 InputIterator aFirstProgress, InputIterator aLastProgress,
354 OUT_GUID aId = NULL)
355 {
356 /* Enclose the state transition NotReady->InInit->Ready */
357 AutoInitSpan autoInitSpan (this);
358 AssertReturn (autoInitSpan.isOk(), E_FAIL);
359
360 mProgresses = ProgressVector (aFirstProgress, aLastProgress);
361
362 HRESULT rc = protectedInit (autoInitSpan,
363#if !defined (VBOX_COM_INPROC)
364 aParent,
365#endif
366 aInitiator, aDescription, aId);
367
368 /* Confirm a successful initialization when it's the case */
369 if (SUCCEEDED (rc))
370 autoInitSpan.setSucceeded();
371
372 return rc;
373 }
374
375protected:
376
377 HRESULT protectedInit (AutoInitSpan &aAutoInitSpan,
378#if !defined (VBOX_COM_INPROC)
379 VirtualBox *aParent,
380#endif
381 IUnknown *aInitiator,
382 CBSTR aDescription, OUT_GUID aId);
383
384public:
385
386 void uninit();
387
388 // IProgress properties
389 STDMETHOD(COMGETTER(Percent)) (ULONG *aPercent);
390 STDMETHOD(COMGETTER(Completed)) (BOOL *aCompleted);
391 STDMETHOD(COMGETTER(Canceled)) (BOOL *aCanceled);
392 STDMETHOD(COMGETTER(ResultCode)) (HRESULT *aResultCode);
393 STDMETHOD(COMGETTER(ErrorInfo)) (IVirtualBoxErrorInfo **aErrorInfo);
394 STDMETHOD(COMGETTER(Operation)) (ULONG *aCount);
395 STDMETHOD(COMGETTER(OperationDescription)) (BSTR *aOperationDescription);
396 STDMETHOD(COMGETTER(OperationPercent)) (ULONG *aOperationPercent);
397
398 // IProgress methods
399 STDMETHOD(WaitForCompletion) (LONG aTimeout);
400 STDMETHOD(WaitForOperationCompletion) (ULONG aOperation, LONG aTimeout);
401 STDMETHOD(Cancel)();
402
403 // public methods only for internal purposes
404
405 /** For com::SupportErrorInfoImpl. */
406 static const char *ComponentName() { return "CombinedProgress"; }
407
408private:
409
410 HRESULT checkProgress();
411
412 typedef std::vector <ComPtr <IProgress> > ProgressVector;
413 ProgressVector mProgresses;
414
415 size_t mProgress;
416 ULONG mCompletedOperations;
417};
418
419#endif /* ____H_PROGRESSIMPL */
420
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