Files
oceanbase/src/storage/ob_safe_ref.h
wangzelin.wzl 93a1074b0c patch 4.0
2022-10-24 17:57:12 +08:00

129 lines
2.8 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef OCEANBASE_MEMTABLE_OB_SAFE_REF_H_
#define OCEANBASE_MEMTABLE_OB_SAFE_REF_H_
#include "lib/objectpool/ob_concurrency_objpool.h"
#include "lib/queue/ob_link_queue.h"
namespace oceanbase
{
namespace storage
{
struct SafeRef: public common::ObLink
{
SafeRef(): ref_(0), seq_(0), ptr_(NULL) {}
~SafeRef() {}
void xref(int64_t x) { ATOMIC_AAF(&ref_, x); }
int64_t ref() { return ATOMIC_LOAD(&ref_); }
int64_t seq() { return ATOMIC_LOAD(&seq_); }
void inc_seq() { ATOMIC_AAF(&seq_, 1); }
int64_t ref_;
int64_t seq_;
void* ptr_;
};
struct SafeRef2
{
SafeRef2(): sref_(NULL), seq_(0) {}
~SafeRef2() {}
SafeRef* sref_;
int64_t seq_;
};
class SafeRefAlloc
{
public:
typedef common::ObLinkQueue FreeList;
SafeRef* alloc() {
int ret = common::OB_SUCCESS;
SafeRef* p = NULL;
while(NULL == p) {
if (OB_FAIL(free_list_.pop((common::ObLink*&)p))) {
p = OB_NEW(SafeRef, "SafeRef");
}
if (NULL == p) {
ob_usleep(10 * 1000);
}
}
return p;
}
void free(SafeRef* p) {
(void)free_list_.push(p);
}
private:
FreeList free_list_;
};
class ObSafeRefKeeper
{
public:
typedef SafeRefAlloc Alloc;
ObSafeRefKeeper() {}
~ObSafeRefKeeper() {}
void reg(SafeRef2& ref, void* ptr) {
SafeRef* p = alloc_.alloc();
p->ptr_ = ptr;
ref.sref_ = p;
ref.seq_ = p->seq_;
}
void unreg(SafeRef2& ref) {
SafeRef* p = (SafeRef*)ref.sref_;
if (NULL != p) {
p->inc_seq();
ATOMIC_STORE(&ref.sref_, NULL);
while(p->ref() > 0) {
PAUSE();
}
ATOMIC_STORE(&p->ptr_, NULL);
alloc_.free(p);
}
}
void* lock(SafeRef2& ref) {
void* ret = NULL;
SafeRef* p = (SafeRef*)ref.sref_;
if (NULL != p) {
p->xref(1);
ret = p->ptr_;
if (NULL == ret) {
// unexpected
p->xref(-1);
} else if (p->seq() != ref.seq_) {
p->xref(-1);
ret = NULL;
}
}
return ret;
}
void unlock(SafeRef2& ref) {
SafeRef* p = (SafeRef*)ref.sref_;
if (NULL != p) {
p->xref(-1);
}
}
private:
Alloc alloc_;
};
inline ObSafeRefKeeper& get_safe_ref_keeper()
{
static ObSafeRefKeeper ref_keeper;
return ref_keeper;
}
#define REF_KEEPER get_safe_ref_keeper()
}; // end namespace memtable
}; // end namespace oceanbase
#endif /* OCEANBASE_MEMTABLE_OB_SAFE_REF_H_ */