yandex-writeups/3_1/3practice.md
2025-11-17 07:18:54 +07:00

72 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### **Практическое задание: задачи с таймаутом**
Создайте метод TaskPool::create, которая будет отправлять задачу в канал, но если не получается отправить задачу в канал в течение 100 миллисекунд, возвращается None
```rust
use std::time::{Duration, Instant};
use tokio::{
sync::mpsc::{Receiver, Sender, channel, error::SendError},
time::timeout,
};
struct TaskPool<T> {
tasks: Receiver<T>,
sender: Sender<T>,
}
impl<T> TaskPool<T> {
fn new(queue_size: usize) -> Self {
let (sender, tasks) = channel::<T>(queue_size);
Self { tasks, sender }
}
async fn create(&self, task: T) -> Option<Result<(), SendError<T>>> {
// Напишите свое решение здесь
}
async fn pull_task(&mut self) -> Option<T> {
self.tasks.recv().await
}
}
#[tokio::main]
async fn main() {
let mut tasks = TaskPool::new(2);
assert_eq!(tasks.create(()).await, Some(Ok(())));
assert_eq!(tasks.create(()).await, Some(Ok(())));
let start = Instant::now();
assert_eq!(tasks.create(()).await, None);
let end = start.elapsed();
assert!(end > Duration::from_millis(90));
assert!(end < Duration::from_millis(110));
assert_eq!(tasks.pull_task().await, Some(()));
assert_eq!(tasks.create(()).await, Some(Ok(())));
}
```
### Подсказки
используйте tokio::time::timeout для таймаута
tokio::time::timeout принимает фьючерс для которого нужен таймаут
используйте .send() для отправки значение
обратите внимание, что .send() возвращает фьючерс
Проверьте свой код по чек-листу:
используется tokio::time::timeout
используются асинхронные каналы
все тесты проходят
### **Решение**
```rust
async fn create(&self, task: T) -> Option<Result<(), SendError<T>>> {
let sender = self.sender.send(task);
timeout(Duration::from_millis(100), sender).await.ok()
}
```
Вы знаете про существование таких синхронизационных примитивов в стандартной библиотеке, как Mutex, RwLock, каналы. И в тоже происходит ожидание. Но они блокируют поток, поэтому в tokio есть альтернативы с идентичным интерфейсом, но асинхронным:
У асинхронных мьютекса и RwLock есть преимущество: если фьючерс ожидает лока асинхронного мьютекса, токио будет обратно переключаться на другие фьючерсы. В то время, как синхронные версии будут держать поток и не давать другим фьючерсам исполняться. Для синхронных версий это создает проблему: если MutexGuard пересек границу .await, где, к примеру, ожидается ответ в течение 30 секунд, то другой фьючерс, ожидающий лока мьютекса, будет держать целый поток токио в течение всего этого времени, что приведет к потере производительности. А если рантайм токио будет однопоточным, то программа зависнет навсегда.
после вызова await залочен, что приводит к ожиданию анлока от других