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