remove td::this_thread::yield function. usleep_for(1) used instead

This commit is contained in:
Arseny Smirnov 2022-07-14 16:15:17 +04:00
parent b8bd39dc6f
commit 7ddc3099f6
11 changed files with 58 additions and 20 deletions

View File

@ -51,7 +51,7 @@ class Backoff {
if (cnt < 50) {
return true;
} else {
td::this_thread::yield();
td::usleep_for(1);
return cnt < 500;
}
}

View File

@ -194,7 +194,7 @@ Status NetQueryDispatcher::wait_dc_init(DcId dc_id, bool force) {
return Status::Error("Closing");
}
#if !TD_THREAD_UNSUPPORTED
td::this_thread::yield();
td::usleep_for(1);
#endif
}
}

View File

@ -7,6 +7,7 @@
#pragma once
#include "td/utils/common.h"
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h"
#include "td/utils/type_traits.h"
@ -20,6 +21,15 @@ template <class T>
class AtomicRead {
public:
void read(T &dest) const {
int it = 0;
const int wait_each_it = 4;
auto wait = [&]() {
it++;
if (it % wait_each_it == 0) {
usleep_for(1);
}
};
while (true) {
static_assert(TD_IS_TRIVIALLY_COPYABLE(T), "T must be trivially copyable");
auto version_before = version.load();
@ -30,7 +40,7 @@ class AtomicRead {
break;
}
}
td::this_thread::yield();
wait();
}
}

View File

@ -14,6 +14,7 @@
#include "td/utils/format.h"
#include "td/utils/HazardPointers.h"
#include "td/utils/logging.h"
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h"
#include "td/utils/ScopeGuard.h"
@ -305,7 +306,7 @@ class MpmcQueueOld {
if (try_pop(value, thread_id)) {
return value;
}
td::this_thread::yield();
td::usleep_for(1);
}
}
@ -429,7 +430,7 @@ class MpmcQueue {
if (try_pop(value, thread_id)) {
return value;
}
td::this_thread::yield();
td::usleep_for(1);
}
}

View File

@ -8,6 +8,7 @@
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h"
#include <algorithm>
@ -29,16 +30,17 @@ class MpmcEagerWaiter {
slot.yields = 0;
slot.worker_id = worker_id;
}
void wait(Slot &slot) {
if (slot.yields < RoundsTillSleepy) {
td::this_thread::yield();
yield();
slot.yields++;
} else if (slot.yields == RoundsTillSleepy) {
auto state = state_.load(std::memory_order_relaxed);
if (!State::has_worker(state)) {
auto new_state = State::with_worker(state, slot.worker_id);
if (state_.compare_exchange_strong(state, new_state, std::memory_order_acq_rel)) {
td::this_thread::yield();
yield();
slot.yields++;
return;
}
@ -47,12 +49,12 @@ class MpmcEagerWaiter {
return;
}
}
td::this_thread::yield();
yield();
slot.yields = 0;
} else if (slot.yields < RoundsTillAsleep) {
auto state = state_.load(std::memory_order_acquire);
if (State::still_sleepy(state, slot.worker_id)) {
td::this_thread::yield();
yield();
slot.yields++;
return;
}
@ -121,6 +123,10 @@ class MpmcEagerWaiter {
condition_variable_.notify_all();
}
}
static void yield() {
// whatever, this is better than sched_yield
usleep_for(1);
}
};
class MpmcSleepyWaiter {
@ -208,7 +214,7 @@ class MpmcSleepyWaiter {
}
if (slot.state_ == Slot::Search) {
if (slot.yield_cnt++ < 10 && false) {
td::this_thread::yield();
// TODO some sleep backoff is possible
return;
}

View File

@ -6,6 +6,7 @@
//
#pragma once
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h"
#include <atomic>
@ -30,7 +31,7 @@ class SpinLock {
//TODO pause
return true;
} else {
td::this_thread::yield();
usleep_for(1);
return true;
}
}

View File

@ -88,9 +88,6 @@ int ThreadPthread::do_pthread_create(pthread_t *thread, const pthread_attr_t *at
}
namespace this_thread_pthread {
void yield() {
sched_yield();
}
ThreadPthread::id get_id() {
return pthread_self();
}

View File

@ -83,7 +83,6 @@ class ThreadPthread {
};
namespace this_thread_pthread {
void yield();
ThreadPthread::id get_id();
} // namespace this_thread_pthread
} // namespace detail

View File

@ -70,7 +70,9 @@ class ThreadStl {
return std::forward<T>(v);
}
};
namespace this_thread_stl = std::this_thread;
namespace this_thread_stl {
using std::this_thread::get_id;
} // namespace this_thread_stl
} // namespace detail
} // namespace td

View File

@ -32,7 +32,7 @@ class Backoff {
if (cnt < 1) { // 50
return true;
} else {
td::this_thread::yield();
td::usleep_for(1);
return cnt < 3; // 500
}
}
@ -47,7 +47,7 @@ class InfBackoff {
if (cnt < 50) {
return true;
} else {
td::this_thread::yield();
td::usleep_for(1);
return true;
}
}

View File

@ -10,12 +10,14 @@
#include "td/utils/Context.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include <atomic>
#include <functional>
#include <mutex>
#include <utility>
namespace td {
@ -126,12 +128,12 @@ class RegisterTest {
}
};
class Stage {
class StageWait {
public:
void wait(uint64 need) {
value_.fetch_add(1, std::memory_order_release);
while (value_.load(std::memory_order_acquire) < need) {
td::this_thread::yield();
usleep_for(1);
}
};
@ -139,6 +141,26 @@ class Stage {
std::atomic<uint64> value_{0};
};
class StageMutex {
public:
void wait(uint64 need) {
std::unique_lock<std::mutex> lock{mutex_};
value_++;
if (value_ == need) {
cond_.notify_all();
return;
}
cond_.wait(lock, [&] { return value_ >= need; });
};
private:
std::mutex mutex_;
std::condition_variable cond_;
uint64 value_{0};
};
using Stage = StageMutex;
string rand_string(int from, int to, size_t len);
vector<string> rand_split(Slice str);