]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/RefCountedObj.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / common / RefCountedObj.h
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#ifndef CEPH_REFCOUNTEDOBJ_H
16#define CEPH_REFCOUNTEDOBJ_H
17
11fdf7f2 18#include "common/ceph_mutex.h"
7c673cae
FG
19#include "common/ceph_context.h"
20#include "common/valgrind.h"
11fdf7f2
TL
21#include "common/debug.h"
22
23#include <boost/smart_ptr/intrusive_ptr.hpp>
7c673cae 24
7c673cae 25// re-include our assert to clobber the system one; fix dout:
11fdf7f2 26#include "include/ceph_assert.h"
7c673cae
FG
27
28struct RefCountedObject {
29private:
31f18b77 30 mutable std::atomic<uint64_t> nref;
7c673cae
FG
31 CephContext *cct;
32public:
33 RefCountedObject(CephContext *c = NULL, int n=1) : nref(n), cct(c) {}
34 virtual ~RefCountedObject() {
11fdf7f2 35 ceph_assert(nref == 0);
7c673cae
FG
36 }
37
38 const RefCountedObject *get() const {
31f18b77 39 int v = ++nref;
7c673cae
FG
40 if (cct)
41 lsubdout(cct, refs, 1) << "RefCountedObject::get " << this << " "
42 << (v - 1) << " -> " << v
43 << dendl;
44 return this;
45 }
46 RefCountedObject *get() {
31f18b77 47 int v = ++nref;
7c673cae
FG
48 if (cct)
49 lsubdout(cct, refs, 1) << "RefCountedObject::get " << this << " "
50 << (v - 1) << " -> " << v
51 << dendl;
52 return this;
53 }
54 void put() const {
55 CephContext *local_cct = cct;
31f18b77 56 int v = --nref;
11fdf7f2
TL
57 if (local_cct)
58 lsubdout(local_cct, refs, 1) << "RefCountedObject::put " << this << " "
59 << (v + 1) << " -> " << v
60 << dendl;
7c673cae
FG
61 if (v == 0) {
62 ANNOTATE_HAPPENS_AFTER(&nref);
63 ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&nref);
64 delete this;
65 } else {
66 ANNOTATE_HAPPENS_BEFORE(&nref);
67 }
7c673cae
FG
68 }
69 void set_cct(CephContext *c) {
70 cct = c;
71 }
72
73 uint64_t get_nref() const {
31f18b77 74 return nref;
7c673cae
FG
75 }
76};
77
11fdf7f2
TL
78#ifndef WITH_SEASTAR
79
7c673cae
FG
80/**
81 * RefCountedCond
82 *
83 * a refcounted condition, will be removed when all references are dropped
84 */
85
86struct RefCountedCond : public RefCountedObject {
87 bool complete;
11fdf7f2
TL
88 ceph::mutex lock = ceph::make_mutex("RefCountedCond::lock");
89 ceph::condition_variable cond;
7c673cae
FG
90 int rval;
91
11fdf7f2 92 RefCountedCond() : complete(false), rval(0) {}
7c673cae
FG
93
94 int wait() {
11fdf7f2 95 std::unique_lock l(lock);
7c673cae 96 while (!complete) {
11fdf7f2 97 cond.wait(l);
7c673cae
FG
98 }
99 return rval;
100 }
101
102 void done(int r) {
11fdf7f2 103 std::lock_guard l(lock);
7c673cae
FG
104 rval = r;
105 complete = true;
11fdf7f2 106 cond.notify_all();
7c673cae
FG
107 }
108
109 void done() {
110 done(0);
111 }
112};
113
114/**
115 * RefCountedWaitObject
116 *
117 * refcounted object that allows waiting for the object's last reference.
118 * Any referrer can either put or put_wait(). A simple put() will return
119 * immediately, a put_wait() will return only when the object is destroyed.
120 * e.g., useful when we want to wait for a specific event completion. We
121 * use RefCountedCond, as the condition can be referenced after the object
122 * destruction.
123 *
124 */
125struct RefCountedWaitObject {
31f18b77 126 std::atomic<uint64_t> nref = { 1 };
7c673cae
FG
127 RefCountedCond *c;
128
31f18b77 129 RefCountedWaitObject() {
7c673cae
FG
130 c = new RefCountedCond;
131 }
132 virtual ~RefCountedWaitObject() {
133 c->put();
134 }
135
136 RefCountedWaitObject *get() {
31f18b77 137 nref++;
7c673cae
FG
138 return this;
139 }
140
141 bool put() {
142 bool ret = false;
143 RefCountedCond *cond = c;
144 cond->get();
31f18b77 145 if (--nref == 0) {
7c673cae
FG
146 cond->done();
147 delete this;
148 ret = true;
149 }
150 cond->put();
151 return ret;
152 }
153
154 void put_wait() {
155 RefCountedCond *cond = c;
156
157 cond->get();
31f18b77 158 if (--nref == 0) {
7c673cae
FG
159 cond->done();
160 delete this;
161 } else {
162 cond->wait();
163 }
164 cond->put();
165 }
166};
167
11fdf7f2
TL
168#endif // WITH_SEASTAR
169
170static inline void intrusive_ptr_add_ref(const RefCountedObject *p) {
171 p->get();
172}
173static inline void intrusive_ptr_release(const RefCountedObject *p) {
174 p->put();
175}
176
177using RefCountedPtr = boost::intrusive_ptr<RefCountedObject>;
7c673cae
FG
178
179#endif