2016-10-26 8 views
0

나는 Vec<CacheChange>을 공유했습니다. 새로운 CacheChange이 쓰여질 때마다 나는 독자들을 깨우고 싶다. 프리디 케이트/상황이 준비되었을 때, 즉 Vec이 수정되었을 때 Condvar이 시그널링에 좋다는 것을 기억합니다.Condvar 및 Mutex로 변경 사항을 모니터링하는 방법

그래서 Vec을 소유하고 waitlock 의미 체계를 제공하기 위해 Monitor 추상화를 만드는 데 시간을 보냈습니다.

지금 문제는 Condvar을 언제 재설정해야할지 모르겠다. 독자가 술어를 치고 자물쇠를 들고가는 길에 합당한 시간을주는 좋은 방법은 무엇입니까? 아내를 닫기 전에? 내가 잘못된 방법으로 Condvar에 접근하고 있습니까?

이것은 녹 부호이지만 여러 독자 간의 정확한 동시 액세스/알림을위한 기본 사항에 대한 질문입니다.

pub struct Monitor<T>(
    sync::Arc<MonitorInner<T>> 
); 

struct MonitorInner<T> { 
    data: sync::Mutex<T>, 
    predicate: (sync::Mutex<bool>, sync::Condvar) 
} 

impl<T> Monitor<T> { 
    pub fn wait(&self) -> Result<(),sync::PoisonError<sync::MutexGuard<bool>>> { 
     let mut open = try!(self.0.predicate.0.lock()); 
     while !*open { 
      open = try!(self.0.predicate.1.wait(open)); 
     } 
     Ok(()) 
    } 

    pub fn lock(&self) -> Result<sync::MutexGuard<T>, sync::PoisonError<sync::MutexGuard<T>>> { 
     self.0.data.lock() 
    } 

    pub fn reset(&mut self) -> Result<(),sync::PoisonError<sync::MutexGuard<bool>>> { 
     let mut open = try!(self.0.predicate.0.lock()); 
     *open = false; 
     Ok(()) 
    } 

    pub fn wakeup_all(&mut self) -> Result<(),sync::PoisonError<sync::MutexGuard<bool>>> { 
     let mut open = try!(self.0.predicate.0.lock()); 
     *open = true; 
     self.0.predicate.1.notify_all(); 
     Ok(()) 
    } 
} 

첫 번째 깨우기 호출 후 내 독자는 읽지 못할 수 있습니다. 아마 그들은 술어가 다시 토글 링되는 동안 여전히 데이터 잠금을 유지하고 있기 때문일 것입니다. 필자는 테스트 코드에서 단 한 명의 리더와 한 명의 작가 만 보았습니다.

그런 다음 Monitor을 재설정해야하는 번거 로움이 있습니다. 모든 독자가 데이터를 볼 기회가있는 것이 이상적입니다. 독자가 모니터를 무시하면 교착 상태 문제가 발생할 수 있습니다 (모든 깨우기 호출을 처리해야한다는 보장이 없음).

모니터링 판독기가 계속 서비스되는 동안 새 데이터가 도착하면 시간 초과와 함께 일종의 판독기 추적 시스템을 사용해야하고 데이터를 추적해야합니까? 내가 알아야 할 기존 패러다임이 있습니까?

답변

3

가장 간단한 해결책은 부울 대신 카운터를 사용하는 것입니다.

그런 다음 업데이트가 완료 될 때마다 카운터가 증가합니다. 재설정되지 않으므로 재설정시기는 의문의 여지가 없습니다.

물론 그것은 마지막으로 깨어 난 카운터 값을 독자가 기억해야한다는 것을 의미합니다.

+0

* 재설정되지 않습니다. * 2^32 또는 2^64 씩 증가합니다. 일명 'time_t' 2038 호^_^ – Shepmaster

+0

@Shepmaster : 예, 저는 64 비트 카운터가 1 단위 씩 오버플로 할 수 없기 때문에'AtomicU64 '가 안정적 이었으면합니다. (수학적 경향에 대해서는 600 년이 걸립니다. 1 inc/ns, 또는 5 GHz에서 ~ 120 년)로 오버 플로우됩니다. –

+0

나는 원자 적재를'wait()'에 넣을 수 있었고 재로드 된 카운트가 더 높을 때 쓰레드가 깨어났다. – xrl