VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/TokenImpl.cpp@ 49498

Last change on this file since 49498 was 48431, checked in by vboxsync, 11 years ago

Main/Machine+Session: New generic client session watcher implementation based on token objects, works on all platforms and is used for now on XPCOM. Additionally a better error message when several API clients are racing for a lock, previously it could be quite confusing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.6 KB
Line 
1/* $Id: TokenImpl.cpp 48431 2013-09-11 14:08:36Z vboxsync $ */
2/** @file
3 *
4 * Token COM class implementation: MachineToken and MediumLockToken
5 */
6
7/*
8 * Copyright (C) 2013 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#include "TokenImpl.h"
20#include "MachineImpl.h"
21#include "MediumImpl.h"
22#include "AutoCaller.h"
23#include "Logging.h"
24
25// constructor / destructor
26/////////////////////////////////////////////////////////////////////////////
27
28DEFINE_EMPTY_CTOR_DTOR(MachineToken)
29
30HRESULT MachineToken::FinalConstruct()
31{
32 return BaseFinalConstruct();
33}
34
35void MachineToken::FinalRelease()
36{
37 uninit(false);
38
39 BaseFinalRelease();
40}
41
42// public initializer/uninitializer for internal purposes only
43/////////////////////////////////////////////////////////////////////////////
44
45/**
46 * Initializes the token object.
47 *
48 * @param pSessionMachine Pointer to a SessionMachine object.
49 */
50HRESULT MachineToken::init(const ComObjPtr<SessionMachine> &pSessionMachine)
51{
52 LogFlowThisFunc(("pSessionMachine=%p\n", &pSessionMachine));
53
54 ComAssertRet(!pSessionMachine.isNull(), E_INVALIDARG);
55
56 /* Enclose the state transition NotReady->InInit->Ready */
57 AutoInitSpan autoInitSpan(this);
58 AssertReturn(autoInitSpan.isOk(), E_FAIL);
59
60 m.pSessionMachine = pSessionMachine;
61
62 /* Confirm a successful initialization */
63 autoInitSpan.setSucceeded();
64
65 return S_OK;
66}
67
68/**
69 * Uninitializes the instance and sets the ready flag to FALSE.
70 * Called either from FinalRelease() or by the parent when it gets destroyed.
71 */
72void MachineToken::uninit(bool fAbandon)
73{
74 LogFlowThisFunc(("\n"));
75
76 /* Enclose the state transition Ready->InUninit->NotReady */
77 AutoUninitSpan autoUninitSpan(this);
78 if (autoUninitSpan.uninitDone())
79 return;
80
81 /* Destroy the SessionMachine object, check is paranoia */
82 if (!m.pSessionMachine.isNull())
83 {
84 m.pSessionMachine->uninit(fAbandon ? SessionMachine::Uninit::Normal : SessionMachine::Uninit::Abnormal);
85 m.pSessionMachine.setNull();
86 }
87}
88
89// IToken methods
90/////////////////////////////////////////////////////////////////////////////
91
92HRESULT MachineToken::abandon(AutoCaller &aAutoCaller)
93{
94 /* have to release the AutoCaller before calling uninit(), self-deadlock */
95 aAutoCaller.release();
96
97 /* uninit does everything we need */
98 uninit(true);
99 return S_OK;
100}
101
102HRESULT MachineToken::dummy()
103{
104 /* Remember, the wrapper contains the AutoCaller, which means that after
105 * uninit() this code won't be reached any more. */
106
107 /* this is a NOOP, no need to lock */
108
109 return S_OK;
110}
111
112// public methods only for internal purposes
113/////////////////////////////////////////////////////////////////////////////
114
115
116// constructor / destructor
117/////////////////////////////////////////////////////////////////////////////
118
119DEFINE_EMPTY_CTOR_DTOR(MediumLockToken)
120
121HRESULT MediumLockToken::FinalConstruct()
122{
123 return BaseFinalConstruct();
124}
125
126void MediumLockToken::FinalRelease()
127{
128 uninit();
129
130 BaseFinalRelease();
131}
132
133// public initializer/uninitializer for internal purposes only
134/////////////////////////////////////////////////////////////////////////////
135
136/**
137 * Initializes the token object.
138 *
139 * @param pMedium Pointer to a Medium object.
140 * @param fWrite True if this is a write lock, false otherwise.
141 */
142HRESULT MediumLockToken::init(const ComObjPtr<Medium> &pMedium, bool fWrite)
143{
144 LogFlowThisFunc(("pMedium=%p\n", &pMedium));
145
146 ComAssertRet(!pMedium.isNull(), E_INVALIDARG);
147
148 /* Enclose the state transition NotReady->InInit->Ready */
149 AutoInitSpan autoInitSpan(this);
150 AssertReturn(autoInitSpan.isOk(), E_FAIL);
151
152 m.pMedium = pMedium;
153 m.fWrite = fWrite;
154
155 /* Confirm a successful initialization */
156 autoInitSpan.setSucceeded();
157
158 return S_OK;
159}
160
161/**
162 * Uninitializes the instance and sets the ready flag to FALSE.
163 * Called either from FinalRelease() or by the parent when it gets destroyed.
164 */
165void MediumLockToken::uninit()
166{
167 LogFlowThisFunc(("\n"));
168
169 /* Enclose the state transition Ready->InUninit->NotReady */
170 AutoUninitSpan autoUninitSpan(this);
171 if (autoUninitSpan.uninitDone())
172 return;
173
174 /* Release the appropriate lock, check is paranoia */
175 if (!m.pMedium.isNull())
176 {
177 if (m.fWrite)
178 {
179 HRESULT rc = m.pMedium->unlockWrite(NULL);
180 AssertComRC(rc);
181 }
182 else
183 {
184 HRESULT rc = m.pMedium->unlockRead(NULL);
185 AssertComRC(rc);
186 }
187 m.pMedium.setNull();
188 }
189}
190
191// IToken methods
192/////////////////////////////////////////////////////////////////////////////
193
194HRESULT MediumLockToken::abandon(AutoCaller &aAutoCaller)
195{
196 /* have to release the AutoCaller before calling uninit(), self-deadlock */
197 aAutoCaller.release();
198
199 /* uninit does everything we need */
200 uninit();
201 return S_OK;
202}
203
204HRESULT MediumLockToken::dummy()
205{
206 /* Remember, the wrapper contains the AutoCaller, which means that after
207 * uninit() this code won't be reached any more. */
208
209 /* this is a NOOP, no need to lock */
210
211 return S_OK;
212}
213
214// public methods only for internal purposes
215/////////////////////////////////////////////////////////////////////////////
216
217/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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