Skip to content

Commit 38c0ab0

Browse files
committed
ENH: Allow sharing xoutManager between threads
1 parent 3700590 commit 38c0ab0

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

Core/Kernel/elxElastixMain.cxx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
# include "itkOpenCLSetup.h"
3636
#endif
3737

38+
#include <mutex>
39+
40+
3841
namespace
3942
{
4043
/**
@@ -139,6 +142,47 @@ xoutManager::xoutManager(const std::string & logFileName, const bool setupLoggin
139142
}
140143
}
141144

145+
146+
std::shared_ptr<const xoutManager>
147+
xoutManager::GetSharedManager(const std::string & logFileName, const bool setupLogging, const bool setupCout)
148+
{
149+
const auto makeManagerPtrPair = [](const std::string & logFileName, const bool setupLogging, const bool setupCout) {
150+
std::shared_ptr<const xoutManager> sharedPtr(new xoutManager(logFileName, setupLogging, setupCout));
151+
std::weak_ptr<const xoutManager> weakPtr(sharedPtr);
152+
return std::make_pair(sharedPtr, weakPtr);
153+
};
154+
155+
// Note that the initialization of this static variable is thread-safe,
156+
// as supported by C++11 "magic statics".
157+
static auto managerPtrPair = makeManagerPtrPair(logFileName, setupLogging, setupCout);
158+
159+
const struct ResetGuard
160+
{
161+
std::shared_ptr<const xoutManager> & sharedPtr;
162+
~ResetGuard() { sharedPtr.reset(); }
163+
} resetGuard{ managerPtrPair.first };
164+
165+
const auto lockedSharedPtr = managerPtrPair.second.lock();
166+
167+
if (lockedSharedPtr == nullptr)
168+
{
169+
// Apply the "double-checked locking" design pattern.
170+
static std::mutex managerMutex;
171+
const std::lock_guard<std::mutex> lock(managerMutex);
172+
173+
const auto doubleCheckedLockedSharedPtr = managerPtrPair.second.lock();
174+
175+
if (doubleCheckedLockedSharedPtr == nullptr)
176+
{
177+
managerPtrPair = makeManagerPtrPair(logFileName, setupLogging, setupCout);
178+
return managerPtrPair.second.lock();
179+
}
180+
return doubleCheckedLockedSharedPtr;
181+
}
182+
return lockedSharedPtr;
183+
}
184+
185+
142186
xoutManager::Guard::~Guard()
143187
{
144188
g_data = {};

Core/Kernel/elxElastixMain.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ class xoutManager
6464
/** This explicit constructor does set up the "xout" output streams. */
6565
explicit xoutManager(const std::string & logfilename, const bool setupLogging, const bool setupCout);
6666

67+
static std::shared_ptr<const xoutManager>
68+
GetSharedManager(const std::string & logFileName, const bool setupLogging, const bool setupCout);
69+
6770
/** The default-constructor only just constructs a manager object */
6871
xoutManager() = default;
6972

Core/Main/elxElastixFilter.hxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ ElastixFilter<TFixedImage, TMovingImage>::GenerateData(void)
197197
}
198198

199199
// Setup xout
200-
const elx::xoutManager manager(logFileName, this->GetLogToFile(), this->GetLogToConsole());
200+
const auto sharedManager = xoutManager::GetSharedManager(logFileName, this->GetLogToFile(), this->GetLogToConsole());
201201

202202
// Run the (possibly multiple) registration(s)
203203
for (unsigned int i = 0; i < parameterMapVector.size(); ++i)

0 commit comments

Comments
 (0)