15ad09de9SLang Hames //===--- ThreadSafeModuleTest.cpp - Test basic use of ThreadSafeModule ----===//
25ad09de9SLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ad09de9SLang Hames //
75ad09de9SLang Hames //===----------------------------------------------------------------------===//
85ad09de9SLang Hames
95ad09de9SLang Hames #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
105ad09de9SLang Hames #include "gtest/gtest.h"
115ad09de9SLang Hames
125ad09de9SLang Hames #include <atomic>
135ad09de9SLang Hames #include <future>
145ad09de9SLang Hames #include <thread>
155ad09de9SLang Hames
165ad09de9SLang Hames using namespace llvm;
175ad09de9SLang Hames using namespace llvm::orc;
185ad09de9SLang Hames
195ad09de9SLang Hames namespace {
205ad09de9SLang Hames
TEST(ThreadSafeModuleTest,ContextWhollyOwnedByOneModule)215ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextWhollyOwnedByOneModule) {
225ad09de9SLang Hames // Test that ownership of a context can be transferred to a single
235ad09de9SLang Hames // ThreadSafeModule.
240eaee545SJonas Devlieghere ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
250eaee545SJonas Devlieghere auto M = std::make_unique<Module>("M", *TSCtx.getContext());
26f1c96490SLang Hames ThreadSafeModule TSM(std::move(M), std::move(TSCtx));
275ad09de9SLang Hames }
285ad09de9SLang Hames
TEST(ThreadSafeModuleTest,ContextOwnershipSharedByTwoModules)295ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextOwnershipSharedByTwoModules) {
305ad09de9SLang Hames // Test that ownership of a context can be shared between more than one
315ad09de9SLang Hames // ThreadSafeModule.
320eaee545SJonas Devlieghere ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
335ad09de9SLang Hames
340eaee545SJonas Devlieghere auto M1 = std::make_unique<Module>("M1", *TSCtx.getContext());
35f1c96490SLang Hames ThreadSafeModule TSM1(std::move(M1), TSCtx);
36f1c96490SLang Hames
370eaee545SJonas Devlieghere auto M2 = std::make_unique<Module>("M2", *TSCtx.getContext());
38f1c96490SLang Hames ThreadSafeModule TSM2(std::move(M2), std::move(TSCtx));
395ad09de9SLang Hames }
405ad09de9SLang Hames
TEST(ThreadSafeModuleTest,ContextOwnershipSharedWithClient)415ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextOwnershipSharedWithClient) {
425ad09de9SLang Hames // Test that ownership of a context can be shared with a client-held
435ad09de9SLang Hames // ThreadSafeContext so that it can be re-used for new modules.
440eaee545SJonas Devlieghere ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
455ad09de9SLang Hames
465ad09de9SLang Hames {
475ad09de9SLang Hames // Create and destroy a module.
480eaee545SJonas Devlieghere auto M1 = std::make_unique<Module>("M1", *TSCtx.getContext());
49f1c96490SLang Hames ThreadSafeModule TSM1(std::move(M1), TSCtx);
505ad09de9SLang Hames }
515ad09de9SLang Hames
525ad09de9SLang Hames // Verify that the context is still available for re-use.
530eaee545SJonas Devlieghere auto M2 = std::make_unique<Module>("M2", *TSCtx.getContext());
54f1c96490SLang Hames ThreadSafeModule TSM2(std::move(M2), std::move(TSCtx));
555ad09de9SLang Hames }
565ad09de9SLang Hames
TEST(ThreadSafeModuleTest,ThreadSafeModuleMoveAssignment)575ad09de9SLang Hames TEST(ThreadSafeModuleTest, ThreadSafeModuleMoveAssignment) {
585ad09de9SLang Hames // Move assignment needs to move the module before the context (opposite
595ad09de9SLang Hames // to the field order) to ensure that overwriting with an empty
605ad09de9SLang Hames // ThreadSafeModule does not destroy the context early.
610eaee545SJonas Devlieghere ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
620eaee545SJonas Devlieghere auto M = std::make_unique<Module>("M", *TSCtx.getContext());
63f1c96490SLang Hames ThreadSafeModule TSM(std::move(M), std::move(TSCtx));
645ad09de9SLang Hames TSM = ThreadSafeModule();
655ad09de9SLang Hames }
665ad09de9SLang Hames
TEST(ThreadSafeModuleTest,BasicContextLockAPI)675ad09de9SLang Hames TEST(ThreadSafeModuleTest, BasicContextLockAPI) {
685ad09de9SLang Hames // Test that basic lock API calls work.
690eaee545SJonas Devlieghere ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
700eaee545SJonas Devlieghere auto M = std::make_unique<Module>("M", *TSCtx.getContext());
71f1c96490SLang Hames ThreadSafeModule TSM(std::move(M), TSCtx);
725ad09de9SLang Hames
735ad09de9SLang Hames { auto L = TSCtx.getLock(); }
745ad09de9SLang Hames
75809e9d1eSLang Hames { auto L = TSM.getContext().getLock(); }
765ad09de9SLang Hames }
775ad09de9SLang Hames
TEST(ThreadSafeModuleTest,ContextLockPreservesContext)785ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextLockPreservesContext) {
795ad09de9SLang Hames // Test that the existence of a context lock preserves the attached
805ad09de9SLang Hames // context.
815ad09de9SLang Hames // The trick to verify this is a bit of a hack: We attach a Module
825ad09de9SLang Hames // (without the ThreadSafeModule wrapper) to the context, then verify
835ad09de9SLang Hames // that this Module destructs safely (which it will not if its context
845ad09de9SLang Hames // has been destroyed) even though all references to the context have
855ad09de9SLang Hames // been thrown away (apart from the lock).
865ad09de9SLang Hames
870eaee545SJonas Devlieghere ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
885ad09de9SLang Hames auto L = TSCtx.getLock();
895ad09de9SLang Hames auto &Ctx = *TSCtx.getContext();
900eaee545SJonas Devlieghere auto M = std::make_unique<Module>("M", Ctx);
915ad09de9SLang Hames TSCtx = ThreadSafeContext();
925ad09de9SLang Hames }
935ad09de9SLang Hames
TEST(ThreadSafeModuleTest,WithModuleDo)940bf85d7dSLang Hames TEST(ThreadSafeModuleTest, WithModuleDo) {
950bf85d7dSLang Hames // Test non-const version of withModuleDo.
960bf85d7dSLang Hames ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
970bf85d7dSLang Hames ThreadSafeModule TSM(std::make_unique<Module>("M", *TSCtx.getContext()),
980bf85d7dSLang Hames TSCtx);
990bf85d7dSLang Hames TSM.withModuleDo([](Module &M) {});
1000bf85d7dSLang Hames }
1010bf85d7dSLang Hames
TEST(ThreadSafeModuleTest,WithModuleDoConst)1020bf85d7dSLang Hames TEST(ThreadSafeModuleTest, WithModuleDoConst) {
1030bf85d7dSLang Hames // Test const version of withModuleDo.
1040bf85d7dSLang Hames ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
1050bf85d7dSLang Hames const ThreadSafeModule TSM(std::make_unique<Module>("M", *TSCtx.getContext()),
1060bf85d7dSLang Hames TSCtx);
1070bf85d7dSLang Hames TSM.withModuleDo([](const Module &M) {});
1080bf85d7dSLang Hames }
1090bf85d7dSLang Hames
TEST(ThreadSafeModuleTest,ConsumingModuleDo)110*ae331245SLang Hames TEST(ThreadSafeModuleTest, ConsumingModuleDo) {
111*ae331245SLang Hames // Test consumingModuleDo.
1120bf85d7dSLang Hames ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
1130bf85d7dSLang Hames ThreadSafeModule TSM(std::make_unique<Module>("M", *TSCtx.getContext()),
1140bf85d7dSLang Hames TSCtx);
115*ae331245SLang Hames TSM.consumingModuleDo([](std::unique_ptr<Module> M) {});
1160bf85d7dSLang Hames }
1170bf85d7dSLang Hames
1185ad09de9SLang Hames } // end anonymous namespace
119