diff options
author | Billy Donahue <billy.donahue@mongodb.com> | 2022-07-14 15:44:28 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-07-14 17:18:10 +0000 |
commit | 4725f9b1fb48e95fd96284ccaa371d08f8cb8b41 (patch) | |
tree | 998471038cdc30b61923bf5b65edefbf4a8cbc24 /src | |
parent | 60e0fe845e805e7b23e73ea6e7170572a35806cf (diff) | |
download | mongo-4725f9b1fb48e95fd96284ccaa371d08f8cb8b41.tar.gz |
SERVER-67927 ServiceExecutor: ThreadingModel -> HasDedicatedThread
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/commands.cpp | 27 | ||||
-rw-r--r-- | src/mongo/db/commands.h | 11 | ||||
-rw-r--r-- | src/mongo/db/curop.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/service_entry_point_common.cpp | 12 | ||||
-rw-r--r-- | src/mongo/embedded/service_entry_point_embedded.cpp | 2 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_command_test_fixture.cpp | 2 | ||||
-rw-r--r-- | src/mongo/s/commands/strategy.cpp | 11 | ||||
-rw-r--r-- | src/mongo/transport/service_entry_point_impl.cpp | 2 | ||||
-rw-r--r-- | src/mongo/transport/service_executor.cpp | 165 | ||||
-rw-r--r-- | src/mongo/transport/service_executor.h | 29 | ||||
-rw-r--r-- | src/mongo/transport/service_executor.idl | 11 | ||||
-rw-r--r-- | src/mongo/transport/service_state_machine_test.cpp | 44 |
12 files changed, 103 insertions, 217 deletions
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index 6e8b2cee87d..3c8c915c023 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -155,22 +155,17 @@ BSONObj CommandHelpers::runCommandDirectly(OperationContext* opCtx, const OpMsgR return replyBuilder.releaseBody(); } -Future<void> CommandHelpers::runCommandInvocation( - std::shared_ptr<RequestExecutionContext> rec, - std::shared_ptr<CommandInvocation> invocation, - transport::ServiceExecutor::ThreadingModel threadingModel) { - switch (threadingModel) { - case transport::ServiceExecutor::ThreadingModel::kBorrowed: - return runCommandInvocationAsync(std::move(rec), std::move(invocation)); - case transport::ServiceExecutor::ThreadingModel::kDedicated: - return makeReadyFutureWith([opCtx = rec->getOpCtx(), - request = rec->getRequest(), - invocation = invocation.get(), - replyBuilder = rec->getReplyBuilder()] { - runCommandInvocation(opCtx, request, invocation, replyBuilder); - }); - } - MONGO_UNREACHABLE; +Future<void> CommandHelpers::runCommandInvocation(std::shared_ptr<RequestExecutionContext> rec, + std::shared_ptr<CommandInvocation> invocation, + bool useDedicatedThread) { + if (useDedicatedThread) + return makeReadyFutureWith([opCtx = rec->getOpCtx(), + request = rec->getRequest(), + invocation = invocation.get(), + replyBuilder = rec->getReplyBuilder()] { + runCommandInvocation(opCtx, request, invocation, replyBuilder); + }); + return runCommandInvocationAsync(std::move(rec), std::move(invocation)); } void CommandHelpers::runCommandInvocation(OperationContext* opCtx, diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index cbfb6f82451..778b34db424 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -259,13 +259,12 @@ struct CommandHelpers { static BSONObj runCommandDirectly(OperationContext* opCtx, const OpMsgRequest& request); /** - * Decides the command execution model (i.e., synchronous or asynchronous) based on the provided - * threading model. + * Runs the command synchronously in presence of a dedicated thread. + * Otherwise, runs the command asynchronously. */ - static Future<void> runCommandInvocation( - std::shared_ptr<RequestExecutionContext> rec, - std::shared_ptr<CommandInvocation> invocation, - transport::ServiceExecutor::ThreadingModel threadingModel); + static Future<void> runCommandInvocation(std::shared_ptr<RequestExecutionContext> rec, + std::shared_ptr<CommandInvocation> invocation, + bool useDedicatedThread); /** * Runs a previously parsed CommandInvocation and propagates the result to the diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp index 251f0e7fcf0..1b17d5080e1 100644 --- a/src/mongo/db/curop.cpp +++ b/src/mongo/db/curop.cpp @@ -218,9 +218,7 @@ void CurOp::reportCurrentOpForClient(OperationContext* opCtx, } if (const auto seCtx = transport::ServiceExecutorContext::get(client)) { - bool isDedicated = (seCtx->getThreadingModel() == - transport::ServiceExecutorContext::ThreadingModel::kDedicated); - infoBuilder->append("threaded"_sd, isDedicated); + infoBuilder->append("threaded"_sd, seCtx->useDedicatedThread()); } if (clientOpCtx) { diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp index e06ee01bfb1..1b76291285e 100644 --- a/src/mongo/db/service_entry_point_common.cpp +++ b/src/mongo/db/service_entry_point_common.cpp @@ -143,17 +143,18 @@ using namespace fmt::literals; Future<void> runCommandInvocation(std::shared_ptr<RequestExecutionContext> rec, std::shared_ptr<CommandInvocation> invocation) { - auto threadingModel = [client = rec->getOpCtx()->getClient()] { + auto useDedicatedThread = [&] { + auto client = rec->getOpCtx()->getClient(); if (auto context = transport::ServiceExecutorContext::get(client); context) { - return context->getThreadingModel(); + return context->useDedicatedThread(); } tassert(5453901, "Threading model may only be absent for internal and direct clients", !client->hasRemote() || client->isInDirectClient()); - return transport::ServiceExecutor::ThreadingModel::kDedicated; + return true; }(); return CommandHelpers::runCommandInvocation( - std::move(rec), std::move(invocation), threadingModel); + std::move(rec), std::move(invocation), useDedicatedThread); } /* @@ -2346,8 +2347,7 @@ Future<DbResponse> ServiceEntryPointCommon::handleRequest( invocation && !invocation->isSafeForBorrowedThreads()) { // If the last command wasn't safe for a borrowed thread, then let's move // off of it. - seCtx->setThreadingModel( - transport::ServiceExecutor::ThreadingModel::kDedicated); + seCtx->setUseDedicatedThread(true); } } diff --git a/src/mongo/embedded/service_entry_point_embedded.cpp b/src/mongo/embedded/service_entry_point_embedded.cpp index 4c2ca23c77b..c1f3ad842f1 100644 --- a/src/mongo/embedded/service_entry_point_embedded.cpp +++ b/src/mongo/embedded/service_entry_point_embedded.cpp @@ -54,7 +54,7 @@ namespace { class EmbeddedClientObserver final : public ServiceContext::ClientObserver { void onCreateClient(Client* client) { auto seCtx = std::make_unique<transport::ServiceExecutorContext>(); - seCtx->setThreadingModel(transport::ServiceExecutor::ThreadingModel::kDedicated); + seCtx->setUseDedicatedThread(true); transport::ServiceExecutorContext::set(client, std::move(seCtx)); } void onDestroyClient(Client*) {} diff --git a/src/mongo/s/commands/cluster_command_test_fixture.cpp b/src/mongo/s/commands/cluster_command_test_fixture.cpp index 3292f62a7ab..c31a6f61f23 100644 --- a/src/mongo/s/commands/cluster_command_test_fixture.cpp +++ b/src/mongo/s/commands/cluster_command_test_fixture.cpp @@ -125,7 +125,7 @@ DbResponse ClusterCommandTestFixture::runCommand(BSONObj cmd) { // execution of the command by the client thread. stdx::lock_guard lk(*client.get()); auto seCtx = std::make_unique<transport::ServiceExecutorContext>(); - seCtx->setThreadingModel(transport::ServiceExecutor::ThreadingModel::kDedicated); + seCtx->setUseDedicatedThread(true); transport::ServiceExecutorContext::set(client.get(), std::move(seCtx)); } diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp index 17a7a591807..bafb6b21fcf 100644 --- a/src/mongo/s/commands/strategy.cpp +++ b/src/mongo/s/commands/strategy.cpp @@ -116,17 +116,18 @@ MONGO_FAIL_POINT_DEFINE(allowSkippingAppendRequiredFieldsToResponse); Future<void> runCommandInvocation(std::shared_ptr<RequestExecutionContext> rec, std::shared_ptr<CommandInvocation> invocation) { - auto threadingModel = [client = rec->getOpCtx()->getClient()] { + bool useDedicatedThread = [&] { + auto client = rec->getOpCtx()->getClient(); if (auto context = transport::ServiceExecutorContext::get(client); context) { - return context->getThreadingModel(); + return context->useDedicatedThread(); } tassert(5453902, "Threading model may only be absent for internal and direct clients", !client->hasRemote() || client->isInDirectClient()); - return transport::ServiceExecutor::ThreadingModel::kDedicated; + return true; }(); return CommandHelpers::runCommandInvocation( - std::move(rec), std::move(invocation), threadingModel); + std::move(rec), std::move(invocation), useDedicatedThread); } /** @@ -355,7 +356,7 @@ void ExecCommandClient::_onCompletion() { if (!_invocation->isSafeForBorrowedThreads()) { // If the last command wasn't safe for a borrowed thread, then let's move // off of it. - seCtx->setThreadingModel(transport::ServiceExecutor::ThreadingModel::kDedicated); + seCtx->setUseDedicatedThread(true); } } diff --git a/src/mongo/transport/service_entry_point_impl.cpp b/src/mongo/transport/service_entry_point_impl.cpp index 524dc94a964..386f0e9f851 100644 --- a/src/mongo/transport/service_entry_point_impl.cpp +++ b/src/mongo/transport/service_entry_point_impl.cpp @@ -306,7 +306,7 @@ void ServiceEntryPointImpl::startSession(transport::SessionHandle session) { // Imbue the new Client with a ServiceExecutorContext. { auto seCtx = std::make_unique<transport::ServiceExecutorContext>(); - seCtx->setThreadingModel(transport::ServiceExecutor::getInitialThreadingModel()); + seCtx->setUseDedicatedThread(transport::gInitialUseDedicatedThread); seCtx->setCanUseReserved(isPrivilegedSession); stdx::lock_guard lk(*client); transport::ServiceExecutorContext::set(&*client, std::move(seCtx)); diff --git a/src/mongo/transport/service_executor.cpp b/src/mongo/transport/service_executor.cpp index b61c55ea250..747ea46e477 100644 --- a/src/mongo/transport/service_executor.cpp +++ b/src/mongo/transport/service_executor.cpp @@ -32,7 +32,10 @@ #include "mongo/transport/service_executor.h" +#include <algorithm> +#include <array> #include <boost/optional.hpp> +#include <utility> #include "mongo/logv2/log.h" #include "mongo/transport/service_entry_point.h" @@ -45,52 +48,22 @@ #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kNetwork -namespace mongo { -namespace transport { -namespace { -static constexpr auto kDiagnosticLogLevel = 4; +namespace mongo::transport { -static constexpr auto kThreadingModelDedicatedStr = "dedicated"_sd; -static constexpr auto kThreadingModelBorrowedStr = "borrowed"_sd; +bool gInitialUseDedicatedThread = true; -auto gInitialThreadingModel = ServiceExecutor::ThreadingModel::kDedicated; +namespace { +static constexpr auto kDiagnosticLogLevel = 4; auto getServiceExecutorStats = ServiceContext::declareDecoration<synchronized_value<ServiceExecutorStats>>(); auto getServiceExecutorContext = Client::declareDecoration<std::unique_ptr<ServiceExecutorContext>>(); -} // namespace - -StringData toString(ServiceExecutor::ThreadingModel threadingModel) { - switch (threadingModel) { - case ServiceExecutor::ThreadingModel::kDedicated: - return kThreadingModelDedicatedStr; - case ServiceExecutor::ThreadingModel::kBorrowed: - return kThreadingModelBorrowedStr; - default: - MONGO_UNREACHABLE; - } -} - -Status ServiceExecutor::setInitialThreadingModelFromString(StringData value) noexcept { - if (value == kThreadingModelDedicatedStr) { - setInitialThreadingModel(ServiceExecutor::ThreadingModel::kDedicated); - } else if (value == kThreadingModelBorrowedStr) { - setInitialThreadingModel(ServiceExecutor::ThreadingModel::kBorrowed); - } else { - MONGO_UNREACHABLE; - } - - return Status::OK(); -} - -void ServiceExecutor::setInitialThreadingModel(ThreadingModel threadingModel) noexcept { - gInitialThreadingModel = threadingModel; -} -auto ServiceExecutor::getInitialThreadingModel() noexcept -> ThreadingModel { - return gInitialThreadingModel; +void incrThreadingModelStats(ServiceExecutorStats& stats, bool useDedicatedThread, int step) { + (useDedicatedThread ? stats.usesDedicated : stats.usesBorrowed) += step; } +} // namespace ServiceExecutorStats ServiceExecutorStats::get(ServiceContext* ctx) noexcept { return getServiceExecutorStats(ctx).get(); @@ -111,97 +84,46 @@ void ServiceExecutorContext::set(Client* client, seCtx._sep = client->getServiceContext()->getServiceEntryPoint(); { - auto stats = getServiceExecutorStats(client->getServiceContext()).synchronize(); - if (seCtx._canUseReserved) { - ++stats->limitExempt; - } - - switch (seCtx._threadingModel) { - case ThreadingModel::kBorrowed: { - ++stats->usesBorrowed; - } break; - case ThreadingModel::kDedicated: { - ++stats->usesDedicated; - } break; - default: - MONGO_UNREACHABLE; - } + auto&& syncStats = *getServiceExecutorStats(client->getServiceContext()); + if (seCtx._canUseReserved) + ++syncStats->limitExempt; + incrThreadingModelStats(*syncStats, seCtx._useDedicatedThread, 1); } LOGV2_DEBUG(4898000, kDiagnosticLogLevel, "Setting initial ServiceExecutor context for client", "client"_attr = client->desc(), - "threadingModel"_attr = seCtx._threadingModel, + "useDedicatedThread"_attr = seCtx._useDedicatedThread, "canUseReserved"_attr = seCtx._canUseReserved); serviceExecutorContext = std::move(seCtxPtr); } void ServiceExecutorContext::reset(Client* client) noexcept { - if (client) { - auto& serviceExecutorContext = getServiceExecutorContext(client); - - auto stats = getServiceExecutorStats(client->getServiceContext()).synchronize(); - - LOGV2_DEBUG(4898001, - kDiagnosticLogLevel, - "Resetting ServiceExecutor context for client", - "client"_attr = client->desc(), - "threadingModel"_attr = serviceExecutorContext->_threadingModel, - "canUseReserved"_attr = serviceExecutorContext->_canUseReserved); - - if (serviceExecutorContext->_canUseReserved) { - --stats->limitExempt; - } - - switch (serviceExecutorContext->_threadingModel) { - case ThreadingModel::kBorrowed: { - --stats->usesBorrowed; - } break; - case ThreadingModel::kDedicated: { - --stats->usesDedicated; - } break; - default: - MONGO_UNREACHABLE; - } - } + if (!client) + return; + auto& seCtx = getServiceExecutorContext(client); + LOGV2_DEBUG(4898001, + kDiagnosticLogLevel, + "Resetting ServiceExecutor context for client", + "client"_attr = client->desc(), + "threadingModel"_attr = seCtx->_useDedicatedThread, + "canUseReserved"_attr = seCtx->_canUseReserved); + auto stats = *getServiceExecutorStats(client->getServiceContext()); + if (seCtx->_canUseReserved) + --stats->limitExempt; + incrThreadingModelStats(*stats, seCtx->_useDedicatedThread, -1); } -void ServiceExecutorContext::setThreadingModel(ThreadingModel threadingModel) noexcept { - - if (_threadingModel == threadingModel) { - // Nothing to do. +void ServiceExecutorContext::setUseDedicatedThread(bool b) noexcept { + if (b == _useDedicatedThread) return; - } - - auto lastThreadingModel = std::exchange(_threadingModel, threadingModel); - - if (_client) { - auto stats = getServiceExecutorStats(_client->getServiceContext()).synchronize(); - - // Decrement the stats for the previous ThreadingModel. - switch (lastThreadingModel) { - case ThreadingModel::kBorrowed: { - --stats->usesBorrowed; - } break; - case ThreadingModel::kDedicated: { - --stats->usesDedicated; - } break; - default: - MONGO_UNREACHABLE; - } - // Increment the stats for the next ThreadingModel. - switch (_threadingModel) { - case ThreadingModel::kBorrowed: { - ++stats->usesBorrowed; - } break; - case ThreadingModel::kDedicated: { - ++stats->usesDedicated; - } break; - default: - MONGO_UNREACHABLE; - } - } + auto prev = std::exchange(_useDedicatedThread, b); + if (!_client) + return; + auto stats = *getServiceExecutorStats(_client->getServiceContext()); + incrThreadingModelStats(*stats, prev, -1); + incrThreadingModelStats(*stats, _useDedicatedThread, +1); } void ServiceExecutorContext::setCanUseReserved(bool canUseReserved) noexcept { @@ -223,16 +145,8 @@ void ServiceExecutorContext::setCanUseReserved(bool canUseReserved) noexcept { ServiceExecutor* ServiceExecutorContext::getServiceExecutor() noexcept { invariant(_client); - - switch (_threadingModel) { - case ThreadingModel::kBorrowed: - return ServiceExecutorFixed::get(_client->getServiceContext()); - case ThreadingModel::kDedicated: { - // Continue on. - } break; - default: - MONGO_UNREACHABLE; - } + if (!_useDedicatedThread) + return ServiceExecutorFixed::get(_client->getServiceContext()); auto shouldUseReserved = [&] { // This is at best a naive solution. There could be a world where numOpenSessions() changes @@ -292,5 +206,4 @@ void ServiceExecutor::shutdownAll(ServiceContext* serviceContext, Date_t deadlin } } -} // namespace transport -} // namespace mongo +} // namespace mongo::transport diff --git a/src/mongo/transport/service_executor.h b/src/mongo/transport/service_executor.h index 56e43b4c404..458f152bd89 100644 --- a/src/mongo/transport/service_executor.h +++ b/src/mongo/transport/service_executor.h @@ -45,26 +45,13 @@ namespace mongo { namespace transport { +extern bool gInitialUseDedicatedThread; + /* * This is the interface for all ServiceExecutors. */ class ServiceExecutor : public OutOfLineExecutor { public: - /** - * An enum to indicate if a ServiceExecutor should use dedicated or borrowed threading - * resources. - */ - enum class ThreadingModel { - kBorrowed, - kDedicated, - }; - - friend StringData toString(ThreadingModel threadingModel); - - static Status setInitialThreadingModelFromString(StringData value) noexcept; - static void setInitialThreadingModel(ThreadingModel threadingModel) noexcept; - static ThreadingModel getInitialThreadingModel() noexcept; - static void shutdownAll(ServiceContext* serviceContext, Date_t deadline); virtual ~ServiceExecutor() = default; @@ -142,8 +129,6 @@ public: */ class ServiceExecutorContext { public: - using ThreadingModel = ServiceExecutor::ThreadingModel; - /** * Get a pointer to the ServiceExecutorContext for a given client. * @@ -173,11 +158,11 @@ public: ServiceExecutorContext& operator=(ServiceExecutorContext&&) = delete; /** - * Set the ThreadingModel for the associated Client's service execution. + * Set the threading model for the associated Client's service execution. * * This function is only valid to invoke with the Client lock or before the Client is set. */ - void setThreadingModel(ThreadingModel threadingModel) noexcept; + void setUseDedicatedThread(bool dedicated) noexcept; /** * Set if reserved resources are available for the associated Client's service execution. @@ -191,8 +176,8 @@ public: * * This function is valid to invoke either on the Client thread or with the Client lock. */ - auto getThreadingModel() const noexcept { - return _threadingModel; + bool useDedicatedThread() const noexcept { + return _useDedicatedThread; } /** @@ -207,7 +192,7 @@ private: Client* _client = nullptr; ServiceEntryPoint* _sep = nullptr; - ThreadingModel _threadingModel = ThreadingModel::kDedicated; + bool _useDedicatedThread = true; bool _canUseReserved = false; bool _hasUsedSynchronous = false; }; diff --git a/src/mongo/transport/service_executor.idl b/src/mongo/transport/service_executor.idl index 1758e45ee13..8471f2eebeb 100644 --- a/src/mongo/transport/service_executor.idl +++ b/src/mongo/transport/service_executor.idl @@ -32,14 +32,13 @@ global: - "mongo/transport/service_executor.h" server_parameters: - initialServiceExecutorThreadingModel: + initialServiceExecutorUseDedicatedThread: description: >- - Start new client connections using an executor that follows this model. + If true, each client will use a dedicated thread. set_at: [ startup ] - cpp_vartype: "std::string" - cpp_varname: "initialServiceExecutorThreadingModel" - on_update: "ServiceExecutor::setInitialThreadingModelFromString" - default: "dedicated" + cpp_vartype: bool + cpp_varname: gInitialServiceExecutorUseDedicatedThread + default: true synchronousServiceExecutorRecursionLimit: description: >- Tasks may recurse further if their recursion depth is less than this value. diff --git a/src/mongo/transport/service_state_machine_test.cpp b/src/mongo/transport/service_state_machine_test.cpp index 5d742ca81da..ad01830adec 100644 --- a/src/mongo/transport/service_state_machine_test.cpp +++ b/src/mongo/transport/service_state_machine_test.cpp @@ -65,6 +65,21 @@ namespace mongo { namespace transport { namespace { +/** Scope guard to set and restore an object value. */ +template <typename T> +class ScopedValueOverride { +public: + ScopedValueOverride(T& target, T v) + : _target{target}, _saved{std::exchange(_target, std::move(v))} {} + ~ScopedValueOverride() { + _target = std::move(_saved); + } + +private: + T& _target; + T _saved; +}; + // TODO(cr) Does this go into its own header? /** * The ServiceStateMachineTest is a fixture that mocks the external inputs into the @@ -151,9 +166,6 @@ public: return std::make_shared<ThreadPool>(std::move(options)); } - ServiceStateMachineTest(boost::optional<ServiceExecutor::ThreadingModel> threadingModel = {}) - : _threadingModel(std::move(threadingModel)) {} - void setUp() override; void tearDown() override; @@ -463,9 +475,6 @@ private: ++_onClientDisconnectCalled; } - const boost::optional<ServiceExecutor::ThreadingModel> _threadingModel; - boost::optional<ServiceExecutor::ThreadingModel> _originalThreadingModel; - ServiceStateMachineTest::ServiceEntryPoint* _sep; const std::shared_ptr<ThreadPool> _threadPool = makeThreadPool(); @@ -754,11 +763,6 @@ void ServiceStateMachineTest::terminateViaServiceEntryPoint() { void ServiceStateMachineTest::setUp() { ServiceContextTest::setUp(); - if (_threadingModel) { - _originalThreadingModel = ServiceExecutor::getInitialThreadingModel(); - ServiceExecutor::setInitialThreadingModel(*_threadingModel); - } - auto sep = std::make_unique<ServiceStateMachineTest::ServiceEntryPoint>(this); _sep = sep.get(); getServiceContext()->setServiceEntryPoint(std::move(sep)); @@ -779,23 +783,15 @@ void ServiceStateMachineTest::tearDown() { _threadPool->shutdown(); _threadPool->join(); - - if (_originalThreadingModel) { - ServiceExecutor::setInitialThreadingModel(*_originalThreadingModel); - } } -class ServiceStateMachineWithDedicatedThreadsTest : public ServiceStateMachineTest { -public: - ServiceStateMachineWithDedicatedThreadsTest() - : ServiceStateMachineTest(ServiceExecutor::ThreadingModel::kDedicated) {} +template <bool useDedicatedThread> +class DedicatedThreadOverrideTest : public ServiceStateMachineTest { + ScopedValueOverride<bool> _svo{gInitialUseDedicatedThread, useDedicatedThread}; }; -class ServiceStateMachineWithBorrowedThreadsTest : public ServiceStateMachineTest { -public: - ServiceStateMachineWithBorrowedThreadsTest() - : ServiceStateMachineTest(ServiceExecutor::ThreadingModel::kBorrowed) {} -}; +using ServiceStateMachineWithBorrowedThreadsTest = DedicatedThreadOverrideTest<false>; +using ServiceStateMachineWithDedicatedThreadsTest = DedicatedThreadOverrideTest<true>; TEST_F(ServiceStateMachineTest, StartThenEndSession) { initNewSession(); |