本文整理汇总了C++中stdx::unique_lock::mutex方法的典型用法代码示例。如果您正苦于以下问题:C++ unique_lock::mutex方法的具体用法?C++ unique_lock::mutex怎么用?C++ unique_lock::mutex使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类stdx::unique_lock
的用法示例。
在下文中一共展示了unique_lock::mutex方法的3个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: cvWaitUntilWithClockSource
static NOINLINE_DECL stdx::cv_status cvWaitUntilWithClockSource(ClockSource* clockSource,
stdx::condition_variable& cv,
stdx::unique_lock<stdx::mutex>& m,
Date_t deadline) {
if (deadline <= clockSource->now()) {
return stdx::cv_status::timeout;
}
struct AlarmInfo {
stdx::mutex controlMutex;
stdx::mutex* waitMutex;
stdx::condition_variable* waitCV;
stdx::cv_status cvWaitResult = stdx::cv_status::no_timeout;
};
auto alarmInfo = std::make_shared<AlarmInfo>();
alarmInfo->waitCV = &cv;
alarmInfo->waitMutex = m.mutex();
invariantOK(clockSource->setAlarm(deadline, [alarmInfo] {
stdx::lock_guard<stdx::mutex> controlLk(alarmInfo->controlMutex);
alarmInfo->cvWaitResult = stdx::cv_status::timeout;
if (!alarmInfo->waitMutex) {
return;
}
stdx::lock_guard<stdx::mutex> waitLk(*alarmInfo->waitMutex);
alarmInfo->waitCV->notify_all();
}));
cv.wait(m);
m.unlock();
stdx::lock_guard<stdx::mutex> controlLk(alarmInfo->controlMutex);
m.lock();
alarmInfo->waitMutex = nullptr;
alarmInfo->waitCV = nullptr;
return alarmInfo->cvWaitResult;
}
示例2: getServiceContext
// Theory of operation for waitForConditionOrInterruptNoAssertUntil and markKilled:
//
// An operation indicates to potential killers that it is waiting on a condition variable by setting
// _waitMutex and _waitCV, while holding the lock on its parent Client. It then unlocks its Client,
// unblocking any killers, which are required to have locked the Client before calling markKilled.
//
// When _waitMutex and _waitCV are set, killers must lock _waitMutex before setting the _killCode,
// and must signal _waitCV before releasing _waitMutex. Unfortunately, they must lock _waitMutex
// without holding a lock on Client to avoid a deadlock with callers of
// waitForConditionOrInterruptNoAssertUntil(). So, in the event that _waitMutex is set, the killer
// increments _numKillers, drops the Client lock, acquires _waitMutex and then re-acquires the
// Client lock. We know that the Client, its OperationContext and _waitMutex will remain valid
// during this period because the caller of waitForConditionOrInterruptNoAssertUntil will not return
// while _numKillers > 0 and will not return until it has itself reacquired _waitMutex. Instead,
// that caller will keep waiting on _waitCV until _numKillers drops to 0.
//
// In essence, when _waitMutex is set, _killCode is guarded by _waitMutex and _waitCV, but when
// _waitMutex is not set, it is guarded by the Client spinlock. Changing _waitMutex is itself
// guarded by the Client spinlock and _numKillers.
//
// When _numKillers does drop to 0, the waiter will null out _waitMutex and _waitCV.
//
// This implementation adds a minimum of two spinlock acquire-release pairs to every condition
// variable wait.
StatusWith<stdx::cv_status> OperationContext::waitForConditionOrInterruptNoAssertUntil(
stdx::condition_variable& cv, stdx::unique_lock<stdx::mutex>& m, Date_t deadline) noexcept {
invariant(getClient());
{
stdx::lock_guard<Client> clientLock(*getClient());
invariant(!_waitMutex);
invariant(!_waitCV);
invariant(0 == _numKillers);
// This interrupt check must be done while holding the client lock, so as not to race with a
// concurrent caller of markKilled.
auto status = checkForInterruptNoAssert();
if (!status.isOK()) {
return status;
}
_waitMutex = m.mutex();
_waitCV = &cv;
}
if (hasDeadline()) {
deadline = std::min(deadline, getDeadline());
}
const auto waitStatus = [&] {
if (Date_t::max() == deadline) {
cv.wait(m);
return stdx::cv_status::no_timeout;
}
return getServiceContext()->getPreciseClockSource()->waitForConditionUntil(cv, m, deadline);
}();
// Continue waiting on cv until no other thread is attempting to kill this one.
cv.wait(m, [this] {
stdx::lock_guard<Client> clientLock(*getClient());
if (0 == _numKillers) {
_waitMutex = nullptr;
_waitCV = nullptr;
return true;
}
return false;
});
auto status = checkForInterruptNoAssert();
if (!status.isOK()) {
return status;
}
if (hasDeadline() && waitStatus == stdx::cv_status::timeout && deadline == getDeadline()) {
// It's possible that the system clock used in stdx::condition_variable::wait_until
// is slightly ahead of the FastClock used in checkForInterrupt. In this case,
// we treat the operation as though it has exceeded its time limit, just as if the
// FastClock and system clock had agreed.
markKilled(ErrorCodes::ExceededTimeLimit);
return Status(ErrorCodes::ExceededTimeLimit, "operation exceeded time limit");
}
return waitStatus;
}
示例3: getServiceContext
// Theory of operation for waitForConditionOrInterruptNoAssertUntil and markKilled:
//
// An operation indicates to potential killers that it is waiting on a condition variable by setting
// _waitMutex and _waitCV, while holding the lock on its parent Client. It then unlocks its Client,
// unblocking any killers, which are required to have locked the Client before calling markKilled.
//
// When _waitMutex and _waitCV are set, killers must lock _waitMutex before setting the _killCode,
// and must signal _waitCV before releasing _waitMutex. Unfortunately, they must lock _waitMutex
// without holding a lock on Client to avoid a deadlock with callers of
// waitForConditionOrInterruptNoAssertUntil(). So, in the event that _waitMutex is set, the killer
// increments _numKillers, drops the Client lock, acquires _waitMutex and then re-acquires the
// Client lock. We know that the Client, its OperationContext and _waitMutex will remain valid
// during this period because the caller of waitForConditionOrInterruptNoAssertUntil will not return
// while _numKillers > 0 and will not return until it has itself reacquired _waitMutex. Instead,
// that caller will keep waiting on _waitCV until _numKillers drops to 0.
//
// In essence, when _waitMutex is set, _killCode is guarded by _waitMutex and _waitCV, but when
// _waitMutex is not set, it is guarded by the Client spinlock. Changing _waitMutex is itself
// guarded by the Client spinlock and _numKillers.
//
// When _numKillers does drop to 0, the waiter will null out _waitMutex and _waitCV.
//
// This implementation adds a minimum of two spinlock acquire-release pairs to every condition
// variable wait.
StatusWith<stdx::cv_status> OperationContext::waitForConditionOrInterruptNoAssertUntil(
stdx::condition_variable& cv, stdx::unique_lock<stdx::mutex>& m, Date_t deadline) noexcept {
invariant(getClient());
{
stdx::lock_guard<Client> clientLock(*getClient());
invariant(!_waitMutex);
invariant(!_waitCV);
invariant(0 == _numKillers);
// This interrupt check must be done while holding the client lock, so as not to race with a
// concurrent caller of markKilled.
auto status = checkForInterruptNoAssert();
if (!status.isOK()) {
return status;
}
_waitMutex = m.mutex();
_waitCV = &cv;
}
// If the maxTimeNeverTimeOut failpoint is set, behave as though the operation's deadline does
// not exist. Under normal circumstances, if the op has an existing deadline which is sooner
// than the deadline passed into this method, we replace our deadline with the op's. This means
// that we expect to time out at the same time as the existing deadline expires. If, when we
// time out, we find that the op's deadline has not expired (as will always be the case if
// maxTimeNeverTimeOut is set) then we assume that the incongruity is due to a clock mismatch
// and return _timeoutError regardless. To prevent this behaviour, only consider the op's
// deadline in the event that the maxTimeNeverTimeOut failpoint is not set.
bool opHasDeadline = (hasDeadline() && !MONGO_FAIL_POINT(maxTimeNeverTimeOut));
if (opHasDeadline) {
deadline = std::min(deadline, getDeadline());
}
const auto waitStatus = [&] {
if (Date_t::max() == deadline) {
Waitable::wait(_baton.get(), getServiceContext()->getPreciseClockSource(), cv, m);
return stdx::cv_status::no_timeout;
}
return getServiceContext()->getPreciseClockSource()->waitForConditionUntil(
cv, m, deadline, _baton.get());
}();
// Continue waiting on cv until no other thread is attempting to kill this one.
Waitable::wait(_baton.get(), getServiceContext()->getPreciseClockSource(), cv, m, [this] {
stdx::lock_guard<Client> clientLock(*getClient());
if (0 == _numKillers) {
_waitMutex = nullptr;
_waitCV = nullptr;
return true;
}
return false;
});
auto status = checkForInterruptNoAssert();
if (!status.isOK()) {
return status;
}
if (opHasDeadline && waitStatus == stdx::cv_status::timeout && deadline == getDeadline()) {
// It's possible that the system clock used in stdx::condition_variable::wait_until
// is slightly ahead of the FastClock used in checkForInterrupt. In this case,
// we treat the operation as though it has exceeded its time limit, just as if the
// FastClock and system clock had agreed.
if (!_hasArtificialDeadline) {
markKilled(_timeoutError);
}
return Status(_timeoutError, "operation exceeded time limit");
}
return waitStatus;
}