--- /dev/null
+/* Automatic refcounter pointer class
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef POINTER_H
+#define POINTER_H
+
+#include <fmt/core.h>
+
+namespace rxrpc {
+
+template <class T> class ref;
+
+/*
+ * Refcounting base class, for use in objects pointed to by class ref<>.
+ */
+struct refcount {
+ template<class T> friend class ref;
+protected:
+ int usage;
+
+ virtual void get() { usage++; }
+ virtual void put() { if (--usage == 0) { delete this; } }
+public:
+ refcount() { usage = 0; }
+ virtual ~refcount() = 0;
+ inline int get_refcount() const { return usage; }
+};
+
+/*
+ * Typed pointer class. Holds a reference on an object of type T that's a
+ * subclass of the refcount class.
+ */
+template <class T>
+class ref {
+private:
+ T *ptr;
+ void set(T *p) { ptr = p; if (p) ptr->refcount::get(); }
+ void clear() { if (ptr) ptr->refcount::put(); }
+ void assign(T *p) { clear(); set(p); }
+
+ inline void set_cast(refcount *c)
+ {
+ if (c) {
+ T *t = dynamic_cast<T *>(c);
+ if (!t)
+ throw std::logic_error("Type mismatch");
+ set(t);
+ } else {
+ set(NULL);
+ }
+ }
+public:
+ inline void assign_cast(refcount *c)
+ {
+ clear();
+ set_cast(c);
+ }
+ inline T *get_ptr() const { return ptr; }
+
+ ~ref() { clear(); }
+ ref() : ptr(NULL) { }
+ ref(T *p) { set(p); }
+ ref(const ref<T> &p) { set(p.ptr); }
+ template <class Q> ref(ref<Q> &p) { Q *q = p.get_ptr(); set(q); }
+ template <class Q> ref(const ref<Q> &p) { Q *q = p.get_ptr(); set(q); }
+
+ void operator=(T *p) { assign(p); }
+ void operator=(const ref<T> &p) { assign(p.ptr); }
+ template <class Q> void operator=(const ref<Q> &p) { assign(p); }
+ template <class Q> void operator=(Q *p) { assign(p); }
+
+ T &operator*() { return *(T *)ptr; }
+ const T &operator*() const { return *(T *)ptr; }
+ T *operator->() { return (T *)ptr; }
+ const T *operator->() const { return (T *)ptr; }
+ operator T *() { return ptr; }
+ operator const T *() const { return ptr; }
+ operator unsigned long() const { return (unsigned long)ptr; }
+ operator bool() const { return ptr; }
+ bool operator!() const { return !ptr; }
+
+ //template <class Q> operator ref<Q> *() { return dynamic_cast<Q *>(ptr); }
+ //template <class Q> operator Q *() { return dynamic_cast<Q *>(ptr); }
+ template <class Q> Q *cast() { return dynamic_cast<Q *>(ptr); }
+};
+
+} /* end namespace rxrpc */
+
+#endif /* POINTER_H */