This repository has been archived on 2020-05-25. You can view files and clone it, but cannot push or open issues or pull requests.
tdlib-fork/tdutils/td/utils/SpinLock.h
levlam eaebfad034 Update copyright year.
GitOrigin-RevId: 359e2b43322222922c44c430d3814b0a4c778dc6
2019-01-01 01:02:34 +03:00

60 lines
1.1 KiB
C++

//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2019
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/port/thread.h"
#include <atomic>
#include <memory>
namespace td {
class SpinLock {
struct Unlock {
void operator()(SpinLock *ptr) {
ptr->unlock();
}
};
class InfBackoff {
int cnt = 0;
public:
bool next() {
cnt++;
if (cnt < 50) {
return true;
} else {
td::this_thread::yield();
return true;
}
}
};
public:
using Lock = std::unique_ptr<SpinLock, Unlock>;
Lock lock() {
InfBackoff backoff;
while (!try_lock()) {
backoff.next();
}
return Lock(this);
}
bool try_lock() {
return !flag_.test_and_set(std::memory_order_acquire);
}
private:
std::atomic_flag flag_ = ATOMIC_FLAG_INIT;
void unlock() {
flag_.clear(std::memory_order_release);
}
};
} // namespace td