summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorJordi Olivares Provencio <jordi.olivares-provencio@mongodb.com>2022-05-18 10:07:43 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-05-18 12:27:07 +0000
commit25c66e358f9701b127b7b7f08a1246b424fd0067 (patch)
treedaceab5b2154f52b555854264a538700c1e464dc /src/mongo
parent6d7e4ea84316181578b9e78981f4adc1b0e9838d (diff)
downloadmongo-25c66e358f9701b127b7b7f08a1246b424fd0067.tar.gz
SERVER-66249 Refactor Tickets to be RAII and auto releasable
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp4
-rw-r--r--src/mongo/db/concurrency/lock_state.h2
-rw-r--r--src/mongo/dbtests/threadedtests.cpp1
-rw-r--r--src/mongo/util/concurrency/ticket.h90
-rw-r--r--src/mongo/util/concurrency/ticketholder.cpp42
-rw-r--r--src/mongo/util/concurrency/ticketholder.h93
-rw-r--r--src/mongo/util/concurrency/ticketholder_bm.cpp31
-rw-r--r--src/mongo/util/concurrency/ticketholder_test.cpp99
8 files changed, 135 insertions, 227 deletions
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp
index 0c050d528c7..681043076dd 100644
--- a/src/mongo/db/concurrency/lock_state.cpp
+++ b/src/mongo/db/concurrency/lock_state.cpp
@@ -1076,10 +1076,6 @@ void LockerImpl::releaseTicket() {
}
void LockerImpl::_releaseTicket() {
- auto holder = shouldAcquireTicket() ? _ticketHolders->getTicketHolder(_modeForTicket) : nullptr;
- if (holder) {
- holder->release(&_admCtx, std::move(*_ticket));
- }
_ticket.reset();
_clientState.store(kInactive);
}
diff --git a/src/mongo/db/concurrency/lock_state.h b/src/mongo/db/concurrency/lock_state.h
index a6677385e2f..af95dbe4d79 100644
--- a/src/mongo/db/concurrency/lock_state.h
+++ b/src/mongo/db/concurrency/lock_state.h
@@ -39,7 +39,7 @@
#include "mongo/platform/atomic_word.h"
#include "mongo/util/concurrency/admission_context.h"
#include "mongo/util/concurrency/spin_lock.h"
-#include "mongo/util/concurrency/ticket.h"
+#include "mongo/util/concurrency/ticketholder.h"
namespace mongo {
diff --git a/src/mongo/dbtests/threadedtests.cpp b/src/mongo/dbtests/threadedtests.cpp
index e5fe2ec48df..2d0449856ab 100644
--- a/src/mongo/dbtests/threadedtests.cpp
+++ b/src/mongo/dbtests/threadedtests.cpp
@@ -274,7 +274,6 @@ private:
AdmissionContext admCtx;
auto ticket = _tickets->waitForTicket(
opCtx.get(), &admCtx, TicketHolder::WaitMode::kUninterruptible);
- TicketHolderReleaser whenDone(std::move(ticket), &admCtx, _tickets.get());
_hotel.checkIn();
diff --git a/src/mongo/util/concurrency/ticket.h b/src/mongo/util/concurrency/ticket.h
deleted file mode 100644
index 3f10db3e6a1..00000000000
--- a/src/mongo/util/concurrency/ticket.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * Copyright (C) 2022-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program 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
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. 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 in the license file.
- */
-#pragma once
-
-#include <boost/optional.hpp>
-
-#include "mongo/util/assert_util_core.h"
-#include "mongo/util/tick_source.h"
-
-namespace mongo {
-
-class SemaphoreTicketHolder;
-class FifoTicketHolder;
-
-/**
- * Move-only token that gets generated when a ticket is acquired and has to be marked invalid when
- * it is released. Only TicketHolders can create and release valid Tickets.
- */
-class Ticket {
- friend class SemaphoreTicketHolder;
- friend class FifoTicketHolder;
-
-public:
- Ticket(Ticket&& t) : _valid(t._valid) {
- t._valid = false;
- }
-
- Ticket& operator=(Ticket&& t) {
- invariant(!_valid);
- _valid = t._valid;
- t._valid = false;
- return *this;
- };
-
- ~Ticket() {
- // A Ticket can't be destroyed unless it's been released.
- invariant(!_valid);
- }
-
- /**
- * Returns whether or not a ticket is held. The default constructor creates an invalid Ticket
- * and the move operators mark the source object as invalid.
- */
- bool valid() {
- return _valid;
- }
-
-private:
- Ticket() : _valid(true) {}
-
- void release() {
- invariant(_valid);
- _valid = false;
- }
-
- // No copy constructors.
- Ticket(const Ticket&) = delete;
- Ticket& operator=(const Ticket&) = delete;
-
- // Whether this represents a ticket being held.
- bool _valid;
-};
-
-} // namespace mongo
diff --git a/src/mongo/util/concurrency/ticketholder.cpp b/src/mongo/util/concurrency/ticketholder.cpp
index 392f7146c3a..82fe813b516 100644
--- a/src/mongo/util/concurrency/ticketholder.cpp
+++ b/src/mongo/util/concurrency/ticketholder.cpp
@@ -32,7 +32,6 @@
#include "mongo/db/service_context.h"
#include "mongo/util/concurrency/admission_context.h"
-#include "mongo/util/concurrency/ticket.h"
#include "mongo/util/concurrency/ticketholder.h"
#include <iostream>
@@ -93,7 +92,7 @@ boost::optional<Ticket> SemaphoreTicketHolder::tryAcquire(AdmissionContext* admC
if (errno != EINTR)
failWithErrno(errno);
}
- return Ticket{};
+ return Ticket{this, admCtx};
}
Ticket SemaphoreTicketHolder::waitForTicket(OperationContext* opCtx,
@@ -111,7 +110,7 @@ boost::optional<Ticket> SemaphoreTicketHolder::waitForTicketUntil(OperationConte
// Attempt to get a ticket without waiting in order to avoid expensive time calculations.
if (sem_trywait(&_sem) == 0) {
- return Ticket{};
+ return Ticket{this, admCtx};
}
const Milliseconds intervalMs(500);
@@ -141,12 +140,11 @@ boost::optional<Ticket> SemaphoreTicketHolder::waitForTicketUntil(OperationConte
if (waitMode == WaitMode::kInterruptible)
opCtx->checkForInterrupt();
}
- return Ticket{};
+ return Ticket{this, admCtx};
}
-void SemaphoreTicketHolder::release(AdmissionContext* admCtx, Ticket&& ticket) {
+void SemaphoreTicketHolder::_release(AdmissionContext* admCtx) noexcept {
check(sem_post(&_sem));
- ticket.release();
}
Status SemaphoreTicketHolder::resize(int newSize) {
@@ -163,14 +161,13 @@ Status SemaphoreTicketHolder::resize(int newSize) {
AdmissionContext admCtx;
while (_outof.load() < newSize) {
- Ticket ticket;
- release(&admCtx, std::move(ticket));
+ _release(&admCtx);
_outof.fetchAndAdd(1);
}
while (_outof.load() > newSize) {
auto ticket = waitForTicket(nullptr, &admCtx, WaitMode::kUninterruptible);
- ticket.release();
+ ticket.discard();
_outof.subtractAndFetch(1);
}
@@ -203,7 +200,7 @@ boost::optional<Ticket> SemaphoreTicketHolder::tryAcquire(AdmissionContext* admC
if (!_tryAcquire()) {
return boost::none;
}
- return Ticket{};
+ return Ticket{this, admCtx};
}
Ticket SemaphoreTicketHolder::waitForTicket(OperationContext* opCtx,
@@ -216,7 +213,7 @@ Ticket SemaphoreTicketHolder::waitForTicket(OperationContext* opCtx,
} else {
_newTicket.wait(lk, [this] { return _tryAcquire(); });
}
- return Ticket{};
+ return Ticket{this, admCtx};
}
@@ -238,16 +235,15 @@ boost::optional<Ticket> SemaphoreTicketHolder::waitForTicketUntil(OperationConte
if (!taken) {
return boost::none;
}
- return Ticket{};
+ return Ticket{this, admCtx};
}
-void SemaphoreTicketHolder::release(AdmissionContext* admCtx, Ticket&& ticket) {
+void SemaphoreTicketHolder::release(AdmissionContext* admCtx) {
{
stdx::lock_guard<Latch> lk(_mutex);
_num++;
}
_newTicket.notify_one();
- ticket.release();
}
Status SemaphoreTicketHolder::resize(int newSize) {
@@ -324,10 +320,9 @@ int FifoTicketHolder::queued() const {
return std::max(static_cast<int>(added - removed), 0);
}
-void FifoTicketHolder::release(AdmissionContext* admCtx, Ticket&& ticket) {
+void FifoTicketHolder::_release(AdmissionContext* admCtx) noexcept {
invariant(admCtx);
- ticket.release();
auto tickSource = _serviceContext->getTickSource();
// Update statistics.
@@ -382,7 +377,7 @@ boost::optional<Ticket> FifoTicketHolder::tryAcquire(AdmissionContext* admCtx) {
}
admCtx->start(_serviceContext->getTickSource());
_totalStartedProcessing.fetchAndAddRelaxed(1);
- return Ticket{};
+ return Ticket{this, admCtx};
}
Ticket FifoTicketHolder::waitForTicket(OperationContext* opCtx,
@@ -438,7 +433,7 @@ boost::optional<Ticket> FifoTicketHolder::waitForTicketUntil(OperationContext* o
if (remaining >= 0) {
_enqueuedElements.subtractAndFetch(1);
startProcessing();
- return Ticket{};
+ return Ticket{this, admCtx};
}
_ticketsAvailable.addAndFetch(1);
// We copy-construct the shared_ptr here as the waiting element needs to be alive in both
@@ -460,7 +455,7 @@ boost::optional<Ticket> FifoTicketHolder::waitForTicketUntil(OperationContext* o
// To cover the edge case of getting a ticket assigned before cancelling the ticket
// request. As we have been granted a ticket we must release it.
startProcessing();
- release(admCtx, Ticket{});
+ _release(admCtx);
}
});
@@ -487,7 +482,7 @@ boost::optional<Ticket> FifoTicketHolder::waitForTicketUntil(OperationContext* o
if (assigned) {
cancelWait.dismiss();
startProcessing();
- return Ticket{};
+ return Ticket{this, admCtx};
} else {
return boost::none;
}
@@ -502,15 +497,14 @@ Status FifoTicketHolder::resize(int newSize) {
AdmissionContext admCtx;
while (_capacity.load() < newSize) {
- Ticket ticket;
admCtx.start(_serviceContext->getTickSource());
- release(&admCtx, std::move(ticket));
+ _release(&admCtx);
_capacity.fetchAndAdd(1);
}
while (_capacity.load() > newSize) {
- Ticket ticket = waitForTicket(nullptr, &admCtx, WaitMode::kUninterruptible);
- ticket.release();
+ auto ticket = waitForTicket(nullptr, &admCtx, WaitMode::kUninterruptible);
+ ticket.discard();
_capacity.subtractAndFetch(1);
}
diff --git a/src/mongo/util/concurrency/ticketholder.h b/src/mongo/util/concurrency/ticketholder.h
index a03518f908b..3e8348a80ac 100644
--- a/src/mongo/util/concurrency/ticketholder.h
+++ b/src/mongo/util/concurrency/ticketholder.h
@@ -41,13 +41,16 @@
#include "mongo/stdx/future.h"
#include "mongo/util/concurrency/admission_context.h"
#include "mongo/util/concurrency/mutex.h"
-#include "mongo/util/concurrency/ticket.h"
#include "mongo/util/hierarchical_acquisition.h"
#include "mongo/util/time_support.h"
namespace mongo {
+class Ticket;
+
class TicketHolder {
+ friend class Ticket;
+
public:
/**
* Wait mode for ticket acquisition: interruptible or uninterruptible.
@@ -80,7 +83,6 @@ public:
AdmissionContext* admCtx,
Date_t until,
WaitMode waitMode) = 0;
- virtual void release(AdmissionContext* admCtx, Ticket&& ticket) = 0;
virtual Status resize(int newSize) = 0;
@@ -91,6 +93,9 @@ public:
virtual int outof() const = 0;
virtual void appendStats(BSONObjBuilder& b) const = 0;
+
+private:
+ virtual void _release(AdmissionContext* admCtx) noexcept = 0;
};
class SemaphoreTicketHolder final : public TicketHolder {
@@ -109,7 +114,6 @@ public:
Date_t until,
WaitMode waitMode) override final;
- void release(AdmissionContext* admCtx, Ticket&& ticket) override final;
Status resize(int newSize) override final;
@@ -122,6 +126,8 @@ public:
void appendStats(BSONObjBuilder& b) const override final;
private:
+ void _release(AdmissionContext* admCtx) noexcept override final;
+
#if defined(__linux__)
mutable sem_t _sem;
@@ -161,7 +167,6 @@ public:
Date_t until,
WaitMode waitMode) override final;
- void release(AdmissionContext* admCtx, Ticket&& ticket) override final;
Status resize(int newSize) override final;
@@ -176,6 +181,8 @@ public:
void appendStats(BSONObjBuilder& b) const override final;
private:
+ void _release(AdmissionContext* admCtx) noexcept override final;
+
void _release(WithLock);
Mutex _resizeMutex =
@@ -207,50 +214,60 @@ private:
ServiceContext* _serviceContext;
};
-class ScopedTicket {
-public:
- ScopedTicket(OperationContext* opCtx, TicketHolder* holder, TicketHolder::WaitMode waitMode)
- : _holder(holder), _ticket(_holder->waitForTicket(opCtx, &_admCtx, waitMode)) {}
-
- ~ScopedTicket() {
- _holder->release(&_admCtx, std::move(_ticket));
- }
-
-private:
- AdmissionContext _admCtx;
- TicketHolder* _holder;
- Ticket _ticket;
-};
-
-class TicketHolderReleaser {
- TicketHolderReleaser(const TicketHolderReleaser&) = delete;
- TicketHolderReleaser& operator=(const TicketHolderReleaser&) = delete;
+/**
+ * RAII-style movable token that gets generated when a ticket is acquired and is automatically
+ * released when going out of scope.
+ */
+class Ticket {
+ friend class SemaphoreTicketHolder;
+ friend class FifoTicketHolder;
public:
- explicit TicketHolderReleaser(Ticket&& ticket, AdmissionContext* admCtx, TicketHolder* holder)
- : _holder(holder), _ticket(std::move(ticket)), _admCtx(admCtx) {}
+ Ticket(Ticket&& t) : _ticketholder(t._ticketholder), _admissionContext(t._admissionContext) {
+ t._ticketholder = nullptr;
+ t._admissionContext = nullptr;
+ }
+ Ticket& operator=(Ticket&& t) {
+ invariant(!valid(), "Attempting to overwrite a valid ticket with another one");
+ _ticketholder = t._ticketholder;
+ _admissionContext = t._admissionContext;
+ t._ticketholder = nullptr;
+ t._admissionContext = nullptr;
+ return *this;
+ };
- ~TicketHolderReleaser() {
- if (_holder) {
- _holder->release(_admCtx, std::move(_ticket));
+ ~Ticket() {
+ if (_ticketholder) {
+ _ticketholder->_release(_admissionContext);
}
}
- bool hasTicket() const {
- return _holder != nullptr;
+ /**
+ * Returns whether or not a ticket is being held.
+ */
+ bool valid() {
+ return _ticketholder != nullptr;
}
- void reset(TicketHolder* holder = nullptr) {
- if (_holder) {
- _holder->release(_admCtx, std::move(_ticket));
- }
- _holder = holder;
+private:
+ Ticket(TicketHolder* ticketHolder, AdmissionContext* admissionContext)
+ : _ticketholder(ticketHolder), _admissionContext(admissionContext) {}
+
+ /**
+ * Discards the ticket without releasing it back to the ticketholder.
+ */
+ void discard() {
+ _ticketholder = nullptr;
+ _admissionContext = nullptr;
}
-private:
- TicketHolder* _holder;
- Ticket _ticket;
- AdmissionContext* _admCtx;
+ // No copy constructors.
+ Ticket(const Ticket&) = delete;
+ Ticket& operator=(const Ticket&) = delete;
+
+ TicketHolder* _ticketholder;
+ AdmissionContext* _admissionContext;
};
+
} // namespace mongo
diff --git a/src/mongo/util/concurrency/ticketholder_bm.cpp b/src/mongo/util/concurrency/ticketholder_bm.cpp
index be4c3034d44..0e26465aff4 100644
--- a/src/mongo/util/concurrency/ticketholder_bm.cpp
+++ b/src/mongo/util/concurrency/ticketholder_bm.cpp
@@ -83,8 +83,8 @@ void BM_tryAcquire(benchmark::State& state) {
attempted++;
if (ticket) {
acquired++;
- p->ticketHolder->release(&admCtx, std::move(*ticket));
}
+ ticket.reset();
state.ResumeTiming();
}
state.counters["Attempted"] = attempted;
@@ -105,10 +105,11 @@ void BM_acquire(benchmark::State& state) {
for (auto _ : state) {
AdmissionContext admCtx;
auto opCtx = p->opCtxs[state.thread_index].get();
- auto ticket = p->ticketHolder->waitForTicket(opCtx, &admCtx, waitMode);
- state.PauseTiming();
- sleepmicros(1);
- p->ticketHolder->release(&admCtx, std::move(ticket));
+ {
+ auto ticket = p->ticketHolder->waitForTicket(opCtx, &admCtx, waitMode);
+ state.PauseTiming();
+ sleepmicros(1);
+ }
acquired++;
state.ResumeTiming();
}
@@ -132,10 +133,11 @@ void BM_release(benchmark::State& state) {
AdmissionContext admCtx;
auto opCtx = p->opCtxs[state.thread_index].get();
state.PauseTiming();
- auto ticket = p->ticketHolder->waitForTicket(opCtx, &admCtx, waitMode);
- sleepmicros(1);
- state.ResumeTiming();
- p->ticketHolder->release(&admCtx, std::move(ticket));
+ {
+ auto ticket = p->ticketHolder->waitForTicket(opCtx, &admCtx, waitMode);
+ sleepmicros(1);
+ state.ResumeTiming();
+ }
acquired++;
}
state.counters["Acquired"] = benchmark::Counter(acquired, benchmark::Counter::kIsRate);
@@ -158,11 +160,12 @@ void BM_acquireAndRelease(benchmark::State& state) {
for (auto _ : state) {
AdmissionContext admCtx;
auto opCtx = p->opCtxs[state.thread_index].get();
- auto ticket = p->ticketHolder->waitForTicket(opCtx, &admCtx, waitMode);
- state.PauseTiming();
- sleepmicros(1);
- state.ResumeTiming();
- p->ticketHolder->release(&admCtx, std::move(ticket));
+ {
+ auto ticket = p->ticketHolder->waitForTicket(opCtx, &admCtx, waitMode);
+ state.PauseTiming();
+ sleepmicros(1);
+ state.ResumeTiming();
+ }
acquired++;
}
state.counters["Acquired"] = benchmark::Counter(acquired, benchmark::Counter::kIsRate);
diff --git a/src/mongo/util/concurrency/ticketholder_test.cpp b/src/mongo/util/concurrency/ticketholder_test.cpp
index 7a7db89c656..64077c87819 100644
--- a/src/mongo/util/concurrency/ticketholder_test.cpp
+++ b/src/mongo/util/concurrency/ticketholder_test.cpp
@@ -71,7 +71,7 @@ void basicTimeout(OperationContext* opCtx) {
AdmissionContext admCtx;
{
- ScopedTicket ticket(opCtx, holder.get(), mode);
+ auto ticket = holder->waitForTicket(opCtx, &admCtx, mode);
ASSERT_EQ(holder->used(), 1);
ASSERT_EQ(holder->available(), 0);
ASSERT_EQ(holder->outof(), 1);
@@ -88,48 +88,48 @@ void basicTimeout(OperationContext* opCtx) {
ASSERT_EQ(holder->available(), 1);
ASSERT_EQ(holder->outof(), 1);
- auto ticket = holder->waitForTicketUntil(opCtx, &admCtx, Date_t::now(), mode);
- ASSERT(ticket);
- holder->release(&admCtx, std::move(*ticket));
+ {
+ auto ticket = holder->waitForTicketUntil(opCtx, &admCtx, Date_t::now(), mode);
+ ASSERT(ticket);
+ }
ASSERT_EQ(holder->used(), 0);
- ticket = holder->waitForTicketUntil(opCtx, &admCtx, Date_t::now() + Milliseconds(20), mode);
- ASSERT(ticket);
- ASSERT_EQ(holder->used(), 1);
+ {
+ auto ticket =
+ holder->waitForTicketUntil(opCtx, &admCtx, Date_t::now() + Milliseconds(20), mode);
+ ASSERT(ticket);
+ ASSERT_EQ(holder->used(), 1);
+ ASSERT_FALSE(
+ holder->waitForTicketUntil(opCtx, &admCtx, Date_t::now() + Milliseconds(2), mode));
+ }
- ASSERT_FALSE(holder->waitForTicketUntil(opCtx, &admCtx, Date_t::now() + Milliseconds(2), mode));
- holder->release(&admCtx, std::move(*ticket));
ASSERT_EQ(holder->used(), 0);
//
// Test resize
//
ASSERT(holder->resize(6).isOK());
- ticket = holder->waitForTicket(opCtx, &admCtx, mode);
- ASSERT(ticket);
- ASSERT_EQ(holder->used(), 1);
- ASSERT_EQ(holder->outof(), 6);
-
std::array<boost::optional<Ticket>, 5> tickets;
- for (int i = 0; i < 5; ++i) {
- tickets[i] = holder->waitForTicket(opCtx, &admCtx, mode);
- ASSERT_EQ(holder->used(), 2 + i);
+ {
+ auto ticket = holder->waitForTicket(opCtx, &admCtx, mode);
+ ASSERT_EQ(holder->used(), 1);
ASSERT_EQ(holder->outof(), 6);
- }
- ASSERT_FALSE(holder->waitForTicketUntil(opCtx, &admCtx, Date_t::now() + Milliseconds(1), mode));
+ for (int i = 0; i < 5; ++i) {
+ tickets[i] = holder->waitForTicket(opCtx, &admCtx, mode);
+ ASSERT_EQ(holder->used(), 2 + i);
+ ASSERT_EQ(holder->outof(), 6);
+ }
- holder->release(&admCtx, std::move(*ticket));
+ ASSERT_FALSE(
+ holder->waitForTicketUntil(opCtx, &admCtx, Date_t::now() + Milliseconds(1), mode));
+ }
ASSERT(holder->resize(5).isOK());
ASSERT_EQ(holder->used(), 5);
ASSERT_EQ(holder->outof(), 5);
ASSERT_FALSE(holder->waitForTicketUntil(opCtx, &admCtx, Date_t::now() + Milliseconds(1), mode));
-
- for (int i = 0; i < 5; ++i) {
- holder->release(&admCtx, std::move(*tickets[i]));
- }
}
TEST_F(TicketHolderTest, BasicTimeoutFifo) {
@@ -162,7 +162,7 @@ TEST_F(TicketHolderTest, FifoBasicMetrics) {
Stats stats(&holder);
AdmissionContext admCtx;
- auto ticket =
+ boost::optional<Ticket> ticket =
holder.waitForTicket(_opCtx.get(), &admCtx, TicketHolder::WaitMode::kInterruptible);
unittest::Barrier barrier(2);
@@ -174,7 +174,6 @@ TEST_F(TicketHolderTest, FifoBasicMetrics) {
auto ticket =
holder.waitForTicket(opCtx.get(), &admCtx, TicketHolder::WaitMode::kInterruptible);
barrier.countDownAndWait();
- holder.release(&admCtx, std::move(ticket));
});
while (holder.queued() == 0) {
@@ -187,7 +186,7 @@ TEST_F(TicketHolderTest, FifoBasicMetrics) {
ASSERT_EQ(stats["queueLength"], 1);
tickSource->advance(Microseconds(100));
- holder.release(&admCtx, std::move(ticket));
+ ticket.reset();
while (holder.queued() > 0) {
// Wait for thread to take ticket.
@@ -213,8 +212,7 @@ TEST_F(TicketHolderTest, FifoBasicMetrics) {
ASSERT_EQ(stats["newAdmissions"], 2);
// Retake ticket.
- ticket = holder.waitForTicket(_opCtx.get(), &admCtx, TicketHolder::WaitMode::kInterruptible);
- holder.release(&admCtx, std::move(ticket));
+ holder.waitForTicket(_opCtx.get(), &admCtx, TicketHolder::WaitMode::kInterruptible);
ASSERT_EQ(admCtx.getAdmissions(), 2);
ASSERT_EQ(stats["newAdmissions"], 2);
@@ -228,26 +226,27 @@ TEST_F(TicketHolderTest, FifoCanceled) {
Stats stats(&holder);
AdmissionContext admCtx;
- auto ticket =
- holder.waitForTicket(_opCtx.get(), &admCtx, TicketHolder::WaitMode::kInterruptible);
+ {
+ auto ticket =
+ holder.waitForTicket(_opCtx.get(), &admCtx, TicketHolder::WaitMode::kInterruptible);
- stdx::thread waiting([this, &holder]() {
- auto client = this->getServiceContext()->makeClient("waiting");
- auto opCtx = client->makeOperationContext();
+ stdx::thread waiting([this, &holder]() {
+ auto client = this->getServiceContext()->makeClient("waiting");
+ auto opCtx = client->makeOperationContext();
- AdmissionContext admCtx;
- auto deadline = Date_t::now() + Milliseconds(100);
- ASSERT_FALSE(holder.waitForTicketUntil(
- opCtx.get(), &admCtx, deadline, TicketHolder::WaitMode::kInterruptible));
- });
+ AdmissionContext admCtx;
+ auto deadline = Date_t::now() + Milliseconds(100);
+ ASSERT_FALSE(holder.waitForTicketUntil(
+ opCtx.get(), &admCtx, deadline, TicketHolder::WaitMode::kInterruptible));
+ });
- while (holder.queued() == 0) {
- // Wait for thread to take ticket.
- }
+ while (holder.queued() == 0) {
+ // Wait for thread to take ticket.
+ }
- tickSource->advance(Microseconds(100));
- waiting.join();
- holder.release(&admCtx, std::move(ticket));
+ tickSource->advance(Microseconds(100));
+ waiting.join();
+ }
ASSERT_EQ(stats["addedToQueue"], 1);
ASSERT_EQ(stats["removedFromQueue"], 1);
@@ -260,14 +259,4 @@ TEST_F(TicketHolderTest, FifoCanceled) {
ASSERT_EQ(stats["canceled"], 1);
}
-DEATH_TEST_F(TicketHolderTest, UnreleasedTicket, "invariant") {
- ServiceContext serviceContext;
- serviceContext.setTickSource(std::make_unique<TickSourceMock<Microseconds>>());
- FifoTicketHolder holder(1, &serviceContext);
- Stats stats(&holder);
- AdmissionContext admCtx;
-
- auto ticket =
- holder.waitForTicket(_opCtx.get(), &admCtx, TicketHolder::WaitMode::kInterruptible);
-}
} // namespace