Skip to content

Commit 032700b

Browse files
add Cpp::TakeInterpreter
pops interpreter with destroying it destruction to be handled by the caller
1 parent 97bd9b8 commit 032700b

File tree

3 files changed

+73
-20
lines changed

3 files changed

+73
-20
lines changed

include/CppInterOp/CppInterOp.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,11 @@ CreateInterpreter(const std::vector<const char*>& Args = {},
702702
///\returns false on failure or if \c I is not tracked in the stack.
703703
CPPINTEROP_API bool DeleteInterpreter(TInterp_t I = nullptr);
704704

705+
/// Take ownership of an interpreter instance.
706+
///\param[in] I - the interpreter to be taken, if nullptr, returns the last.
707+
///\returns nullptr on failure or if \c I is not tracked in the stack.
708+
CPPINTEROP_API TInterp_t TakeInterpreter(TInterp_t I = nullptr);
709+
705710
/// Activates an instance of an interpreter to handle subsequent API requests
706711
///\param[in] I - the interpreter to be activated.
707712
///\returns false on failure.

lib/CppInterOp/CppInterOp.cpp

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,10 @@ struct InterpreterInfo {
140140

141141
// NOLINTBEGIN
142142
// std::deque avoids relocations and calling the dtor of InterpreterInfo.
143-
static llvm::ManagedStatic<std::deque<std::shared_ptr<InterpreterInfo>>>
143+
static llvm::ManagedStatic<std::deque<std::unique_ptr<InterpreterInfo>>>
144144
sInterpreters;
145145
static llvm::ManagedStatic<
146-
std::unordered_map<clang::ASTContext*, std::weak_ptr<InterpreterInfo>>>
146+
std::unordered_map<clang::ASTContext*, InterpreterInfo*>>
147147
sInterpreterASTMap;
148148
static std::recursive_mutex InterpreterStackLock;
149149
static std::recursive_mutex LLVMLock;
@@ -161,7 +161,7 @@ static InterpreterInfo& getInterpInfo(const clang::Decl* D) {
161161
return getInterpInfo();
162162
if (sInterpreters->size() == 1)
163163
return *sInterpreters->back();
164-
return *(*sInterpreterASTMap)[&D->getASTContext()].lock();
164+
return *(*sInterpreterASTMap)[&D->getASTContext()];
165165
}
166166
static InterpreterInfo& getInterpInfo(const void* D) {
167167
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
@@ -171,7 +171,7 @@ static InterpreterInfo& getInterpInfo(const void* D) {
171171
return *sInterpreters->back();
172172
for (auto& item : *sInterpreterASTMap) {
173173
if (item.first->getAllocator().identifyObject(D))
174-
return *item.second.lock();
174+
return *item.second;
175175
}
176176
llvm_unreachable(
177177
"This pointer does not belong to any interpreter instance.\n");
@@ -189,7 +189,7 @@ static compat::Interpreter& getInterp(const clang::Decl* D) {
189189
return getInterp();
190190
if (sInterpreters->size() == 1)
191191
return *sInterpreters->back()->Interpreter;
192-
return *(*sInterpreterASTMap)[&D->getASTContext()].lock()->Interpreter;
192+
return *(*sInterpreterASTMap)[&D->getASTContext()]->Interpreter;
193193
}
194194
static compat::Interpreter& getInterp(const void* D) {
195195
return *getInterpInfo(D).Interpreter;
@@ -3338,6 +3338,8 @@ static std::string MakeResourcesPath() {
33383338
TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
33393339
const std::vector<const char*>& GpuArgs /*={}*/) {
33403340
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
3341+
assert(sInterpreters->size() == sInterpreterASTMap->size());
3342+
33413343
std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr);
33423344
std::string ResourceDir = MakeResourcesPath();
33433345
std::vector<const char*> ClingArgv = {"-resource-dir", ResourceDir.c_str(),
@@ -3414,42 +3416,73 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
34143416
)");
34153417

34163418
sInterpreters->emplace_back(
3417-
std::make_shared<InterpreterInfo>(I, /*Owned=*/true));
3419+
std::make_unique<InterpreterInfo>(I, /*Owned=*/true));
34183420
sInterpreterASTMap->insert(
34193421
{&sInterpreters->back()->Interpreter->getSema().getASTContext(),
3420-
sInterpreters->back()});
3422+
sInterpreters->back().get()});
34213423

3424+
assert(sInterpreters->size() == sInterpreterASTMap->size());
34223425
return I;
34233426
}
34243427

3428+
static inline auto find_interpreter_in_stack(TInterp_t I) {
3429+
return std::find_if(
3430+
sInterpreters->begin(), sInterpreters->end(),
3431+
[&I](const auto& Info) { return Info->Interpreter == I; });
3432+
}
3433+
3434+
static inline auto find_interpreter_in_map(InterpreterInfo* I) {
3435+
return std::find_if(sInterpreterASTMap->begin(), sInterpreterASTMap->end(),
3436+
[](const auto& Item) {
3437+
return Item.second == sInterpreters->back().get();
3438+
});
3439+
}
3440+
34253441
bool DeleteInterpreter(TInterp_t I /*=nullptr*/) {
34263442
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
3443+
assert(sInterpreters->size() == sInterpreterASTMap->size());
34273444

34283445
if (!I) {
3429-
auto foundAST =
3430-
std::find_if(sInterpreterASTMap->begin(), sInterpreterASTMap->end(),
3431-
[](const auto& Item) {
3432-
return Item.second.lock() == sInterpreters->back();
3433-
});
3446+
auto foundAST = find_interpreter_in_map(sInterpreters->back().get());
34343447
sInterpreterASTMap->erase(foundAST);
34353448
sInterpreters->pop_back();
34363449
return true;
34373450
}
34383451

3439-
auto found =
3440-
std::find_if(sInterpreters->begin(), sInterpreters->end(),
3441-
[&I](const auto& Info) { return Info->Interpreter == I; });
3452+
auto found = find_interpreter_in_stack(I);
34423453
if (found == sInterpreters->end())
34433454
return false; // failure
34443455

3445-
auto foundAST = std::find_if(
3446-
sInterpreterASTMap->begin(), sInterpreterASTMap->end(),
3447-
[&found](const auto& Item) { return Item.second.lock() == *found; });
3456+
auto foundAST = find_interpreter_in_map((*found).get());
34483457
sInterpreterASTMap->erase(foundAST);
34493458
sInterpreters->erase(found);
34503459
return true;
34513460
}
34523461

3462+
TInterp_t TakeInterpreter(TInterp_t I /*=nullptr*/) {
3463+
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
3464+
assert(sInterpreters->size() == sInterpreterASTMap->size());
3465+
3466+
if (!I) {
3467+
auto foundAST = find_interpreter_in_map(sInterpreters->back().get());
3468+
sInterpreterASTMap->erase(foundAST);
3469+
InterpreterInfo* res = sInterpreters->back().release();
3470+
sInterpreters->pop_back();
3471+
return res->Interpreter;
3472+
}
3473+
3474+
auto found = find_interpreter_in_stack(I);
3475+
if (found == sInterpreters->end())
3476+
return nullptr; // failure
3477+
3478+
auto foundAST = find_interpreter_in_map((*found).get());
3479+
sInterpreterASTMap->erase(foundAST);
3480+
InterpreterInfo* res = (*found).release();
3481+
sInterpreters->erase(found);
3482+
assert(sInterpreters->size() == sInterpreterASTMap->size());
3483+
return res->Interpreter;
3484+
}
3485+
34533486
bool ActivateInterpreter(TInterp_t I) {
34543487
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
34553488

@@ -3477,10 +3510,13 @@ TInterp_t GetInterpreter() {
34773510

34783511
void UseExternalInterpreter(TInterp_t I) {
34793512
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
3480-
assert(sInterpreters->empty() && "sInterpreter already in use!");
34813513
sInterpreters->emplace_back(
3482-
std::make_shared<InterpreterInfo>(static_cast<compat::Interpreter*>(I),
3514+
std::make_unique<InterpreterInfo>(static_cast<compat::Interpreter*>(I),
34833515
/*isOwned=*/false));
3516+
sInterpreterASTMap->insert(
3517+
{&sInterpreters->back()->Interpreter->getSema().getASTContext(),
3518+
sInterpreters->back().get()});
3519+
assert(sInterpreters->size() == sInterpreterASTMap->size());
34843520
}
34853521

34863522
void AddSearchPath(const char* dir, bool isUser, bool prepend) {

unittests/CppInterOp/InterpreterTest.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,19 @@ TEST(InterpreterTest, DeleteInterpreter) {
8888

8989
EXPECT_EQ(I3, Cpp::GetInterpreter()) << "I3 is not active";
9090

91+
auto* D1 = Cpp::TakeInterpreter();
92+
EXPECT_EQ(D1, I3);
93+
94+
Cpp::UseExternalInterpreter(D1);
95+
9196
EXPECT_TRUE(Cpp::DeleteInterpreter(nullptr));
9297
EXPECT_EQ(I2, Cpp::GetInterpreter());
9398

99+
auto* D2 = Cpp::TakeInterpreter(I2);
100+
EXPECT_EQ(I2, D2);
101+
102+
Cpp::UseExternalInterpreter(D2);
103+
94104
auto* I4 = reinterpret_cast<void*>(static_cast<std::uintptr_t>(~0U));
95105
EXPECT_FALSE(Cpp::DeleteInterpreter(I4));
96106

@@ -150,6 +160,8 @@ TEST(InterpreterTest, Process) {
150160
EXPECT_EQ(Res, CXError_Success);
151161
clang_Value_dispose(CXV);
152162
clang_Interpreter_dispose(CXI);
163+
auto* OldI = Cpp::TakeInterpreter();
164+
EXPECT_EQ(OldI, I);
153165
}
154166

155167
TEST(InterpreterTest, EmscriptenExceptionHandling) {

0 commit comments

Comments
 (0)