BUG: Improve thead safety of ObjectFactoryBase::Initialize#4226
BUG: Improve thead safety of ObjectFactoryBase::Initialize#4226blowekamp wants to merge 1 commit intoInsightSoftwareConsortium:masterfrom
Conversation
Block concurent threads until initializaiton is completed.
| if (!m_PimplGlobals->m_Initialized) | ||
| { | ||
| ObjectFactoryBase::InitializeFactoryList(); | ||
| ObjectFactoryBase::RegisterInternal(); | ||
| // only one thread initializing at a time, wait until initialization is completed. | ||
| std::lock_guard lockGuard(m_PimplGlobals->m_Lock); | ||
| if (!m_PimplGlobals->m_Initialized) |
There was a problem hiding this comment.
Looks like you're doing double-checked locking, which is considered an anti-pattern nowadays! If one thread sets m_PimplGlobals->m_Initialized = true while at the same time, another thread tries to evaluate m_PimplGlobals->m_Initialized outside the locked region, we have undefined behavior.
There was a problem hiding this comment.
What is the updated pattern? To ensure it's only initialized once and block other threads until it it initialed?
There was a problem hiding this comment.
My bigger concern now is if using std::mutex during static initialization is OK aka ( defined behavior ).
evaluate m_PimplGlobals->m_Initialized outside the locked region, we have undefined behavior.
Not sure how undefined the undefined read behavior would be, maybe just not 100% synced between threads. It's will either be true or false, either will be OK.
There was a problem hiding this comment.
std::call_once?
Thanks, @dzenanz. I just gave it a try, using std::call_once. Please check! (Still draft!)
| std::lock_guard lockGuard(m_PimplGlobals->m_Lock); | ||
| if (!m_PimplGlobals->m_Initialized) | ||
| { | ||
| ObjectFactoryBase::InitializeFactoryList(); |
There was a problem hiding this comment.
Please consider removing the ObjectFactoryBase::InitializeFactoryList() call, as in:
|
Would it be possible to move this code (calling ObjectFactoryBase::RegisterInternal() and ObjectFactoryBase::LoadDynamicFactories()) to the default-constructor of ITK/Modules/Core/Common/src/itkObjectFactoryBase.cxx Lines 244 to 247 in c3a8eab |
|
4227 looks like a better approach. |
Block concurent threads until initializaiton is completed.
PR Checklist
Refer to the ITK Software Guide for
further development details if necessary.