129 lines
2.8 KiB
C++
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_ */
|
|
|