X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fcommon%2FRefCountedObj.h;fp=src%2Fceph%2Fsrc%2Fcommon%2FRefCountedObj.h;h=9c0dad1d302f8574e1ec017622ce616b547f503a;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/common/RefCountedObj.h b/src/ceph/src/common/RefCountedObj.h new file mode 100644 index 0000000..9c0dad1 --- /dev/null +++ b/src/ceph/src/common/RefCountedObj.h @@ -0,0 +1,167 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_REFCOUNTEDOBJ_H +#define CEPH_REFCOUNTEDOBJ_H + +#include "common/Mutex.h" +#include "common/Cond.h" +#include "common/ceph_context.h" +#include "common/valgrind.h" + +// re-include our assert to clobber the system one; fix dout: +#include "include/assert.h" + +struct RefCountedObject { +private: + mutable std::atomic nref; + CephContext *cct; +public: + RefCountedObject(CephContext *c = NULL, int n=1) : nref(n), cct(c) {} + virtual ~RefCountedObject() { + assert(nref == 0); + } + + const RefCountedObject *get() const { + int v = ++nref; + if (cct) + lsubdout(cct, refs, 1) << "RefCountedObject::get " << this << " " + << (v - 1) << " -> " << v + << dendl; + return this; + } + RefCountedObject *get() { + int v = ++nref; + if (cct) + lsubdout(cct, refs, 1) << "RefCountedObject::get " << this << " " + << (v - 1) << " -> " << v + << dendl; + return this; + } + void put() const { + CephContext *local_cct = cct; + int v = --nref; + if (v == 0) { + ANNOTATE_HAPPENS_AFTER(&nref); + ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&nref); + delete this; + } else { + ANNOTATE_HAPPENS_BEFORE(&nref); + } + if (local_cct) + lsubdout(local_cct, refs, 1) << "RefCountedObject::put " << this << " " + << (v + 1) << " -> " << v + << dendl; + } + void set_cct(CephContext *c) { + cct = c; + } + + uint64_t get_nref() const { + return nref; + } +}; + +/** + * RefCountedCond + * + * a refcounted condition, will be removed when all references are dropped + */ + +struct RefCountedCond : public RefCountedObject { + bool complete; + Mutex lock; + Cond cond; + int rval; + + RefCountedCond() : complete(false), lock("RefCountedCond"), rval(0) {} + + int wait() { + Mutex::Locker l(lock); + while (!complete) { + cond.Wait(lock); + } + return rval; + } + + void done(int r) { + Mutex::Locker l(lock); + rval = r; + complete = true; + cond.SignalAll(); + } + + void done() { + done(0); + } +}; + +/** + * RefCountedWaitObject + * + * refcounted object that allows waiting for the object's last reference. + * Any referrer can either put or put_wait(). A simple put() will return + * immediately, a put_wait() will return only when the object is destroyed. + * e.g., useful when we want to wait for a specific event completion. We + * use RefCountedCond, as the condition can be referenced after the object + * destruction. + * + */ +struct RefCountedWaitObject { + std::atomic nref = { 1 }; + RefCountedCond *c; + + RefCountedWaitObject() { + c = new RefCountedCond; + } + virtual ~RefCountedWaitObject() { + c->put(); + } + + RefCountedWaitObject *get() { + nref++; + return this; + } + + bool put() { + bool ret = false; + RefCountedCond *cond = c; + cond->get(); + if (--nref == 0) { + cond->done(); + delete this; + ret = true; + } + cond->put(); + return ret; + } + + void put_wait() { + RefCountedCond *cond = c; + + cond->get(); + if (--nref == 0) { + cond->done(); + delete this; + } else { + cond->wait(); + } + cond->put(); + } +}; + +void intrusive_ptr_add_ref(const RefCountedObject *p); +void intrusive_ptr_release(const RefCountedObject *p); + +#endif