1*5ad09de9SLang Hames //===--- ThreadSafeModuleTest.cpp - Test basic use of ThreadSafeModule ----===// 2*5ad09de9SLang Hames // 3*5ad09de9SLang Hames // The LLVM Compiler Infrastructure 4*5ad09de9SLang Hames // 5*5ad09de9SLang Hames // This file is distributed under the University of Illinois Open Source 6*5ad09de9SLang Hames // License. See LICENSE.TXT for details. 7*5ad09de9SLang Hames // 8*5ad09de9SLang Hames //===----------------------------------------------------------------------===// 9*5ad09de9SLang Hames 10*5ad09de9SLang Hames #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" 11*5ad09de9SLang Hames #include "gtest/gtest.h" 12*5ad09de9SLang Hames 13*5ad09de9SLang Hames #include <atomic> 14*5ad09de9SLang Hames #include <future> 15*5ad09de9SLang Hames #include <thread> 16*5ad09de9SLang Hames 17*5ad09de9SLang Hames using namespace llvm; 18*5ad09de9SLang Hames using namespace llvm::orc; 19*5ad09de9SLang Hames 20*5ad09de9SLang Hames namespace { 21*5ad09de9SLang Hames 22*5ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextWhollyOwnedByOneModule) { 23*5ad09de9SLang Hames // Test that ownership of a context can be transferred to a single 24*5ad09de9SLang Hames // ThreadSafeModule. 25*5ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 26*5ad09de9SLang Hames ThreadSafeModule TSM(llvm::make_unique<Module>("M", *TSCtx.getContext()), 27*5ad09de9SLang Hames std::move(TSCtx)); 28*5ad09de9SLang Hames } 29*5ad09de9SLang Hames 30*5ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextOwnershipSharedByTwoModules) { 31*5ad09de9SLang Hames // Test that ownership of a context can be shared between more than one 32*5ad09de9SLang Hames // ThreadSafeModule. 33*5ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 34*5ad09de9SLang Hames 35*5ad09de9SLang Hames ThreadSafeModule TSM1(llvm::make_unique<Module>("M1", *TSCtx.getContext()), 36*5ad09de9SLang Hames TSCtx); 37*5ad09de9SLang Hames ThreadSafeModule TSM2(llvm::make_unique<Module>("M2", *TSCtx.getContext()), 38*5ad09de9SLang Hames std::move(TSCtx)); 39*5ad09de9SLang Hames } 40*5ad09de9SLang Hames 41*5ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextOwnershipSharedWithClient) { 42*5ad09de9SLang Hames // Test that ownership of a context can be shared with a client-held 43*5ad09de9SLang Hames // ThreadSafeContext so that it can be re-used for new modules. 44*5ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 45*5ad09de9SLang Hames 46*5ad09de9SLang Hames { 47*5ad09de9SLang Hames // Create and destroy a module. 48*5ad09de9SLang Hames ThreadSafeModule TSM1(llvm::make_unique<Module>("M1", *TSCtx.getContext()), 49*5ad09de9SLang Hames TSCtx); 50*5ad09de9SLang Hames } 51*5ad09de9SLang Hames 52*5ad09de9SLang Hames // Verify that the context is still available for re-use. 53*5ad09de9SLang Hames ThreadSafeModule TSM2(llvm::make_unique<Module>("M2", *TSCtx.getContext()), 54*5ad09de9SLang Hames std::move(TSCtx)); 55*5ad09de9SLang Hames } 56*5ad09de9SLang Hames 57*5ad09de9SLang Hames TEST(ThreadSafeModuleTest, ThreadSafeModuleMoveAssignment) { 58*5ad09de9SLang Hames // Move assignment needs to move the module before the context (opposite 59*5ad09de9SLang Hames // to the field order) to ensure that overwriting with an empty 60*5ad09de9SLang Hames // ThreadSafeModule does not destroy the context early. 61*5ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 62*5ad09de9SLang Hames ThreadSafeModule TSM(llvm::make_unique<Module>("M", *TSCtx.getContext()), 63*5ad09de9SLang Hames std::move(TSCtx)); 64*5ad09de9SLang Hames TSM = ThreadSafeModule(); 65*5ad09de9SLang Hames } 66*5ad09de9SLang Hames 67*5ad09de9SLang Hames TEST(ThreadSafeModuleTest, BasicContextLockAPI) { 68*5ad09de9SLang Hames // Test that basic lock API calls work. 69*5ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 70*5ad09de9SLang Hames ThreadSafeModule TSM(llvm::make_unique<Module>("M", *TSCtx.getContext()), 71*5ad09de9SLang Hames TSCtx); 72*5ad09de9SLang Hames 73*5ad09de9SLang Hames { auto L = TSCtx.getLock(); } 74*5ad09de9SLang Hames 75*5ad09de9SLang Hames { auto L = TSM.getContextLock(); } 76*5ad09de9SLang Hames } 77*5ad09de9SLang Hames 78*5ad09de9SLang Hames TEST(ThreadSafeModuleTest, ContextLockPreservesContext) { 79*5ad09de9SLang Hames // Test that the existence of a context lock preserves the attached 80*5ad09de9SLang Hames // context. 81*5ad09de9SLang Hames // The trick to verify this is a bit of a hack: We attach a Module 82*5ad09de9SLang Hames // (without the ThreadSafeModule wrapper) to the context, then verify 83*5ad09de9SLang Hames // that this Module destructs safely (which it will not if its context 84*5ad09de9SLang Hames // has been destroyed) even though all references to the context have 85*5ad09de9SLang Hames // been thrown away (apart from the lock). 86*5ad09de9SLang Hames 87*5ad09de9SLang Hames ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 88*5ad09de9SLang Hames auto L = TSCtx.getLock(); 89*5ad09de9SLang Hames auto &Ctx = *TSCtx.getContext(); 90*5ad09de9SLang Hames auto M = llvm::make_unique<Module>("M", Ctx); 91*5ad09de9SLang Hames TSCtx = ThreadSafeContext(); 92*5ad09de9SLang Hames } 93*5ad09de9SLang Hames 94*5ad09de9SLang Hames } // end anonymous namespace 95