我正在使用一个库,它为我提供了创建对象并向其事件分配自定义回调所需的结构和方法。但对于每个回调,我需要跟踪全局或对象范围的状态:哈希图。这个设计的 Rust 方式是什么?我想我可以创建一个包含库对象和哈希图的新结构,但不确定如何获取回调来修改该结构状态
fn fileio_callback(record: &EventRecord, schema_locator: &SchemaLocator) {
//...here i handle the event
//but i also need to access the hashmap
//...
}
struct EtwKernelFileTracker {
trace: KernelTrace,
fileobjects: HashMap<u64, String>,
}
impl EtwKernelFileTracker {
fn new<T>(callback: T) -> EtwKernelFileTracker
where T: FnMut(&EventRecord, &SchemaLocator) + Send + Sync + 'static {
let file_provider = Provider::kernel(&KernelProvider::new(GUID::from("90cbdc39-4a3e-11d1-84f4-0000f80464e3"),EVENT_TRACE_FLAG_FILE_IO|EVENT_TRACE_FLAG_FILE_IO_INIT|EVENT_TRACE_FLAG_DISK_FILE_IO))
.add_callback(callback)
.build();
let kernel_trace = KernelTrace::new()
.named(String::from("file_io"))
.enable(file_provider)
.start_and_process()
.unwrap();
return EtwKernelFileTracker{trace: kernel_trace, fileobjects: HashMap::new()}
}
}
fn main() {
let file_etw = EtwKernelFileTracker::new(fileio_callback);
std::thread::sleep(Duration::new(10, 0));
}
我考虑过将回调放在结构中,但我认为这样做的方式感觉很糟糕,尤其是对于函数输入和特征,而且仍然不确定如何在结构创建时将哈希图传递给回调。我对这门语言很陌生,即使我还很陌生,我想知道设计此类功能的不同且更好的方法。
您正在使用的库 ferrisetw 定义了不可变的回调:
fn process_callback(record: &EventRecord, schema_locator: &SchemaLocator);
如果您需要从该回调中安全地修改某些全局上下文,我建议使用基于互斥体的单例设计模式,使用以下示例:singleton/how-to-create/mutex。
use std::sync::Mutex;
use std::collections::HashMap;
static STATE: Mutex<HashMap<u32, String>> = Mutex::new(HashMap::new());
fn process_callback(record: &EventRecord, schema_locator: &SchemaLocator) {
let mut hashmap = STATE.lock().unwrap();
hashmap.insert(1, "data".into());
}