упр.09 задача 1
- Краен срок:
- 10.12.2025 23:59
- Точки:
- 5
Имплементирайте event dispatcher.
Класът трябва да поддържа следните методи:
-
on(event, callback)- регистрира подадената callback функция свързана със събититето event. ВръщаId, което уникално идентифицира този callback -
off(id)- премахва и връща предварително регистриран callback по неговотоId -
emit(event, state)- изпълнява всички callback функции регистрирани за даденото събитие. Подава състояниетоstateкато аргумент на всяка callback функция
Класът трябва да поддържа използване в многонишков контекст.
В случая искаме типа EventDispatcher да е лек handle към реалната имплементация (виж отдолу защо).
За имплементацията може да използвате private структура (например Inner).
EventDispatcher държи указател (Arc) към стойност от тип Inner. Или Arc<Mutex<Inner>>, ако искаме да модифицираме състоянието Inner.
EventDispatcher трябва да може да се клонира. Клонирането създава нов handle към същата вътрешна стойност.
EventDispatcher трябва да може да се използва от няколко нишки едновременно.
Идеята е да клонираме и подадем по един handle на всяка нишка, през този handle нишките трябва да могат да извикват on, off и emit паралелно една с друга.
Добавете необходимите ограничения (trait bounds), така че кода да позволява използването от множество нишки.
Съвет: направете си пример (или ползвайте базовия тест) и вижте къде ще ви се скара компилатора.
use std::sync::{Arc, Mutex};
pub struct Id {
/* каквито данни ви трябват */
}
pub struct EventDispatcher<S> {
inner: Arc<Mutex</* ...data... */>>,
}
impl<S> EventDispatcher<S> {
pub fn new() -> Self {
todo!()
}
pub fn on(
&self,
event: &str,
callback: Box<dyn FnMut(&mut S) /* + ... */>,
) -> Id {
todo!()
}
pub fn off(
&self,
id: Id,
) -> Option<Box<dyn FnMut(&mut S) /* + ... */>> {
todo!()
}
pub fn emit(&self, event: &str, state: &mut S) {
todo!()
}
}
impl<S> Clone for EventDispatcher<S> {
fn clone(&self) -> Self {
EventDispatcher { inner: Arc::clone(&self.inner) }
}
}
Бонус (1т): Какво ще стане, ако от callback функция извикаме някой от on или off методите?
Погрижете се да може от callback за събитие event="foo" да може да се извикват on и off за друго събитие event="bar", без това да причинява deadlock.
Подсказка: за целта ще трябва да направите две неща:
- да имате отделен мутекс (
Mutex/RwLock) за всеки отделен event, в допълнение към глобалния мутекс върху цялата структура - при извикване на callback функциите за едно събитие, да държите заключен само мутекса на това събитие и да не държите заключен мутекса върху цялата структура.
Кога да използваме или да не използваме типове, които се държат като handle-и:
TODO
Задължително прочетете (или си припомнете): Указания за предаване на домашни
Погрижете се решението ви да се компилира с базовия тест:
