Решение на упр.13 задача 1 от Илиян Гаврилов
Резултати
- 4 точки от тестове
- 0 бонус точки
- 4 точки общо
- 4 успешни тест(а)
- 0 неуспешни тест(а)
Код
use std::sync::{mpsc, Arc, Barrier, Mutex};
use std::thread;
// =========================================================
// 1. JOB TRAIT (НЕ СЕ ПРОМЕНЯ)
// =========================================================
pub trait Job: Send + 'static {
type Output: Send + 'static;
type Error: Send + 'static;
fn run(self) -> Result<Self::Output, Self::Error>;
}
// =========================================================
// 2. ВЪТРЕШНИ СЪОБЩЕНИЯ (НЕ СЕ ПРОМЕНЯ)
// =========================================================
enum Message {
Run(Box<dyn FnOnce() + Send>),
Shutdown,
}
pub struct ThreadPool {
workers: Vec<thread::JoinHandle<()>>,
sender: mpsc::Sender<Message>,
}
impl ThreadPool {
pub fn new(worker_count: usize) -> Self {
let (sender, receiver) = mpsc::channel::<Message>();
let receiver = Arc::new(Mutex::new(receiver));
// Barrier за синхронизация - worker_count + 1 (за main thread)
let barrier = Arc::new(Barrier::new(worker_count + 1));
let mut workers = Vec::with_capacity(worker_count);
for _ in 0..worker_count {
let thread_receiver = Arc::clone(&receiver);
let barrier = Arc::clone(&barrier);
let handle = thread::spawn(move || {
// Сигнализираме, че worker-ът е готов
barrier.wait();
loop {
let message = thread_receiver.lock().unwrap().recv();
match message {
Ok(Message::Run(job)) => {
job();
}
Ok(Message::Shutdown) | Err(_) => {
break;
}
}
}
});
workers.push(handle);
}
// Изчакваме всички workers да са готови
barrier.wait();
Self { workers, sender }
}
pub fn submit<J>(&self, job: J) -> mpsc::Receiver<Result<J::Output, J::Error>>
where
J: Job,
{
let (result_sender, result_receiver) = mpsc::channel();
let job_wrapper = Box::new(move || {
let result = job.run();
let _ = result_sender.send(result);
});
self.sender
.send(Message::Run(job_wrapper))
.expect("ThreadPool channel closed unexpectedly");
result_receiver
}
}
// =========================================================
// 4. ГРАЦИОЗНО СПИРАНЕ
// =========================================================
impl Drop for ThreadPool {
fn drop(&mut self) {
for _ in 0..self.workers.len() {
let _ = self.sender.send(Message::Shutdown);
}
for worker in self.workers.drain(..) {
let _ = worker.join();
}
}
}
Лог от изпълнението
Updating crates.io index
Locking 46 packages to latest compatible versions
Compiling proc-macro2 v1.0.106
Compiling libc v0.2.182
Compiling unicode-ident v1.0.23
Compiling quote v1.0.44
Compiling syn v2.0.115
Compiling parking_lot_core v0.9.12
Compiling pin-project-lite v0.2.16
Compiling futures-sink v0.3.31
Compiling futures-core v0.3.31
Compiling futures-channel v0.3.31
Compiling smallvec v1.15.1
Compiling memchr v2.8.0
Compiling futures-task v0.3.31
Compiling slab v0.4.12
Compiling futures-io v0.3.31
Compiling pin-utils v0.1.0
Compiling scopeguard v1.2.0
Compiling cfg-if v1.0.4
Compiling lock_api v0.4.14
Compiling errno v0.3.14
Compiling signal-hook-registry v1.4.8
Compiling parking_lot v0.12.5
Compiling socket2 v0.6.2
Compiling mio v1.1.1
Compiling futures-macro v0.3.31
Compiling tokio-macros v2.6.0
Compiling futures-util v0.3.31
Compiling bytes v1.11.1
Compiling tokio v1.49.0
Compiling futures-executor v0.3.31
Compiling futures v0.3.31
Compiling solution v0.1.0 (/tmp/d20260214-4108951-1l5wmlr/solution)
Finished `test` profile [unoptimized + debuginfo] target(s) in 18.60s
Running tests/solution_test.rs (target/debug/deps/solution_test-24c102a0f7d8d43b)
running 4 tests
test solution_test::test_scheduling ... ok
test solution_test::test_jobs_run_in_parallel ... ok
test solution_test::test_submit_recursive ... ok
test solution_test::test_submit_queue ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.20s
