VirtualBox

source: vbox/trunk/src/VBox/Main/include/objectslist.h@ 106061

Last change on this file since 106061 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.8 KB
Line 
1/* $Id: objectslist.h 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 *
4 * List of COM objects
5 */
6
7/*
8 * Copyright (C) 2009-2024 Oracle and/or its affiliates.
9 *
10 * This file is part of VirtualBox base platform packages, as
11 * available from https://www.virtualbox.org.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation, in version 3 of the
16 * License.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <https://www.gnu.org/licenses>.
25 *
26 * SPDX-License-Identifier: GPL-3.0-only
27 */
28
29#ifndef MAIN_INCLUDED_objectslist_h
30#define MAIN_INCLUDED_objectslist_h
31#ifndef RT_WITHOUT_PRAGMA_ONCE
32# pragma once
33#endif
34
35#include <list>
36#include <VBox/com/ptr.h>
37
38/**
39 * Implements a "flat" objects list with a lock. Since each such list
40 * has its own lock it is not a good idea to implement trees with this.
41 *
42 * ObjectList<T> is designed to behave as if it were a std::list of
43 * COM pointers of class T; in other words,
44 * ObjectList<Medium> behaves like std::list< ComObjPtr<Medium> > but
45 * it's less typing. Iterators, front(), size(), begin() and end()
46 * are implemented.
47 *
48 * In addition it automatically includes an RWLockHandle which can be
49 * accessed with getLockHandle().
50 *
51 * If you need the raw std::list for some reason you can access it with
52 * getList().
53 *
54 * The destructor automatically calls uninit() on every contained
55 * COM object. If this is not desired, clear the member list before
56 * deleting the list object.
57 */
58template<typename T>
59class ObjectsList
60{
61public:
62 typedef ComObjPtr<T> MyType;
63 typedef std::list<MyType> MyList;
64
65 typedef typename MyList::iterator iterator;
66 typedef typename MyList::const_iterator const_iterator;
67 // typename is necessary to disambiguate "::iterator" in templates; see
68 // the "this might hurt your head" part in
69 // http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18
70
71 ObjectsList(RWLockHandle &lockHandle)
72 : m_lock(lockHandle)
73 { }
74
75 ~ObjectsList()
76 {
77 uninitAll();
78 }
79
80private:
81 // prohibit copying and assignment
82 ObjectsList(const ObjectsList &d);
83 ObjectsList& operator=(const ObjectsList &d);
84
85public:
86
87 /**
88 * Returns the lock handle which protects this list, for use with
89 * AutoReadLock or AutoWriteLock.
90 */
91 RWLockHandle& getLockHandle()
92 {
93 return m_lock;
94 }
95
96 /**
97 * Calls m_ll.push_back(p) with locking.
98 * @param p
99 */
100 void addChild(MyType p)
101 {
102 AutoWriteLock al(m_lock COMMA_LOCKVAL_SRC_POS);
103 m_ll.push_back(p);
104 }
105
106 /**
107 * Calls m_ll.remove(p) with locking. Does NOT call uninit()
108 * on the contained object.
109 * @param p
110 */
111 void removeChild(MyType p)
112 {
113 AutoWriteLock al(m_lock COMMA_LOCKVAL_SRC_POS);
114 m_ll.remove(p);
115 }
116
117 /**
118 * Appends all objects from another list to the member list.
119 * Locks the other list for reading but does not lock "this"
120 * (because it might be on the caller's stack and needs no
121 * locking).
122 * @param ll
123 */
124 void appendOtherList(ObjectsList<T> &ll)
125 {
126 AutoReadLock alr(ll.getLockHandle() COMMA_LOCKVAL_SRC_POS);
127 for (const_iterator it = ll.begin();
128 it != ll.end();
129 ++it)
130 {
131 m_ll.push_back(*it);
132 }
133 }
134
135 /**
136 * Calls uninit() on every COM object on the list and then
137 * clears the list, with locking.
138 */
139 void uninitAll()
140 {
141 /* The implementation differs from the high level description, because
142 * it isn't safe to hold any locks when invoking uninit() methods. It
143 * leads to incorrect lock order (first lock, then the Caller related
144 * event semaphore) and thus deadlocks. Dropping the lock is vital,
145 * and means we can't rely on iterators while not holding the lock. */
146 AutoWriteLock al(m_lock COMMA_LOCKVAL_SRC_POS);
147 while (!m_ll.empty())
148 {
149 /* Need a copy of the element, have to delete the entry before
150 * dropping the lock, otherwise someone else might mess with the
151 * list in the mean time, leading to erratic behavior. */
152 MyType q = m_ll.front();
153 m_ll.pop_front();
154 al.release();
155 q->uninit();
156 al.acquire();
157 }
158 }
159
160 /**
161 * Returns the no. of objects on the list (std::list compatibility)
162 * with locking.
163 */
164 size_t size()
165 {
166 AutoReadLock al(m_lock COMMA_LOCKVAL_SRC_POS);
167 return m_ll.size();
168 }
169
170 /**
171 * Returns a raw pointer to the member list of objects.
172 * Does not lock!
173 * @return
174 */
175 MyList& getList()
176 {
177 return m_ll;
178 }
179
180 /**
181 * Returns the first object on the list (std::list compatibility)
182 * with locking.
183 */
184 MyType front()
185 {
186 AutoReadLock al(m_lock COMMA_LOCKVAL_SRC_POS);
187 return m_ll.front();
188 }
189
190 /**
191 * Returns the begin iterator from the list (std::list compatibility).
192 * Does not lock!
193 * @return
194 */
195 iterator begin()
196 {
197 return m_ll.begin();
198 }
199
200 /**
201 * Returns the end iterator from the list (std::list compatibility).
202 * Does not lock!
203 */
204 iterator end()
205 {
206 return m_ll.end();
207 }
208
209 void insert(iterator it, MyType &p)
210 {
211 m_ll.insert(it, p);
212 }
213
214 void erase(iterator it)
215 {
216 m_ll.erase(it);
217 }
218
219private:
220 MyList m_ll;
221 RWLockHandle &m_lock;
222};
223
224#endif /* !MAIN_INCLUDED_objectslist_h */
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