Для библиотеки, которую мне нужно написать, у меня есть структура, представляющая службу, написанную на C:
struct RustService {
id: u8, /* it's me setting the id in the first place */
service: *mut c_void,
status: *mut c_void,
value: Option<u32>,
/* various fields here */
}
impl RustService {
fn new() -> /* can be wrapped*/RustService {
/* ... */
}
}
У меня есть несколько обратных вызовов, переданных в C библиотеку, например:
#[no_mangle]
extern "C" fn callback_handle(service: *mut c_void, size: *mut u32, buffer: *mut u8)
{
let id: u8 = c_library_get_id(service);
let instance: &mut RustService = /* get that from static container based on id */
if size = mem::size_of::<u32>() as u32 {
let value = buffer.cast::<u32>().read();
instance.value = Some(value);
} else {
panic!("Invalid length passed.");
}
}
То, что я ищу, - это проверенная / хорошая практика, которая применима здесь, которая работает, не вызывая взаимоблокировки, когда мой обратный вызов может ссылаться на правильный экземпляр, используя библиотеку в C. Эта библиотека в C может запускать несколько экземпляров, но это не так важно. В качестве альтернативы я могу принять шаблон одного экземпляра, который будет работать в этом случае.
Другие методы RustService
должны будут вызывать, например, функцию со следующей подписью (из bindgen):
extern "C" pub fn clibCoreWork(status: *mut clibStatus, service: *mut clibService) -> u32;
и внутренности этой функции могут решить вызвать эти обратные вызовы, упомянутые выше.
Подход, который я использовал, убивает меня в ногу, поскольку внутренние взаимоблокировки Mutex даже в одиночном thread:
lazy_static! {
static ref MY_INSTANCES: Mutex<HashMap<u8, Weak<Mutex<RustService>>>> = Mutex::new(HashMap::new());
}
Я откопал inte rnet, но товарищи Rustaceans, похоже, ничего не писали о такой проблеме.
Примечание: Я не могу изменить базовый типы в библиотеке C, которую я использую. В идеальном мире это позволило бы мне хранить указатель на пользовательские данные, и я бы жестоко преобразовал его в изменяемую ссылку в небезопасном коде.