Решение на упр.09 задача 1 от Милен Хаджиев

Обратно към всички решения

Към профила на Милен Хаджиев

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 5 успешни тест(а)
  • 0 неуспешни тест(а)

Код

use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex, RwLock};
use std::hash::{Hash, Hasher};
#[derive(Debug, Clone, Eq)]
pub struct Id {
event: String,
value: u64,
}
impl PartialEq for Id {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl Hash for Id {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state);
}
}
impl Id {
fn new(event: &str, value: u64) -> Self {
Id {
event: event.to_string(),
value,
}
}
}
struct EventCallbacks<S> {
callbacks: Mutex<HashMap<Id, Box<dyn FnMut(&mut S) + Send>>>,
}
impl<S> EventCallbacks<S> {
fn new() -> Self {
EventCallbacks {
callbacks: Mutex::new(HashMap::new()),
}
}
}
struct Inner<S> {
next_id: AtomicU64,
events: RwLock<HashMap<String, Arc<EventCallbacks<S>>>>,
}
impl<S> Inner<S> {
fn new() -> Self {
Inner {
next_id: AtomicU64::new(1),
events: RwLock::new(HashMap::new()),
}
}
}
pub struct EventDispatcher<S> {
inner: Arc<Inner<S>>,
}
impl<S> EventDispatcher<S> {
pub fn new() -> Self {
EventDispatcher {
inner: Arc::new(Inner::new()),
}
}
pub fn on(
&self,
event: &str,
callback: Box<dyn FnMut(&mut S) + Send>,
) -> Id {
let id_value = self.inner.next_id.fetch_add(1, Ordering::SeqCst);
let id = Id::new(event, id_value);
let needs_insert = {
let events_read = self.inner.events.read().unwrap();
!events_read.contains_key(event)
};
if needs_insert {
let mut events_write = self.inner.events.write().unwrap();
events_write.entry(event.to_string())
.or_insert_with(|| Arc::new(EventCallbacks::new()));
}
let events_read = self.inner.events.read().unwrap();
if let Some(event_callbacks) = events_read.get(event) {
let mut callbacks = event_callbacks.callbacks.lock().unwrap();
callbacks.insert(id.clone(), callback);
}
id
}
pub fn off(
&self,
id: Id,
) -> Option<Box<dyn FnMut(&mut S) + Send>> {
let events_read = self.inner.events.read().unwrap();
if let Some(event_callbacks) = events_read.get(&id.event) {
let mut callbacks = event_callbacks.callbacks.lock().unwrap();
callbacks.remove(&id)
} else {
None
}
}
pub fn emit(&self, event: &str, state: &mut S) {
let event_callbacks_arc = {
let events_read = self.inner.events.read().unwrap();
events_read.get(event).cloned()
};
if let Some(event_callbacks) = event_callbacks_arc {
let mut callbacks = event_callbacks.callbacks.lock().unwrap();
for (_, callback) in callbacks.iter_mut() {
callback(state);
}
}
}
}
impl<S> Clone for EventDispatcher<S> {
fn clone(&self) -> Self {
EventDispatcher {
inner: Arc::clone(&self.inner)
}
}
}
unsafe impl<S> Send for EventDispatcher<S> {}
unsafe impl<S> Sync for EventDispatcher<S> {}
//Кога да използваме или да не използваме типове, които се държат като handle-и:
// - използваме ги когато няколко части от кода/или няколко нишки трябва да достъпват един и същ ресурс, когато създаваме връзка с база данни, да се създаде сокет на даден,
// който да слуша и приема заявки
// - когато уникален ownership е достатъчен или става въпрос за малки, копируеми типове

Лог от изпълнението

Updating crates.io index
     Locking 17 packages to latest compatible versions
   Compiling proc-macro2 v1.0.103
   Compiling quote v1.0.42
   Compiling unicode-ident v1.0.22
   Compiling futures-sink v0.3.31
   Compiling futures-core v0.3.31
   Compiling futures-channel v0.3.31
   Compiling memchr v2.7.6
   Compiling syn v2.0.111
   Compiling futures-task v0.3.31
   Compiling futures-io v0.3.31
   Compiling pin-project-lite v0.2.16
   Compiling pin-utils v0.1.0
   Compiling slab v0.4.11
   Compiling solution v0.1.0 (/tmp/d20251211-1757769-1jnyqio/solution)
   Compiling futures-macro v0.3.31
   Compiling futures-util v0.3.31
   Compiling futures-executor v0.3.31
   Compiling futures v0.3.31
    Finished `test` profile [unoptimized + debuginfo] target(s) in 8.99s
     Running tests/solution_test.rs (target/debug/deps/solution_test-ee0783488e12dce9)

running 5 tests
test solution_test::test_basic_run2 ... ok
test solution_test::test_basic_run1 ... ok
test solution_test::test_multithreaded_run1 ... ok
test solution_test::test_multithreaded_run2 ... ok
test solution_test::test_reentrant_run ... ok

test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

История (1 версия и 0 коментара)

Милен качи първо решение на 10.12.2025 20:05 (преди около 2 месеца)