2017-03-20 1 views
1

this file에서 boost::lockfree::detail::freelist 클래스는 free list을 사용하여 잠금없는 데이터 구조 (예 : 대기열)에 대한 저장소를 관리하는 데 사용됩니다. deallocate_impl 메서드는 자유 목록으로 다시 연결하여 노드를 해제하는 데 사용됩니다 (해제 된 노드가 이전 머리를 대체하는 자유 목록의 새로운 머리가됩니다). 이 메서드는 스레드로부터 안전하고 lock-free로되어 있습니다. 내 의견이 의심스러운 코드를 지적하는 주석이 하나 개의 인스턴스의 원래의 소스 코드는 여기에 중복 (잠재적 인 버그?) :이것이 boost :: lockfree :: detail :: freelist의 버그가 아니라면, 여기서 무엇을 놓치고 있습니까?

void deallocate_impl (index_t index) 
{ 
    freelist_node * new_pool_node = 
      reinterpret_cast<freelist_node*>(NodeStorage::nodes() + index); 

    // Shouldn't this line be placed inside the loop? 
    // The loop continues as long as the compare-and-exchange fails, 
    // which happens if the pool head has been concurrently updated. 
    // In that case, we MUST reload the new value of "pool_" to 
    // reuse its tag, link the new free-list head to it and 
    // compare against in the compare_and_exchange call. 
    tagged_index old_pool = pool_.load(memory_order_consume); 

    for(;;) { 
     // The old pool head tag is reused here without causing 
     // any ABA problems. However, if "index" is the same as 
     // old_pool.get_index(), a self-reference is written. 
     tagged_index new_pool (index, old_pool.get_tag()); 
     new_pool_node->next.set_index(old_pool.get_index()); 

     if (pool_.compare_exchange_weak(old_pool, new_pool)) 
      return; 
    } 
} 

나는 부스트 1.62.0 너무

+1

C++의 큰 단점 중 하나는 호출 사이트에서 참조 구성원이 통과하지 못했음을 나타냅니다. 교환을 통해 예상되는 값을 현재 표시된 것으로 업데이트합니다. – Voo

+0

고맙습니다. @Voo. –

답변

2
에서 같은 구현을 보았다

비교 및 ​​교환이 실패 할 때까지 루프가 계속됩니다. 이는 풀 헤드가 동시에 업데이트 된 경우 발생합니다. 이 경우, 우리는

compare_exchange_weak()

는 각 호출 후 old_poolpool_의 이전 값을 기록 ... 그 태그를 재사용하는 "pool_"의 새로운 가치를 다시로드해야합니다. Documentation for compare_exchange_weak(). 그 인덱스 노드가 아직없는 목록으로 이동하지 이후

는 그러나, "인덱스"

이 아마 일어나지 않을 수 있습니다 ... old_pool.get_index()와 동일합니다.

+0

감사합니다. @Grisha. 나는 질문을 게시하기 전에 문서를 찾았어야했다. –

관련 문제