2013-08-22 2 views
0

boost :: call_once가 구현되는 방식은 무엇입니까?double 체크 된 잠금 패턴을 통한 call_once 구현

이중 확인 잠금 패턴을 사용합니까?

Qt 또는 POCO 라이브러리에 상응하는 구현이 있습니까?

+0

당신이 알고있는 진짜처럼 .. 스레드간에 동기화하는 좋은 없다 '더블 패턴 잠금 확인' ? –

+0

난 POCO 스레드를하지 않을 것이다 –

+0

문제는 멀티 스레드 환경에서 싱글 톤 패턴을 구현해야한다는 것이다. 두 번 체크 된 잠금 패턴 (그리고 그 비 효율성)에 대한 분석을했고 call_once를 높였다. 부스트 라이브러리를 사용하지 않아도됩니다. 그래서 구현이 필요합니다. –

답변

1

나는이 오래된 질문을 우연히 만났습니다. 4 년 후에는 아마 더 이상 당신의 경우에는 흥미롭지 않을 것입니다.하지만 샘플 구현에는 여전히 가치가있을 수 있습니다.

DCLP가 손상되었다는 설명 부분의 주장과는 달리 필요한 원자 적 유형, 연산 및 메모리 장벽을 제공하므로 C++ 11에서는 더 이상 사실이 아닙니다.

최소 구현이므로 반드시 boost 구현이 아닙니다. 예외 동작은 무시됩니다.
my_call_once의 인수 함수를 한 번만 호출 할 수 보장 및 공유 데이터가 제대로 단지 std::call_once

#include <iostream> 
#include <thread> 
#include <mutex> 
#include <atomic> 

class my_once_flag { 
    std::mutex mtx; 
    std::atomic<bool> flg{false}; 

    template<typename Func, typename... Args> 
    friend void my_call_once(my_once_flag&, Func&&, Args&&...); 
}; 

template<typename Func, typename... Args> 
void my_call_once(my_once_flag& flag, Func&& f, Args&&... args) 
{ 
    if (flag.flg.load(std::memory_order_acquire) == false) 
    { 
     std::lock_guard<std::mutex> lck{flag.mtx}; 

     if (flag.flg.load(std::memory_order_relaxed) == true) 
      return; 

     std::forward<Func>(f)(std::forward<Args>(args)...); 

     flag.flg.store(true, std::memory_order_release); 
    } 
} 

void just_once(int i) { std::cout << "once " << i << std::endl; } 

int main() 
{ 
    my_once_flag of; 

    std::thread {[&]{ my_call_once(of, just_once, 1); }}.join(); 
    std::thread {[&]{ my_call_once(of, just_once, 2); }}.join(); 
}