1 | /* $Id: AutoStateDep.h 82968 2020-02-04 10:35:17Z vboxsync $ */
|
---|
2 |
|
---|
3 | #ifndef MAIN_INCLUDED_AutoStateDep_h
|
---|
4 | #define MAIN_INCLUDED_AutoStateDep_h
|
---|
5 | #ifndef RT_WITHOUT_PRAGMA_ONCE
|
---|
6 | # pragma once
|
---|
7 | #endif
|
---|
8 |
|
---|
9 | /** @file
|
---|
10 | *
|
---|
11 | * AutoStateDep template classes, formerly in MachineImpl.h. Use these if
|
---|
12 | * you need to ensure that the machine state does not change over a certain
|
---|
13 | * period of time.
|
---|
14 | */
|
---|
15 |
|
---|
16 | /*
|
---|
17 | * Copyright (C) 2006-2020 Oracle Corporation
|
---|
18 | *
|
---|
19 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
20 | * available from http://www.virtualbox.org. This file is free software;
|
---|
21 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
22 | * General Public License (GPL) as published by the Free Software
|
---|
23 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
24 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
25 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
26 | */
|
---|
27 |
|
---|
28 | /**
|
---|
29 | * Helper class that safely manages the machine state dependency by
|
---|
30 | * calling Machine::addStateDependency() on construction and
|
---|
31 | * Machine::releaseStateDependency() on destruction. Intended for Machine
|
---|
32 | * children. The usage pattern is:
|
---|
33 | *
|
---|
34 | * @code
|
---|
35 | * AutoCaller autoCaller(this);
|
---|
36 | * if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
37 | *
|
---|
38 | * Machine::AutoStateDependency<MutableStateDep> adep(mParent);
|
---|
39 | * if (FAILED(stateDep.rc())) return stateDep.rc();
|
---|
40 | * ...
|
---|
41 | * // code that depends on the particular machine state
|
---|
42 | * ...
|
---|
43 | * @endcode
|
---|
44 | *
|
---|
45 | * Note that it is more convenient to use the following individual
|
---|
46 | * shortcut classes instead of using this template directly:
|
---|
47 | * AutoAnyStateDependency, AutoMutableStateDependency,
|
---|
48 | * AutoMutableOrSavedStateDependency, AutoMutableOrRunningStateDependency
|
---|
49 | * or AutoMutableOrSavedOrRunningStateDependency. The usage pattern is
|
---|
50 | * exactly the same as above except that there is no need to specify the
|
---|
51 | * template argument because it is already done by the shortcut class.
|
---|
52 | *
|
---|
53 | * @param taDepType Dependency type to manage.
|
---|
54 | */
|
---|
55 | template <Machine::StateDependency taDepType = Machine::AnyStateDep>
|
---|
56 | class AutoStateDependency
|
---|
57 | {
|
---|
58 | public:
|
---|
59 |
|
---|
60 | AutoStateDependency(Machine *aThat)
|
---|
61 | : mThat(aThat), mRC(S_OK),
|
---|
62 | mMachineState(MachineState_Null),
|
---|
63 | mRegistered(FALSE)
|
---|
64 | {
|
---|
65 | Assert(aThat);
|
---|
66 | mRC = aThat->i_addStateDependency(taDepType, &mMachineState,
|
---|
67 | &mRegistered);
|
---|
68 | }
|
---|
69 | ~AutoStateDependency()
|
---|
70 | {
|
---|
71 | if (SUCCEEDED(mRC))
|
---|
72 | mThat->i_releaseStateDependency();
|
---|
73 | }
|
---|
74 |
|
---|
75 | /** Decreases the number of dependencies before the instance is
|
---|
76 | * destroyed. Note that will reset #rc() to E_FAIL. */
|
---|
77 | void release()
|
---|
78 | {
|
---|
79 | AssertReturnVoid(SUCCEEDED(mRC));
|
---|
80 | mThat->i_releaseStateDependency();
|
---|
81 | mRC = E_FAIL;
|
---|
82 | }
|
---|
83 |
|
---|
84 | /** Restores the number of callers after by #release(). #rc() will be
|
---|
85 | * reset to the result of calling addStateDependency() and must be
|
---|
86 | * rechecked to ensure the operation succeeded. */
|
---|
87 | void add()
|
---|
88 | {
|
---|
89 | AssertReturnVoid(!SUCCEEDED(mRC));
|
---|
90 | mRC = mThat->i_addStateDependency(taDepType, &mMachineState,
|
---|
91 | &mRegistered);
|
---|
92 | }
|
---|
93 |
|
---|
94 | /** Returns the result of Machine::addStateDependency(). */
|
---|
95 | HRESULT rc() const { return mRC; }
|
---|
96 |
|
---|
97 | /** Shortcut to SUCCEEDED(rc()). */
|
---|
98 | bool isOk() const { return SUCCEEDED(mRC); }
|
---|
99 |
|
---|
100 | /** Returns the machine state value as returned by
|
---|
101 | * Machine::addStateDependency(). */
|
---|
102 | MachineState_T machineState() const { return mMachineState; }
|
---|
103 |
|
---|
104 | /** Returns the machine state value as returned by
|
---|
105 | * Machine::addStateDependency(). */
|
---|
106 | BOOL machineRegistered() const { return mRegistered; }
|
---|
107 |
|
---|
108 | protected:
|
---|
109 |
|
---|
110 | Machine *mThat;
|
---|
111 | HRESULT mRC;
|
---|
112 | MachineState_T mMachineState;
|
---|
113 | BOOL mRegistered;
|
---|
114 |
|
---|
115 | private:
|
---|
116 |
|
---|
117 | DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoStateDependency);
|
---|
118 | DECLARE_CLS_NEW_DELETE_NOOP(AutoStateDependency);
|
---|
119 | };
|
---|
120 |
|
---|
121 | /**
|
---|
122 | * Shortcut to AutoStateDependency<AnyStateDep>.
|
---|
123 | * See AutoStateDependency to get the usage pattern.
|
---|
124 | *
|
---|
125 | * Accepts any machine state and guarantees the state won't change before
|
---|
126 | * this object is destroyed. If the machine state cannot be protected (as
|
---|
127 | * a result of the state change currently in progress), this instance's
|
---|
128 | * #rc() method will indicate a failure, and the caller is not allowed to
|
---|
129 | * rely on any particular machine state and should return the failed
|
---|
130 | * result code to the upper level.
|
---|
131 | */
|
---|
132 | typedef AutoStateDependency<Machine::AnyStateDep> AutoAnyStateDependency;
|
---|
133 |
|
---|
134 | /**
|
---|
135 | * Shortcut to AutoStateDependency<MutableStateDep>.
|
---|
136 | * See AutoStateDependency to get the usage pattern.
|
---|
137 | *
|
---|
138 | * Succeeds only if the machine state is in one of the mutable states, and
|
---|
139 | * guarantees the given mutable state won't change before this object is
|
---|
140 | * destroyed. If the machine is not mutable, this instance's #rc() method
|
---|
141 | * will indicate a failure, and the caller is not allowed to rely on any
|
---|
142 | * particular machine state and should return the failed result code to
|
---|
143 | * the upper level.
|
---|
144 | *
|
---|
145 | * Intended to be used within all setter methods of IMachine
|
---|
146 | * children objects (DVDDrive, NetworkAdapter, AudioAdapter, etc.) to
|
---|
147 | * provide data protection and consistency. There must be no VM process,
|
---|
148 | * i.e. use for settings changes which are valid when the VM is shut down.
|
---|
149 | */
|
---|
150 | typedef AutoStateDependency<Machine::MutableStateDep> AutoMutableStateDependency;
|
---|
151 |
|
---|
152 | /**
|
---|
153 | * Shortcut to AutoStateDependency<MutableOrSavedStateDep>.
|
---|
154 | * See AutoStateDependency to get the usage pattern.
|
---|
155 | *
|
---|
156 | * Succeeds only if the machine state is in one of the mutable states, or
|
---|
157 | * if the machine is in the Saved state, and guarantees the given mutable
|
---|
158 | * state won't change before this object is destroyed. If the machine is
|
---|
159 | * not mutable, this instance's #rc() method will indicate a failure, and
|
---|
160 | * the caller is not allowed to rely on any particular machine state and
|
---|
161 | * should return the failed result code to the upper level.
|
---|
162 | *
|
---|
163 | * Intended to be used within setter methods of IMachine
|
---|
164 | * children objects that may operate on shut down or Saved machines.
|
---|
165 | */
|
---|
166 | typedef AutoStateDependency<Machine::MutableOrSavedStateDep> AutoMutableOrSavedStateDependency;
|
---|
167 |
|
---|
168 | /**
|
---|
169 | * Shortcut to AutoStateDependency<MutableOrRunningStateDep>.
|
---|
170 | * See AutoStateDependency to get the usage pattern.
|
---|
171 | *
|
---|
172 | * Succeeds only if the machine state is in one of the mutable states, or
|
---|
173 | * if the machine is in the Running or Paused state, and guarantees the
|
---|
174 | * given mutable state won't change before this object is destroyed. If
|
---|
175 | * the machine is not mutable, this instance's #rc() method will indicate
|
---|
176 | * a failure, and the caller is not allowed to rely on any particular
|
---|
177 | * machine state and should return the failed result code to the upper
|
---|
178 | * level.
|
---|
179 | *
|
---|
180 | * Intended to be used within setter methods of IMachine
|
---|
181 | * children objects that may operate on shut down or running machines.
|
---|
182 | */
|
---|
183 | typedef AutoStateDependency<Machine::MutableOrRunningStateDep> AutoMutableOrRunningStateDependency;
|
---|
184 |
|
---|
185 | /**
|
---|
186 | * Shortcut to AutoStateDependency<MutableOrSavedOrRunningStateDep>.
|
---|
187 | * See AutoStateDependency to get the usage pattern.
|
---|
188 | *
|
---|
189 | * Succeeds only if the machine state is in one of the mutable states, or
|
---|
190 | * if the machine is in the Running, Paused or Saved state, and guarantees
|
---|
191 | * the given mutable state won't change before this object is destroyed.
|
---|
192 | * If the machine is not mutable, this instance's #rc() method will
|
---|
193 | * indicate a failure, and the caller is not allowed to rely on any
|
---|
194 | * particular machine state and should return the failed result code to
|
---|
195 | * the upper level.
|
---|
196 | *
|
---|
197 | * Intended to be used within setter methods of IMachine
|
---|
198 | * children objects that may operate on shut down, running or saved
|
---|
199 | * machines.
|
---|
200 | */
|
---|
201 | typedef AutoStateDependency<Machine::MutableOrSavedOrRunningStateDep> AutoMutableOrSavedOrRunningStateDependency;
|
---|
202 |
|
---|
203 | #endif /* !MAIN_INCLUDED_AutoStateDep_h */
|
---|
204 |
|
---|