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