Skip to content

mrregister: fix race condition in displacement update#3277

Open
daljit46 wants to merge 1 commit intodevfrom
fix_racy_reduction_mrregister
Open

mrregister: fix race condition in displacement update#3277
daljit46 wants to merge 1 commit intodevfrom
fix_racy_reduction_mrregister

Conversation

@daljit46
Copy link
Member

The following race condition was identified with TSAN:

WARNING: ThreadSanitizer: data race (pid=24689)
  Write of size 8 at 0x00016d515ac0 by thread T306:
    #0 MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>::operator()(MR::Iterator const&) <null>:90187328 (libmrtrix-core.dylib:arm64+0x52d0b8)
    #1 void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::execute() <null>:90187328 (libmrtrix-core.dylib:arm64+0x52e168)
    #2 std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>::__execute() <null>:90187328 (libmrtrix-core.dylib:arm64+0x52e510)
    #3 void* std::__1::__thread_proxy[abi:ne180100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>*>>(void*) <null>:90187328 (libmrtrix-core.dylib:arm64+0x52e628)

  Previous read of size 8 at 0x00016d515ac0 by thread T310:
    #0 MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>::operator()(MR::Iterator const&) <null>:90187328 (libmrtrix-core.dylib:arm64+0x52d0a4)
    #1 void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::execute() <null>:90187328 (libmrtrix-core.dylib:arm64+0x52e168)
    #2 std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>::__execute() <null>:90187328 (libmrtrix-core.dylib:arm64+0x52e510)
    #3 void* std::__1::__thread_proxy[abi:ne180100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>*>>(void*) <null>:90187328 (libmrtrix-core.dylib:arm64+0x52e628)

  Location is stack of main thread.

  Thread T306 (tid=13272096, running) created by main thread at:
    #0 pthread_create <null>:93330752 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8)
    #1 std::__1::future<std::__1::__invoke_of<__decay(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&), __decay(void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*)>::type> std::__1::async[abi:ne180100]<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>(std::__1::launch, MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&, void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*&&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x52dd98)
    #2 void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run<MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&)&, MR::Image<double>&>(MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&)&, MR::Image<double>&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x52ac6c)
    #3 void MR::Registration::NonLinear::run<MR::Registration::Transform::Rigid, MR::Image<double>, MR::Image<double>, MR::Image<double>, MR::Image<double>>(MR::Registration::Transform::Rigid, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x4fc40c)
    #4 void MR::Registration::NonLinear::run<MR::Registration::Transform::Rigid, MR::Image<double>, MR::Image<double>, MR::Image<double>, MR::Image<double>>(MR::Registration::Transform::Rigid, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x4f7e94)
    #5 run() <null>:91235072 (mrregister:arm64+0x100013014)
    #6 run() <null>:91235072 (mrregister:arm64+0x1000083ec)
    #7 <null> <null> (0x000185b48274)

  Thread T310 (tid=13272100, running) created by main thread at:
    #0 pthread_create <null>:93332048 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8)
    #1 std::__1::future<std::__1::__invoke_of<__decay(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&), __decay(void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*)>::type> std::__1::async[abi:ne180100]<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>(std::__1::launch, MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&, void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*&&) <null>:90187328 (libmrtrix-core.dylib:arm64+0x52dd98)
    #2 void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run<MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&)&, MR::Image<double>&>(MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&)&, MR::Image<double>&) <null>:90187328 (libmrtrix-core.dylib:arm64+0x52ac6c)
    #3 void MR::Registration::NonLinear::run<MR::Registration::Transform::Rigid, MR::Image<double>, MR::Image<double>, MR::Image<double>, MR::Image<double>>(MR::Registration::Transform::Rigid, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&) <null>:90187328 (libmrtrix-core.dylib:arm64+0x4fc40c)
    #4 void MR::Registration::NonLinear::run<MR::Registration::Transform::Rigid, MR::Image<double>, MR::Image<double>, MR::Image<double>, MR::Image<double>>(MR::Registration::Transform::Rigid, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&) <null>:90187328 (libmrtrix-core.dylib:arm64+0x4f7e94)
    #5 run() <null>:91230992 (mrregister:arm64+0x100013014)
    #6 run() <null>:91230992 (mrregister:arm64+0x1000083ec)
    #7 <null> <null> (0x000185b48274)

SUMMARY: ThreadSanitizer: data race (libmrtrix-core.dylib:arm64+0x52d0b8) in MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>::operator()(MR::Iterator const&)+0x34c
==================
==================
WARNING: ThreadSanitizer: data race (pid=24689)
  Write of size 8 at 0x00016d515ac0 by thread T312:
    #0 MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>::operator()(MR::Iterator const&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x52d0b8)
    #1 void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::execute() <null>:90187520 (libmrtrix-core.dylib:arm64+0x52e168)
    #2 std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>::__execute() <null>:90187520 (libmrtrix-core.dylib:arm64+0x52e510)
    #3 void* std::__1::__thread_proxy[abi:ne180100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>*>>(void*) <null>:90187520 (libmrtrix-core.dylib:arm64+0x52e628)

  Previous write of size 8 at 0x00016d515ac0 by thread T310:
    #0 MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>::operator()(MR::Iterator const&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x52d0b8)
    #1 void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::execute() <null>:90187520 (libmrtrix-core.dylib:arm64+0x52e168)
    #2 std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>::__execute() <null>:90187520 (libmrtrix-core.dylib:arm64+0x52e510)
    #3 void* std::__1::__thread_proxy[abi:ne180100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>>*>>(void*) <null>:90187520 (libmrtrix-core.dylib:arm64+0x52e628)

  Location is stack of main thread.

  Thread T312 (tid=13272102, running) created by main thread at:
    #0 pthread_create <null>:93332048 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8)
    #1 std::__1::future<std::__1::__invoke_of<__decay(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&), __decay(void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*)>::type> std::__1::async[abi:ne180100]<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>(std::__1::launch, MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&, void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*&&) <null>:90177536 (libmrtrix-core.dylib:arm64+0x52dd98)
    #2 void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run<MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&)&, MR::Image<double>&>(MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&)&, MR::Image<double>&) <null>:90177536 (libmrtrix-core.dylib:arm64+0x52af14)
    #3 void MR::Registration::NonLinear::run<MR::Registration::Transform::Rigid, MR::Image<double>, MR::Image<double>, MR::Image<double>, MR::Image<double>>(MR::Registration::Transform::Rigid, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&) <null>:90177536 (libmrtrix-core.dylib:arm64+0x4fc40c)
    #4 void MR::Registration::NonLinear::run<MR::Registration::Transform::Rigid, MR::Image<double>, MR::Image<double>, MR::Image<double>, MR::Image<double>>(MR::Registration::Transform::Rigid, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&) <null>:90177536 (libmrtrix-core.dylib:arm64+0x4f7e94)
    #5 run() <null>:91230992 (mrregister:arm64+0x100013014)
    #6 run() <null>:91230992 (mrregister:arm64+0x1000083ec)
    #7 <null> <null> (0x000185b48274)

  Thread T310 (tid=13272100, running) created by main thread at:
    #0 pthread_create <null>:93330752 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8)
    #1 std::__1::future<std::__1::__invoke_of<__decay(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&), __decay(void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*)>::type> std::__1::async[abi:ne180100]<void (void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread::*)(), void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*>(std::__1::launch, MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&, void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run_outer<MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&>(MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>&)::PerThread*&&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x52dd98)
    #2 void MR::(anonymous namespace)::ThreadedLoopRunOuter<MR::LoopAlongDynamicAxes>::run<MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&)&, MR::Image<double>&>(MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&)&, MR::Image<double>&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x52ac6c)
    #3 void MR::Registration::NonLinear::run<MR::Registration::Transform::Rigid, MR::Image<double>, MR::Image<double>, MR::Image<double>, MR::Image<double>>(MR::Registration::Transform::Rigid, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x4fc40c)
    #4 void MR::Registration::NonLinear::run<MR::Registration::Transform::Rigid, MR::Image<double>, MR::Image<double>, MR::Image<double>, MR::Image<double>>(MR::Registration::Transform::Rigid, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, MR::Image<double>&) <null>:90187520 (libmrtrix-core.dylib:arm64+0x4f7e94)
    #5 run() <null>:91235072 (mrregister:arm64+0x100013014)
    #6 run() <null>:91235072 (mrregister:arm64+0x1000083ec)
    #7 <null> <null> (0x000185b48274)

SUMMARY: ThreadSanitizer: data race (libmrtrix-core.dylib:arm64+0x52d0b8) in MR::(anonymous namespace)::ThreadedLoopRunInner<1, MR::Registration::Warp::update_displacement_scaling_and_squaring(MR::Image<double>&, MR::Image<double>&, MR::Image<double>&, double)::'lambda'(MR::Image<double>&), MR::Image<double>>::operator()(MR::Iterator const&)+0x34c

The cause was this piece of code:

  auto max_norm_func = [&max_norm](Image<default_type> &update) {
    default_type norm = Eigen::Vector3d(update.row(3)).norm();
    if (norm > max_norm)
      max_norm = norm;
  };
  ThreadedLoop(update).run(max_norm_func, update);

Here, max_norm is a local stack variable. The lambda captures it by reference thus the variable is subject to reads/writes from different threads without any synchronisation. This PR fixes the problem by replacing the shared max norm lambda with a thread local functor reduction and mutex-protected merge. Also rather than computing as square root inside the functor, we compute the squared norm and only at the end evaluate the square root.

Replace the shared max norm lambda in scaling-and-squaring with
a thread local functor reduction and mutex-protected merge.
@daljit46 daljit46 self-assigned this Mar 17, 2026
@daljit46 daljit46 added the bug label Mar 17, 2026
@daljit46 daljit46 requested a review from a team March 17, 2026 16:01
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

MaxNormSquaredFunctor &operator=(MaxNormSquaredFunctor &&) = delete;

~MaxNormSquaredFunctor() {
std::lock_guard<std::mutex> lock(mutex);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'lock' of type 'std::lock_guardstd::mutex' can be declared 'const' [misc-const-correctness]

Suggested change
std::lock_guard<std::mutex> lock(mutex);
std::lock_guard<std::mutex> const lock(mutex);

}

private:
default_type &overall_max_norm_squared;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member 'overall_max_norm_squared' of type 'default_type &' (aka 'double &') is a reference [cppcoreguidelines-avoid-const-or-ref-data-members]

  default_type &overall_max_norm_squared;
                ^

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we've used this approach throughout the code base, but I think it may have been criticised at some point. Is there something better, even if only for my own knowledge when I need to do similar in the future? My naive instinct would be std::shared_ptr<default_type>, but there's lots in the language I don't know about.

private:
default_type &overall_max_norm_squared;
default_type local_max_norm_squared;
inline static std::mutex mutex;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'mutex' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]

  inline static std::mutex mutex;
                           ^

@Lestropie
Copy link
Member

Even if the fault was discovered on dev, it would nevertheless be preferable given that it is a bug fix to be ported to master. Could still use this PR as it is, just replicate on master and then when master has to be merged back in to dev resolve the conflict by keeping these contents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants