VirtualBox

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

Last change on this file since 71018 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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