15ad09de9SLang Hames //===--- ThreadSafeModuleTest.cpp - Test basic use of ThreadSafeModule ----===// 25ad09de9SLang Hames // 35ad09de9SLang Hames // The LLVM Compiler Infrastructure 45ad09de9SLang Hames // 55ad09de9SLang Hames // This file is distributed under the University of Illinois Open Source 65ad09de9SLang Hames // License. See LICENSE.TXT for details. 75ad09de9SLang Hames // 85ad09de9SLang Hames //===----------------------------------------------------------------------===// 95ad09de9SLang Hames 105ad09de9SLang Hames #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" 115ad09de9SLang Hames #include "gtest/gtest.h" 125ad09de9SLang Hames 135ad09de9SLang Hames #include <atomic> 145ad09de9SLang Hames #include <future> 155ad09de9SLang Hames #include <thread> 165ad09de9SLang Hames 175ad09de9SLang Hames using namespace llvm; 185ad09de9SLang Hames using namespace llvm::orc; 195ad09de9SLang Hames 205ad09de9SLang Hames namespace { 215ad09de9SLang Hames 225ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextWhollyOwnedByOneModule) { 235ad09de9SLang Hames // Test that ownership of a context can be transferred to a single 245ad09de9SLang Hames // ThreadSafeModule. 255ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 26*f1c96490SLang Hames auto M = llvm::make_unique<Module>("M", *TSCtx.getContext()); 27*f1c96490SLang Hames ThreadSafeModule TSM(std::move(M), std::move(TSCtx)); 285ad09de9SLang Hames } 295ad09de9SLang Hames 305ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextOwnershipSharedByTwoModules) { 315ad09de9SLang Hames // Test that ownership of a context can be shared between more than one 325ad09de9SLang Hames // ThreadSafeModule. 335ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 345ad09de9SLang Hames 35*f1c96490SLang Hames auto M1 =llvm::make_unique<Module>("M1", *TSCtx.getContext()); 36*f1c96490SLang Hames ThreadSafeModule TSM1(std::move(M1), TSCtx); 37*f1c96490SLang Hames 38*f1c96490SLang Hames auto M2 =llvm::make_unique<Module>("M2", *TSCtx.getContext()); 39*f1c96490SLang Hames ThreadSafeModule TSM2(std::move(M2), std::move(TSCtx)); 405ad09de9SLang Hames } 415ad09de9SLang Hames 425ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextOwnershipSharedWithClient) { 435ad09de9SLang Hames // Test that ownership of a context can be shared with a client-held 445ad09de9SLang Hames // ThreadSafeContext so that it can be re-used for new modules. 455ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 465ad09de9SLang Hames 475ad09de9SLang Hames { 485ad09de9SLang Hames // Create and destroy a module. 49*f1c96490SLang Hames auto M1 = llvm::make_unique<Module>("M1", *TSCtx.getContext()); 50*f1c96490SLang Hames ThreadSafeModule TSM1(std::move(M1), TSCtx); 515ad09de9SLang Hames } 525ad09de9SLang Hames 535ad09de9SLang Hames // Verify that the context is still available for re-use. 54*f1c96490SLang Hames auto M2 = llvm::make_unique<Module>("M2", *TSCtx.getContext()); 55*f1c96490SLang Hames ThreadSafeModule TSM2(std::move(M2), std::move(TSCtx)); 565ad09de9SLang Hames } 575ad09de9SLang Hames 585ad09de9SLang Hames TEST(ThreadSafeModuleTest, ThreadSafeModuleMoveAssignment) { 595ad09de9SLang Hames // Move assignment needs to move the module before the context (opposite 605ad09de9SLang Hames // to the field order) to ensure that overwriting with an empty 615ad09de9SLang Hames // ThreadSafeModule does not destroy the context early. 625ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 63*f1c96490SLang Hames auto M = llvm::make_unique<Module>("M", *TSCtx.getContext()); 64*f1c96490SLang Hames ThreadSafeModule TSM(std::move(M), std::move(TSCtx)); 655ad09de9SLang Hames TSM = ThreadSafeModule(); 665ad09de9SLang Hames } 675ad09de9SLang Hames 685ad09de9SLang Hames TEST(ThreadSafeModuleTest, BasicContextLockAPI) { 695ad09de9SLang Hames // Test that basic lock API calls work. 705ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 71*f1c96490SLang Hames auto M =llvm::make_unique<Module>("M", *TSCtx.getContext()); 72*f1c96490SLang Hames ThreadSafeModule TSM(std::move(M), TSCtx); 735ad09de9SLang Hames 745ad09de9SLang Hames { auto L = TSCtx.getLock(); } 755ad09de9SLang Hames 765ad09de9SLang Hames { auto L = TSM.getContextLock(); } 775ad09de9SLang Hames } 785ad09de9SLang Hames 795ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextLockPreservesContext) { 805ad09de9SLang Hames // Test that the existence of a context lock preserves the attached 815ad09de9SLang Hames // context. 825ad09de9SLang Hames // The trick to verify this is a bit of a hack: We attach a Module 835ad09de9SLang Hames // (without the ThreadSafeModule wrapper) to the context, then verify 845ad09de9SLang Hames // that this Module destructs safely (which it will not if its context 855ad09de9SLang Hames // has been destroyed) even though all references to the context have 865ad09de9SLang Hames // been thrown away (apart from the lock). 875ad09de9SLang Hames 885ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 895ad09de9SLang Hames auto L = TSCtx.getLock(); 905ad09de9SLang Hames auto &Ctx = *TSCtx.getContext(); 915ad09de9SLang Hames auto M = llvm::make_unique<Module>("M", Ctx); 925ad09de9SLang Hames TSCtx = ThreadSafeContext(); 935ad09de9SLang Hames } 945ad09de9SLang Hames 955ad09de9SLang Hames } // end anonymous namespace 96