From: Yehuda Sadeh Date: Wed, 25 Apr 2012 22:12:56 +0000 (-0700) Subject: RefCountedObject: relocate from msg/Message.h to common/RefCountedObj.h X-Git-Tag: v0.47~102^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=39f9935416e22335c6a41692bf14d26563a898fc;p=ceph.git RefCountedObject: relocate from msg/Message.h to common/RefCountedObj.h Following a popular request. Signed-off-by: Yehuda Sadeh --- diff --git a/src/Makefile.am b/src/Makefile.am index bfbf5e648a3..4c584f15050 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1198,6 +1198,7 @@ noinst_HEADERS = \ cls_acl.cc\ cls_crypto.cc\ common/BackTrace.h\ + common/RefCountedObj.h\ common/HeartbeatMap.h\ common/LogClient.h\ common/LogEntry.h\ diff --git a/src/common/RefCountedObj.h b/src/common/RefCountedObj.h new file mode 100644 index 00000000000..bb556ddfb11 --- /dev/null +++ b/src/common/RefCountedObj.h @@ -0,0 +1,120 @@ +// -*- 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 "include/atomic.h" + + +struct RefCountedObject { + atomic_t nref; + RefCountedObject() : nref(1) {} + virtual ~RefCountedObject() {} + + RefCountedObject *get() { + //generic_dout(0) << "RefCountedObject::get " << this << " " << nref.read() << " -> " << (nref.read() + 1) << dendl; + nref.inc(); + return this; + } + void put() { + //generic_dout(0) << "RefCountedObject::put " << this << " " << nref.read() << " -> " << (nref.read() - 1) << dendl; + if (nref.dec() == 0) + delete this; + } +}; + +/** + * RefCountedCond + * + * a refcounted condition, will be removed when all references are dropped + */ + +struct RefCountedCond : public RefCountedObject { + Mutex lock; + Cond cond; + bool complete; + + RefCountedCond() : complete(false), lock("RefCountedCond") {} + + void wait() { + Mutex::Locker l(lock); + while (!complete) { + cond.Wait(lock); + } + } + + void done() { + Mutex::Locker l(lock); + complete = true; + cond.SignalAll(); + } +}; + +/** + * 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 { + atomic_t nref; + RefCountedCond *c; + + RefCountedWaitObject() : nref(1) { + c = new RefCountedCond; + } + virtual ~RefCountedWaitObject() { + c->put(); + } + + RefCountedWaitObject *get() { + nref.inc(); + return this; + } + + bool put() { + bool ret = false; + RefCountedCond *cond = c; + cond->get(); + if (nref.dec() == 0) { + cond->done(); + delete this; + ret = true; + } + cond->put(); + return ret; + } + + void put_wait() { + RefCountedCond *cond = c; + + cond->get(); + if (nref.dec() == 0) { + cond->done(); + delete this; + } else { + cond->wait(); + } + cond->put(); + } +}; + + +#endif diff --git a/src/msg/Message.h b/src/msg/Message.h index 865ea268b91..44cc0fea7a5 100644 --- a/src/msg/Message.h +++ b/src/msg/Message.h @@ -141,7 +141,8 @@ using std::list; #include "include/buffer.h" #include "common/Throttle.h" #include "msg_types.h" -#include "include/atomic.h" + +#include "common/RefCountedObj.h" #include "common/debug.h" @@ -151,85 +152,6 @@ using std::list; // abstract Connection, for keeping per-connection state -struct RefCountedObject { - atomic_t nref; - RefCountedObject() : nref(1) {} - virtual ~RefCountedObject() {} - - RefCountedObject *get() { - //generic_dout(0) << "RefCountedObject::get " << this << " " << nref.read() << " -> " << (nref.read() + 1) << dendl; - nref.inc(); - return this; - } - void put() { - //generic_dout(0) << "RefCountedObject::put " << this << " " << nref.read() << " -> " << (nref.read() - 1) << dendl; - if (nref.dec() == 0) - delete this; - } -}; - -struct RefCountedCond : public RefCountedObject { - Mutex lock; - Cond cond; - atomic_t complete; - - RefCountedCond() : lock("RefCountedCond") {} - - void wait() { - Mutex::Locker l(lock); - while (!complete.read()) - cond.Wait(lock); - } - - void done() { - Mutex::Locker l(lock); - cond.SignalAll(); - complete.set(1); - } -}; - -struct RefCountedWaitObject { - atomic_t nref; - RefCountedCond *c; - - RefCountedWaitObject() : nref(1) { - c = new RefCountedCond; - } - virtual ~RefCountedWaitObject() { - c->put(); - } - - RefCountedWaitObject *get() { - nref.inc(); - return this; - } - - bool put() { - bool ret = false; - RefCountedCond *cond = c; - cond->get(); - if (nref.dec() == 0) { - cond->done(); - delete this; - ret = true; - } - cond->put(); - return ret; - } - - void put_wait() { - RefCountedCond *cond = c; - - cond->get(); - if (nref.dec() == 0) { - cond->done(); - delete this; - } else { - cond->wait(); - } - cond->put(); - } -}; struct Connection : public RefCountedObject { Mutex lock;