2012-09-17 2 views
0

참고 사항 -이 빌드는 VS2008/VS2010 빌드 용입니다. 어떤 11 가지 구성도 사용할 수 없습니다.연동이 있습니까? C++

일부 게시자의 수신자가 있습니다. 내 게시자 구독자 포인터의 컨테이너가 있습니다. 내 void detach (ISubscriber *)에서는 구독자 목록을 잠그는 대신에 해당 구독자에게 더 좋은 단어가 없기 때문에 포인터를 "NULL"처리합니다.

//My container in the publisher. Inserts to not invalidate, removals only invalidate iterators pointing to the removed element, for this reason we NULL 
Container<ISubscriber *> myContainer; 

Now in the publisher... 
void NotifySubscribers(){ 
    foreach(subscriber in container){ 
     if(subscriber)//This is my problem 
     subscriber->notify() 
    } 
} 

라인 3 - 포인터가 테스트되었고 유효한 개체를 가리키고 있습니다. 줄 4가 실행되기 전에 다른 스레드가 구독자를 NULL로 지정합니다. 줄 4 - 붐.

내 질문은 테스트 및 호출 원자 같은 일종의 연동 뭔가 사용할 수있는 방법이 있습니다.

소멸자의 레퍼런스 카운트 된 객체에 대해, 이런 일이 기준 카운터가 감소하고 오직 다음의 경우 0과 같지 제로 automically,에 대해 테스트되고, 여기서

RefCountObject::~RefCountObject(){ 
    if(InterlockedDecrement(&m_count) == 0) 
     delete m_data; 
} 

작동 데이터는 해제된다.

포인터의 유효성을 기반으로 함수를 호출 할 때이 작업을 수행 할 수있는 방법이 있습니까?

편집 1 : 의견을 바탕으로 조금 명확히하고 답장을 보내 주셔서 감사드립니다. 게시자는 구독자의 "메모리 해제"에 대해 책임지지 않으므로 누출이 발생하지 않습니다. 알림 후에 게시자는 구독자를 삭제하여 컨테이너를 정리하는 루프를 진행합니다.

이제 구독자 자체에 대해서. 그들이 분리되면, 그들은 출판사의 말을 듣지 않게됩니다. 그들 자신은 정적 인 물체에서 살 것입니다 (이것은 우리가 요구하는 계약입니다). 왜? 우리는 통보하는 동안 자물쇠를 잡을 여유가 없기 때문에. 유일한 다른 옵션은 향후 버전 관리로 인해이 DLL에 통합되지 않기로 결정된 Share_Ptr을 사용하는 것이 었습니다.

shared_ptr로 작성된 손을 만들었지 만 리소스 관리 클래스에서 래핑되지 않은 객체에 대한 참조가 같은 함정에 빠지면 구독자가해야 할 "요구 사항"을 밀어 넣어야합니다. 해당 가입자의 구현 내에서 매달려있는 참조를 언급하지 않도록하십시오.

다시 말해서 구독자는 "릴리스"할 수 없으며 현재는이를 사용하는 모든 클라이언트가 정적 개체입니다. 우리는 미래를 바라보고있었습니다. 일부 사용자는 레거시 앱이므로 enabled_shared_from_this 등을 가져 오는 것이 쉽지 않습니다.

+1

컨테이너를 걷는 동안 구독자를 삭제할 수 있다면 간단한 원자 테스트보다 더 높은 수준의 동기화/수명 관리가 필요합니다. 참조 카운터와 같습니다 (예 : 공유 포인터로 래핑 될 수 있음). *'notify()'가 실행되는 동안 * 삭제되는 객체로부터 보호해야합니다. –

+0

ISubscriber 객체가 누출 될 수 있습니까? –

+0

정말로 (뮤텍스를 사용하는 대신) 이것을 위해 원자가 실제로 필요합니까? Lockfree 구조는 좀 더 복잡한 구조에 특히 적합하기 때문에 악명이 높지 않으므로 흔히 노력할 가치가 없습니다. 이 경우에는 원자 테스트와 호출 (존재한다면)이 도움이되지 않을 것입니다. 왜냐하면 스레드가'notify' 안에있는 동안'subscriber'가 삭제되지 않는다고 보장 할 수 없기 때문입니다. – Grizzly

답변

3

내가 테스트 및 전화와 같은 일종의 인터록을 사용할 수있는 방법이 있습니다.

시험을 위해 방법이있을 것입니다. 포인터를 비교하기 만하면됩니다.

전화를 걸려면 의심 스럽습니다. 통화와 관련하여 중요한 부분 인 경비가 필요합니다.

+0

우리는 중요한 부분을 피하려고 노력하고 있는데, 이것은 질문의 동기입니다. 그것은 아주 좋지 않을 수도 있습니다. 감사합니다 – clanmjc

+0

우리 모두는 특정 범위로 그들을 피하려고합니다. 그러나 모든 것이 원자 적으로 이루어질 수는 없습니다. 스핀 카운트가있는 크리티컬 섹션을 사용하여 프로파일 링을 수행하십시오. 크리티컬 섹션은 잠글 때 "시간이 많이 걸립니다". 자유롭게 통과 할 수 있고 앱에서 대부분 발생합니다. 비용은 생각보다 적을 수 있습니다. –

+0

들려요. 우리는 알림 호출 중에 잠금을 유지할 수 없으며 리소스를 잠그고 복사하고 잠금을 해제하고 알림을 보내고 정리해야 할 수도 있습니다. 다시 이것을 피하려고 노력하지만 가능하지 않을 수도 있습니다. Spin Count, 시간에 엄지 손가락의 규칙이 있습니까? 자신이 사용하고있는 마법의 숫자가 있습니까? 감사합니다 – clanmjc

0

"스마트 포인터"전략을 사용하여 지연된 포인터의 널링을 수행 할 수 있습니다. 누군가가 포인터에 대한 참조를 가지고 있고, 연동 된 참조 카운트에 의해 결정되면 포인터를 유효하게 유지하십시오. 카운트가 0이되면 null이되는 것이 안전합니다.