VirtualBox

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

Last change on this file since 78382 was 76562, checked in by vboxsync, 6 years ago

Main: Use MAIN_INCLUDED_ and MAIN_INCLUDED_SRC_ as header guard prefixes with scm.

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