Skip to content

Commit cfb00a4

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

File tree

3 files changed

+74
-20
lines changed

3 files changed

+74
-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: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "llvm/Support/CommandLine.h"
5555
#include "llvm/Support/Debug.h"
5656
#include "llvm/Support/Error.h"
57+
#include "llvm/Support/ErrorHandling.h"
5758
#include "llvm/Support/ManagedStatic.h"
5859
#include "llvm/Support/Path.h"
5960
#include "llvm/Support/raw_ostream.h"
@@ -140,10 +141,10 @@ struct InterpreterInfo {
140141

141142
// NOLINTBEGIN
142143
// std::deque avoids relocations and calling the dtor of InterpreterInfo.
143-
static llvm::ManagedStatic<std::deque<std::shared_ptr<InterpreterInfo>>>
144+
static llvm::ManagedStatic<std::deque<std::unique_ptr<InterpreterInfo>>>
144145
sInterpreters;
145146
static llvm::ManagedStatic<
146-
std::unordered_map<clang::ASTContext*, std::weak_ptr<InterpreterInfo>>>
147+
std::unordered_map<clang::ASTContext*, InterpreterInfo*>>
147148
sInterpreterASTMap;
148149
static std::recursive_mutex InterpreterStackLock;
149150
static std::recursive_mutex LLVMLock;
@@ -161,7 +162,7 @@ static InterpreterInfo& getInterpInfo(const clang::Decl* D) {
161162
return getInterpInfo();
162163
if (sInterpreters->size() == 1)
163164
return *sInterpreters->back();
164-
return *(*sInterpreterASTMap)[&D->getASTContext()].lock();
165+
return *(*sInterpreterASTMap)[&D->getASTContext()];
165166
}
166167
static InterpreterInfo& getInterpInfo(const void* D) {
167168
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
@@ -171,7 +172,7 @@ static InterpreterInfo& getInterpInfo(const void* D) {
171172
return *sInterpreters->back();
172173
for (auto& item : *sInterpreterASTMap) {
173174
if (item.first->getAllocator().identifyObject(D))
174-
return *item.second.lock();
175+
return *item.second;
175176
}
176177
llvm_unreachable(
177178
"This pointer does not belong to any interpreter instance.\n");
@@ -189,7 +190,7 @@ static compat::Interpreter& getInterp(const clang::Decl* D) {
189190
return getInterp();
190191
if (sInterpreters->size() == 1)
191192
return *sInterpreters->back()->Interpreter;
192-
return *(*sInterpreterASTMap)[&D->getASTContext()].lock()->Interpreter;
193+
return *(*sInterpreterASTMap)[&D->getASTContext()]->Interpreter;
193194
}
194195
static compat::Interpreter& getInterp(const void* D) {
195196
return *getInterpInfo(D).Interpreter;
@@ -3338,6 +3339,8 @@ static std::string MakeResourcesPath() {
33383339
TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
33393340
const std::vector<const char*>& GpuArgs /*={}*/) {
33403341
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
3342+
assert(sInterpreters->size() == sInterpreterASTMap->size());
3343+
33413344
std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr);
33423345
std::string ResourceDir = MakeResourcesPath();
33433346
std::vector<const char*> ClingArgv = {"-resource-dir", ResourceDir.c_str(),
@@ -3414,42 +3417,73 @@ TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
34143417
)");
34153418

34163419
sInterpreters->emplace_back(
3417-
std::make_shared<InterpreterInfo>(I, /*Owned=*/true));
3420+
std::make_unique<InterpreterInfo>(I, /*Owned=*/true));
34183421
sInterpreterASTMap->insert(
34193422
{&sInterpreters->back()->Interpreter->getSema().getASTContext(),
3420-
sInterpreters->back()});
3423+
sInterpreters->back().get()});
34213424

3425+
assert(sInterpreters->size() == sInterpreterASTMap->size());
34223426
return I;
34233427
}
34243428

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

34283446
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-
});
3447+
auto foundAST = find_interpreter_in_map(sInterpreters->back().get());
34343448
sInterpreterASTMap->erase(foundAST);
34353449
sInterpreters->pop_back();
34363450
return true;
34373451
}
34383452

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

3445-
auto foundAST = std::find_if(
3446-
sInterpreterASTMap->begin(), sInterpreterASTMap->end(),
3447-
[&found](const auto& Item) { return Item.second.lock() == *found; });
3457+
auto foundAST = find_interpreter_in_map((*found).get());
34483458
sInterpreterASTMap->erase(foundAST);
34493459
sInterpreters->erase(found);
34503460
return true;
34513461
}
34523462

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

@@ -3477,10 +3511,13 @@ TInterp_t GetInterpreter() {
34773511

34783512
void UseExternalInterpreter(TInterp_t I) {
34793513
std::lock_guard<std::recursive_mutex> Lock(InterpreterStackLock);
3480-
assert(sInterpreters->empty() && "sInterpreter already in use!");
34813514
sInterpreters->emplace_back(
3482-
std::make_shared<InterpreterInfo>(static_cast<compat::Interpreter*>(I),
3515+
std::make_unique<InterpreterInfo>(static_cast<compat::Interpreter*>(I),
34833516
/*isOwned=*/false));
3517+
sInterpreterASTMap->insert(
3518+
{&sInterpreters->back()->Interpreter->getSema().getASTContext(),
3519+
sInterpreters->back().get()});
3520+
assert(sInterpreters->size() == sInterpreterASTMap->size());
34843521
}
34853522

34863523
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)