xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/ThreadSafeModuleTest.cpp (revision 5ad09de9f366860e146513fc9f7b1a986f5b0fc0)
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   ThreadSafeModule TSM(llvm::make_unique<Module>("M", *TSCtx.getContext()),
27                        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   ThreadSafeModule TSM1(llvm::make_unique<Module>("M1", *TSCtx.getContext()),
36                         TSCtx);
37   ThreadSafeModule TSM2(llvm::make_unique<Module>("M2", *TSCtx.getContext()),
38                         std::move(TSCtx));
39 }
40 
41 TEST(ThreadSafeModuleTest, ContextOwnershipSharedWithClient) {
42   // Test that ownership of a context can be shared with a client-held
43   // ThreadSafeContext so that it can be re-used for new modules.
44   ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
45 
46   {
47     // Create and destroy a module.
48     ThreadSafeModule TSM1(llvm::make_unique<Module>("M1", *TSCtx.getContext()),
49                           TSCtx);
50   }
51 
52   // Verify that the context is still available for re-use.
53   ThreadSafeModule TSM2(llvm::make_unique<Module>("M2", *TSCtx.getContext()),
54                         std::move(TSCtx));
55 }
56 
57 TEST(ThreadSafeModuleTest, ThreadSafeModuleMoveAssignment) {
58   // Move assignment needs to move the module before the context (opposite
59   // to the field order) to ensure that overwriting with an empty
60   // ThreadSafeModule does not destroy the context early.
61   ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
62   ThreadSafeModule TSM(llvm::make_unique<Module>("M", *TSCtx.getContext()),
63                        std::move(TSCtx));
64   TSM = ThreadSafeModule();
65 }
66 
67 TEST(ThreadSafeModuleTest, BasicContextLockAPI) {
68   // Test that basic lock API calls work.
69   ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
70   ThreadSafeModule TSM(llvm::make_unique<Module>("M", *TSCtx.getContext()),
71                        TSCtx);
72 
73   { auto L = TSCtx.getLock(); }
74 
75   { auto L = TSM.getContextLock(); }
76 }
77 
78 TEST(ThreadSafeModuleTest, ContextLockPreservesContext) {
79   // Test that the existence of a context lock preserves the attached
80   // context.
81   // The trick to verify this is a bit of a hack: We attach a Module
82   // (without the ThreadSafeModule wrapper) to the context, then verify
83   // that this Module destructs safely (which it will not if its context
84   // has been destroyed) even though all references to the context have
85   // been thrown away (apart from the lock).
86 
87   ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
88   auto L = TSCtx.getLock();
89   auto &Ctx = *TSCtx.getContext();
90   auto M = llvm::make_unique<Module>("M", Ctx);
91   TSCtx = ThreadSafeContext();
92 }
93 
94 } // end anonymous namespace
95