2015-01-27 6 views
0
내가 함수를 작성하려면

는 다음과 같이 호출 할 :구현 "이동"스레드 의미

let k = recv("address"); 
println!("{}",k); 

을하고 다른 스레드가 message을보고

send("message","address"); 

.

특히 메시지가 클 수 있으므로 메시지를 전송하기 위해 "이동"또는 "제로 복사"의미를 원합니다.

  1. 글로벌 되세요 힙,
  2. 쓰기 포인터 메모리에 일부 메모리 위치를 "주소"를 매핑 스레드 해시 맵에 메시지를 할당 :

    C에서

    , 해결책은 무엇인가이다 위치를 보내고 세마포어를 사용하여 수신기를 깨우십시오.

  3. 수신시 메모리 위치에서 포인터를 읽고 새 메시지를 처리하기 위해 세마포를 기다립니다.

하지만 다른 SO 질문에 따라 단계 # 2 "sounds like a bad idea". 그래서 저는이 문제에 접근하기 위해 좀 더 녹슨 관용적 인 방법을보고 싶습니다.

답변

2

이런 종류의 이동 의미를 자동으로 얻고 큰 값을 Box에 배치하여 (즉, 힙에 할당하여) 가벼운 이동을 얻습니다. 스레드의 해시 맵으로 (이이 개선 될 수 여러 가지 방법이 있어요) type ConcurrentHashMap<K, V> = Mutex<HashMap<K, V>>;를 사용하여, 하나가있을 수 있습니다 : 그 코드가 글로벌 해시 맵을 달성하기 위해 lazy_static! 매크로를 사용

use std::collections::{HashMap, RingBuf}; 
use std::sync::Mutex; 

type ConcurrentHashMap<K, V> = Mutex<HashMap<K, V>>; 

lazy_static! { 
    pub static ref MAP: ConcurrentHashMap<String, RingBuf<String>> = { 
     Mutex::new(HashMap::new()) 
    } 
} 

fn send(message: String, address: String) { 
    MAP.lock() 
     // find the place this message goes 
     .entry(address) 
     .get() 
     // create a new RingBuf if this address was empty 
     .unwrap_or_else(|v| v.insert(RingBuf::new())) 
     // add the message on the back 
     .push_back(message) 
} 
fn recv(address: &str) -> Option<String> { 
    MAP.lock() 
     .get_mut(address) 
     // pull the message off the front 
     .and_then(|buf| buf.pop_front()) 
} 

을 (로컬 객체를 사용하는 것이 더 좋을 수 Arc<ConcurrentHashMap<...>, fwiw, 전역 상태는 프로그램 동작에 대한 추론을 어렵게 만들 수 있기 때문에). 또한 RingBuf을 큐로 사용하므로 메시지는 주어진 address에 대해 뱅크 업합니다. 한 번에 하나의 메시지 만 지원하려는 경우 유형은 ConcurrentHashMap<String, String> 일 수 있으며 sendMAP.lock().insert(address, message)이고 recvMAP.lock().remove(address)이 될 수 있습니다.

(NB.이 형식을 컴파일하지 않았으므로 유형이 정확하게 일치하지 않을 수 있습니다.)