onnxruntime/include/onnxruntime/core/platform/Barrier.h
Changming Sun 88676e62b9
Remove nsync (#20413)
### Description
1. Remove the onnxruntime::OrtMutex class and replace it with
~absl::Mutex~ std::mutex.
2. After this change, most source files will not include <Windows.h>
indirectly.


### Motivation and Context
To reduce the number of deps we have, and address some Github issues
that are related to build ONNX Runtime from source.
In PR #3000 , I added a custom implementation of std::mutex . It was
mainly because at that time std::mutex's default constructor was not
trivial on Windows. If you had such a mutex as a global var, it could
not be initialized at compile time. Then VC++ team fixed this issue.
Therefore we don't need this custom implementation anymore.

This PR also removes nsync. I ran several models tests on Linux. I
didn't see any perf difference.
This PR also reverts PR #21005 , which is no longer needed since conda
has updated its msvc runtime DLL.

This PR unblocks #22173 and resolves #22092 . We have a lot of open
issues with nsync. This PR can resolve all of them.
2024-10-21 15:32:14 -07:00

81 lines
2.2 KiB
C++

// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2016 Dmitry Vyukov <dvyukov@google.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <assert.h>
#include "core/common/spin_pause.h"
#include <mutex>
#include <condition_variable>
#include <atomic>
namespace onnxruntime {
class Barrier {
public:
explicit Barrier(unsigned int count, bool spin = false)
: state_(count << 1), notified_(false), spin_(spin) {
assert(((count << 1) >> 1) == count);
}
#ifdef NDEBUG
~Barrier() = default;
#else
~Barrier() {
assert((state_ >> 1) == 0);
}
#endif
void Notify(unsigned int c = 1) {
unsigned int delta = c << 1;
unsigned int v = state_.fetch_sub(delta, std::memory_order_acq_rel) - delta;
if (v != 1) {
// Clear the lowest bit (waiter flag) and check that the original state
// value was not zero. If it was zero, it means that notify was called
// more times than the original count.
assert(((v + delta) & ~1) != 0);
return; // either count has not dropped to 0, or waiter is not waiting
}
std::unique_lock<std::mutex> l(mu_);
assert(!notified_);
notified_ = true;
cv_.notify_all();
}
void Wait() {
if (spin_) {
while ((state_ >> 1) != 0) {
onnxruntime::concurrency::SpinPause();
}
} else {
unsigned int v = state_.fetch_or(1, std::memory_order_acq_rel);
if ((v >> 1) == 0)
return;
std::unique_lock<std::mutex> l(mu_);
while (!notified_) {
cv_.wait(l);
}
}
}
private:
std::mutex mu_;
std::condition_variable cv_;
std::atomic<unsigned int> state_; // low bit is waiter flag
bool notified_;
const bool spin_;
};
// Notification is an object that allows a user to to wait for another
// thread to signal a notification that an event has occurred.
//
// Multiple threads can wait on the same Notification object,
// but only one caller must call Notify() on the object.
struct Notification : Barrier {
Notification() : Barrier(1) {};
};
} // namespace onnxruntime