summaryrefslogtreecommitdiffstats
path: root/raul/Maid.hpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-08-15 17:50:17 +0000
committerDavid Robillard <d@drobilla.net>2012-08-15 17:50:17 +0000
commit55603c281a49070bd941e79093cc20a144f9ee4a (patch)
tree33a532618678dfd8d2ab90848789bf5e74a60cee /raul/Maid.hpp
parent2118d961d97a1e454ee5391785b700d70f22f387 (diff)
downloadraul-55603c281a49070bd941e79093cc20a144f9ee4a.tar.gz
raul-55603c281a49070bd941e79093cc20a144f9ee4a.tar.bz2
raul-55603c281a49070bd941e79093cc20a144f9ee4a.zip
Rewrite Raul::Maid and eliminate Raul:List.
git-svn-id: http://svn.drobilla.net/lad/trunk/raul@4702 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'raul/Maid.hpp')
-rw-r--r--raul/Maid.hpp105
1 files changed, 74 insertions, 31 deletions
diff --git a/raul/Maid.hpp b/raul/Maid.hpp
index 157d519..f7870ec 100644
--- a/raul/Maid.hpp
+++ b/raul/Maid.hpp
@@ -17,57 +17,100 @@
#ifndef RAUL_MAID_HPP
#define RAUL_MAID_HPP
-#include "raul/Deletable.hpp"
-#include "raul/List.hpp"
+#include "raul/AtomicPtr.hpp"
+#include "raul/Disposable.hpp"
+#include "raul/Manageable.hpp"
#include "raul/Noncopyable.hpp"
-#include "raul/SRSWQueue.hpp"
#include "raul/SharedPtr.hpp"
namespace Raul {
-/** Explicitly driven garbage collector.
+/** Explicit quasi-garbage-collector.
*
- * This is used by realtime threads to allow hard realtime deletion of objects
- * (push() is realtime safe).
- *
- * You can also manage a SharedPtr, so cleanup() will delete it when all
- * references are dropped (except the one held by the Maid itself).
- * This allows using a SharedPtr freely in hard realtime threads without having
- * to worry about deletion accidentally occuring in the realtime thread.
- *
- * cleanup() should be called periodically to free memory, often enough to
- * prevent the queue from overflowing. This is probably best done by the main
- * thread to avoid the overhead of having a thread just to delete things.
+ * This allows objects to be disposed of in a real-time thread, but actually
+ * deleted later by another thread which calls cleanup().
*
* \ingroup raul
*/
-class Maid : Noncopyable
+class Maid : public Noncopyable
{
public:
- explicit Maid(size_t size);
- ~Maid();
+ Maid() {}
+
+ inline ~Maid() {
+ cleanup();
+ }
+
+ /** Dispose of an object when cleanup() is called next.
+ *
+ * This is thread safe, and real-time safe assuming reasonably low
+ * contention. If real-time threads need to push, do not call this very
+ * rapidly from many threads.
+ */
+ inline void dispose(Disposable* obj) {
+ if (obj) {
+ while (true) {
+ obj->_maid_next = _disposed.get();
+ if (_disposed.compare_and_exchange(obj->_maid_next, obj)) {
+ return;
+ }
+ }
+ }
+ }
- /** Push a raw pointer to be deleted when cleanup() is called next.
- * Realtime safe.
+ /** Manage an object held by a SharedPtr.
+ *
+ * This will hold a reference to @p ptr ensuring it will not be deleted
+ * except by cleanup(). This is mainly useful to allow dropping SharedPtr
+ * references in real-time threads without causing a deletion.
+ *
+ * This is not thread-safe.
+ *
+ * Note this mechanism scales linearly. If a very large number of objects
+ * are managed cleanup() will become very expensive.
*/
- inline void push(Raul::Deletable* obj) {
- if (obj)
- _objects.push(obj);
+ inline void manage(SharedPtr<Manageable> ptr) {
+ ptr->_maid_next = _managed;
+ _managed = ptr;
}
- void manage(SharedPtr<Raul::Deletable> ptr);
+ /** Free all dead and managed objects immediately.
+ *
+ * Obviously not real-time safe, but may be called while other threads are
+ * calling dispose().
+ */
+ inline void cleanup() {
+ // Atomically get the head of the disposed list
+ Disposable* disposed;
+ while (true) {
+ disposed = _disposed.get();
+ if (_disposed.compare_and_exchange(disposed, NULL)) {
+ break;
+ }
+ }
- void cleanup();
+ // Free the disposed list
+ for (Disposable* obj = _disposed.get(); obj;) {
+ Disposable* const next = obj->_maid_next;
+ delete obj;
+ obj = next;
+ }
-private:
- typedef Raul::SRSWQueue<Raul::Deletable*> Objects;
- typedef Raul::List<SharedPtr<Raul::Deletable> > Managed;
+ // Free the managed list
+ SharedPtr<Manageable> managed = _managed;
+ _managed.reset();
+ for (SharedPtr<Manageable> obj = managed; obj;) {
+ const SharedPtr<Manageable> next = obj->_maid_next;
+ obj->_maid_next.reset();
+ obj = next;
+ }
+ }
- Objects _objects;
- Managed _managed;
+private:
+ AtomicPtr<Disposable> _disposed;
+ SharedPtr<Manageable> _managed;
};
} // namespace Raul
#endif // RAUL_MAID_HPP
-