168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync/** @file
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync *
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * List of COM objects
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync/*
2de0a3f09fd2af308c05d8d27f963a91951826b0vboxsync * Copyright (C) 2009-2014 Oracle Corporation
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync *
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * available from http://www.virtualbox.org. This file is free software;
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * General Public License (GPL) as published by the Free Software
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync#ifndef ____H_OBJECTSLIST
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync#define ____H_OBJECTSLIST
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync#include <list>
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync#include <VBox/com/ptr.h>
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync/**
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Implements a "flat" objects list with a lock. Since each such list
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * has its own lock it is not a good idea to implement trees with this.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync *
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * ObjectList<T> is designed to behave as if it were a std::list of
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * COM pointers of class T; in other words,
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * ObjectList<Medium> behaves like std::list< ComObjPtr<Medium> > but
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * it's less typing. Iterators, front(), size(), begin() and end()
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * are implemented.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync *
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * In addition it automatically includes an RWLockHandle which can be
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * accessed with getLockHandle().
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync *
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * If you need the raw std::list for some reason you can access it with
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * getList().
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync *
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * The destructor automatically calls uninit() on every contained
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * COM object. If this is not desired, clear the member list before
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * deleting the list object.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsynctemplate<typename T>
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsyncclass ObjectsList
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync{
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsyncpublic:
d19316699d7f91959d88c850fd7e0d64840f39a7vboxsync typedef ComObjPtr<T> MyType;
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync typedef std::list<MyType> MyList;
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync typedef typename MyList::iterator iterator;
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync typedef typename MyList::const_iterator const_iterator;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync // typename is necessary to disambiguate "::iterator" in templates; see
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync // the "this might hurt your head" part in
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync // http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
61b7134c0136067d2be618bd96e016854e299645vboxsync ObjectsList(RWLockHandle &lockHandle)
61b7134c0136067d2be618bd96e016854e299645vboxsync : m_lock(lockHandle)
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync { }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync ~ObjectsList()
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync uninitAll();
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
ac99fbe0a96325349539e70433094ba2b53b204fvboxsyncprivate:
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync // prohibit copying and assignment
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync ObjectsList(const ObjectsList &d);
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync ObjectsList& operator=(const ObjectsList &d);
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync
ac99fbe0a96325349539e70433094ba2b53b204fvboxsyncpublic:
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync /**
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Returns the lock handle which protects this list, for use with
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * AutoReadLock or AutoWriteLock.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync RWLockHandle& getLockHandle()
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync return m_lock;
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync /**
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Calls m_ll.push_back(p) with locking.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * @param p
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync void addChild(MyType p)
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
aa28b72963d5e1c22902b7f4b6066ae806fb919fvboxsync AutoWriteLock al(m_lock COMMA_LOCKVAL_SRC_POS);
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync m_ll.push_back(p);
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync /**
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Calls m_ll.remove(p) with locking. Does NOT call uninit()
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * on the contained object.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * @param p
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync void removeChild(MyType p)
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
aa28b72963d5e1c22902b7f4b6066ae806fb919fvboxsync AutoWriteLock al(m_lock COMMA_LOCKVAL_SRC_POS);
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync m_ll.remove(p);
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync /**
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Appends all objects from another list to the member list.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Locks the other list for reading but does not lock "this"
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * (because it might be on the caller's stack and needs no
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * locking).
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * @param ll
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync void appendOtherList(ObjectsList<T> &ll)
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
aa28b72963d5e1c22902b7f4b6066ae806fb919fvboxsync AutoReadLock alr(ll.getLockHandle() COMMA_LOCKVAL_SRC_POS);
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync for (const_iterator it = ll.begin();
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync it != ll.end();
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync ++it)
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync m_ll.push_back(*it);
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync /**
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync * Calls uninit() on every COM object on the list and then
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync * clears the list, with locking.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync void uninitAll()
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync /* The implementation differs from the high level description, because
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync * it isn't safe to hold any locks when invoking uninit() methods. It
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync * leads to incorrect lock order (first lock, then the Caller related
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync * event semaphore) and thus deadlocks. Dropping the lock is vital,
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync * and means we can't rely on iterators while not holding the lock. */
aa28b72963d5e1c22902b7f4b6066ae806fb919fvboxsync AutoWriteLock al(m_lock COMMA_LOCKVAL_SRC_POS);
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync while (!m_ll.empty())
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync {
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync /* Need a copy of the element, have to delete the entry before
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync * dropping the lock, otherwise someone else might mess with the
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync * list in the mean time, leading to erratic behavior. */
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync MyType q = m_ll.front();
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync m_ll.pop_front();
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync al.release();
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync q->uninit();
690c0b91f098addeaeef698b249bf7c61eed8ee8vboxsync al.acquire();
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync /**
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync * Returns the no. of objects on the list (std::list compatibility)
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * with locking.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync size_t size()
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
aa28b72963d5e1c22902b7f4b6066ae806fb919fvboxsync AutoReadLock al(m_lock COMMA_LOCKVAL_SRC_POS);
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync return m_ll.size();
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync /**
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Returns a raw pointer to the member list of objects.
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Does not lock!
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * @return
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync MyList& getList()
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync return m_ll;
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync /**
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync * Returns the first object on the list (std::list compatibility)
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync * with locking.
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync */
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync MyType front()
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync {
aa28b72963d5e1c22902b7f4b6066ae806fb919fvboxsync AutoReadLock al(m_lock COMMA_LOCKVAL_SRC_POS);
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync return m_ll.front();
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync }
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync /**
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Returns the begin iterator from the list (std::list compatibility).
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Does not lock!
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * @return
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync iterator begin()
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync return m_ll.begin();
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync /**
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Returns the end iterator from the list (std::list compatibility).
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync * Does not lock!
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync */
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync iterator end()
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync return m_ll.end();
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync void insert(iterator it, MyType &p)
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync {
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync m_ll.insert(it, p);
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync }
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync void erase(iterator it)
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync {
ac99fbe0a96325349539e70433094ba2b53b204fvboxsync m_ll.erase(it);
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync }
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsyncprivate:
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync MyList m_ll;
61b7134c0136067d2be618bd96e016854e299645vboxsync RWLockHandle &m_lock;
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync};
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync
168d8e5243c71b5d181b789b3b6370ae562c5d0bvboxsync#endif