BONEFLUTE: Hlavni problem je implementace `App`, nevidim moc duvod pro `self: &Rc`, proc ne `&self`? `Rc` je typicky to co pouziva klientsky/uzivatelsky kod, ne implementace. `Rc` je immutable single-threaded reference counted pointer. `RefCell` je pak runtime borrow checker. `Rc` je zero abstraciton, `RefCell` ma overhead (dela borrow checking v runtimeu). Pro to co chces mas vice moznosti:
1. Uzivatel si bude resit borrowing v compile tam. Nepotrebujes ani `Rc`, proste signatury v impl budou:
pub fn new(on_startup: ...) -> Self { /* */}
pub fn run(&self) { /* */}
pub fn add_something(&mut self, x: ...) { /* */ }
2. Uzivatel si bude resit ten borrowing v runtimeu:
// stejne signatury jako v 1.
let app = Rc::new(RefCell::new(App::new()));
app.borrow().run();
app.borrow_mut().add_something(x);
3. Hidnes implementaci a ten runtime borrowing budes delat sam stejne jako ve 2 (hledej "interior mutability"), kde budou trochu jine ty signatiry:
#[derive(Clone)]
struct App {
callback: Rc<RefCell<Callback>>
}
pub fn new(on_startup: ...) -> Self { Self { callback: Rc::new(RefCell::new(on_startup)) } }
pub fn run(&self) { self.callback.borrow()... } // predpoklad je, ze callback je `Fn` nebo obdoba
pub fn add_something(&self, x: ...) { self.callback.borrow_mut()... } // <-- povsimni si, ze toto taky bere &self a ne `&mut self`
Samozrejme nejlepsi je 1. Ty ostatni maji runtime overhead (borrow checking pri runtime). Zejmena jelikoz to mas single-threaded, tak neni moc duvod resit reference counting, pokud `App` nekde neskladujes jako member promennou. V kazdem pripade nejlepsi performance (za cenu nejake ergonomie) m a i v takovem pripade nasledujici pattern:
struct App { pub callback: ... }
type Callabck = ...;
impl App {
pub fn run(callback: &Callback)
pub fn add_something: &mut Callback, x: ...);
}
fn main() {
let app = App { callback: ... };
App::run(&app.callback);
App::add_something(&mut app.callback, x);
}
Tahle varianta presouva ten borrow checking zpet do compile time a je vhodna tam, kde ten ownership neni uplne jasny a kde to chces volat z ruznych mist. Takhle se vlatne pise cecko (minus prave ten borrow checking).