mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated submodules, bugfixes
- added new fift/func code for validator complaint creation - bugfixes in validator - updates in tonlib - new versions of rocksdb/abseil - hardfork support
This commit is contained in:
parent
16a4566091
commit
9f008b129f
129 changed files with 8438 additions and 879 deletions
90
tdutils/td/utils/AtomicRead.h
Normal file
90
tdutils/td/utils/AtomicRead.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
This file is part of TON Blockchain source code.
|
||||
|
||||
TON Blockchain is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
TON Blockchain is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
You must obey the GNU General Public License in all respects for all
|
||||
of the code used other than OpenSSL. If you modify file(s) with this
|
||||
exception, you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. If you delete this exception statement
|
||||
from all source files in the program, then also delete it here.
|
||||
|
||||
Copyright 2019-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include <atomic>
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/port/thread.h"
|
||||
namespace td {
|
||||
template <class T>
|
||||
|
||||
class AtomicRead {
|
||||
public:
|
||||
void read(T &dest) const {
|
||||
while (true) {
|
||||
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
|
||||
auto version_before = version.load();
|
||||
memcpy(&dest, &value, sizeof(dest));
|
||||
auto version_after = version.load();
|
||||
if (version_before == version_after && version_before % 2 == 0) {
|
||||
break;
|
||||
}
|
||||
td::this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
friend struct Write;
|
||||
struct Write {
|
||||
explicit Write(AtomicRead *read) {
|
||||
read->do_lock();
|
||||
ptr.reset(read);
|
||||
}
|
||||
struct Destructor {
|
||||
void operator()(AtomicRead *read) const {
|
||||
read->do_unlock();
|
||||
}
|
||||
};
|
||||
T &operator*() {
|
||||
return value();
|
||||
}
|
||||
T *operator->() {
|
||||
return &value();
|
||||
}
|
||||
T &value() {
|
||||
CHECK(ptr);
|
||||
return ptr->value;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<AtomicRead, Destructor> ptr;
|
||||
};
|
||||
Write lock() {
|
||||
return Write(this);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<td::uint64> version{0};
|
||||
T value;
|
||||
|
||||
void do_lock() {
|
||||
CHECK(++version % 2 == 1);
|
||||
}
|
||||
void do_unlock() {
|
||||
CHECK(++version % 2 == 0);
|
||||
}
|
||||
};
|
||||
}; // namespace td
|
|
@ -57,6 +57,15 @@
|
|||
} \
|
||||
}
|
||||
|
||||
#define TRY_STATUS_PROMISE_PREFIX(promise_name, status, prefix) \
|
||||
{ \
|
||||
auto try_status = (status); \
|
||||
if (try_status.is_error()) { \
|
||||
promise_name.set_error(try_status.move_as_error_prefix(prefix)); \
|
||||
return; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define TRY_RESULT(name, result) TRY_RESULT_IMPL(TD_CONCAT(TD_CONCAT(r_, name), __LINE__), auto name, result)
|
||||
|
||||
#define TRY_RESULT_PROMISE(promise_name, name, result) \
|
||||
|
@ -437,6 +446,7 @@ class Status {
|
|||
template <class T = Unit>
|
||||
class Result {
|
||||
public:
|
||||
using ValueT = T;
|
||||
Result() : status_(Status::Error<-1>()) {
|
||||
}
|
||||
template <class S, std::enable_if_t<!std::is_same<std::decay_t<S>, Result>::value, int> = 0>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "td/utils/tests.h"
|
||||
#include "td/utils/benchmark.h"
|
||||
|
||||
#include "td/utils/AtomicRead.h"
|
||||
#include "td/utils/StealingQueue.h"
|
||||
#include "td/utils/MpmcQueue.h"
|
||||
|
||||
|
@ -79,6 +80,46 @@ TEST(AtomicRead, simple) {
|
|||
thread.join();
|
||||
}
|
||||
}
|
||||
TEST(AtomicRead, simple2) {
|
||||
td::Stage run;
|
||||
td::Stage check;
|
||||
|
||||
size_t threads_n = 10;
|
||||
std::vector<td::thread> threads;
|
||||
|
||||
struct Value {
|
||||
td::uint64 value = 0;
|
||||
char str[50] = "0 0 0 0";
|
||||
};
|
||||
AtomicRead<Value> value;
|
||||
|
||||
auto to_str = [](size_t i) { return PSTRING() << i << " " << i << " " << i << " " << i; };
|
||||
for (size_t i = 0; i < threads_n; i++) {
|
||||
threads.push_back(td::thread([&, id = static_cast<uint32>(i)] {
|
||||
for (uint64 round = 1; round < 10000; round++) {
|
||||
if (id == 0) {
|
||||
}
|
||||
run.wait(round * threads_n);
|
||||
if (id == 0) {
|
||||
auto x = value.lock();
|
||||
x->value = round;
|
||||
auto str = to_str(round);
|
||||
memcpy(x->str, str.c_str(), str.size() + 1);
|
||||
} else {
|
||||
Value x;
|
||||
value.read(x);
|
||||
LOG_CHECK(x.value == round || x.value == round - 1) << x.value << " " << round;
|
||||
CHECK(x.str == to_str(x.value));
|
||||
}
|
||||
check.wait(round * threads_n);
|
||||
}
|
||||
}));
|
||||
}
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(StealingQueue, simple) {
|
||||
uint64 sum;
|
||||
std::atomic<uint64> got_sum;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue