linux: implement dispatcher, add dummy textsystem

This commit is contained in:
Dzmitry Malyshau
2024-02-01 21:28:16 -08:00
parent d675abf70c
commit ca62d22147
10 changed files with 194 additions and 14 deletions
@@ -0,0 +1,97 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
use crate::{PlatformDispatcher, TaskLabel};
use async_task::Runnable;
use parking::{Parker, Unparker};
use parking_lot::Mutex;
use std::{
panic, thread,
time::{Duration, Instant},
};
pub(crate) struct LinuxDispatcher {
parker: Mutex<Parker>,
timed_tasks: Mutex<Vec<(Instant, Runnable)>>,
main_sender: flume::Sender<Runnable>,
main_receiver: flume::Receiver<Runnable>,
background_sender: flume::Sender<Runnable>,
background_thread: thread::JoinHandle<()>,
main_thread_id: thread::ThreadId,
}
impl Default for LinuxDispatcher {
fn default() -> Self {
Self::new()
}
}
impl LinuxDispatcher {
pub fn new() -> Self {
let (main_sender, main_receiver) = flume::unbounded::<Runnable>();
let (background_sender, background_receiver) = flume::unbounded::<Runnable>();
let background_thread = thread::spawn(move || {
for runnable in background_receiver {
let _ignore_panic = panic::catch_unwind(|| runnable.run());
}
});
LinuxDispatcher {
parker: Mutex::new(Parker::new()),
timed_tasks: Mutex::new(Vec::new()),
main_sender,
main_receiver,
background_sender,
background_thread,
main_thread_id: thread::current().id(),
}
}
}
impl PlatformDispatcher for LinuxDispatcher {
fn is_main_thread(&self) -> bool {
thread::current().id() == self.main_thread_id
}
fn dispatch(&self, runnable: Runnable, _: Option<TaskLabel>) {
self.background_sender.send(runnable).unwrap();
}
fn dispatch_on_main_thread(&self, runnable: Runnable) {
self.main_sender.send(runnable).unwrap();
}
fn dispatch_after(&self, duration: Duration, runnable: Runnable) {
let moment = Instant::now() + duration;
let mut timed_tasks = self.timed_tasks.lock();
timed_tasks.push((moment, runnable));
timed_tasks.sort_unstable_by(|&(ref a, _), &(ref b, _)| b.cmp(a));
}
fn tick(&self, background_only: bool) -> bool {
let mut ran = false;
if self.is_main_thread() && !background_only {
for runnable in self.main_receiver.try_iter() {
runnable.run();
ran = true;
}
}
let mut timed_tasks = self.timed_tasks.lock();
while let Some(&(moment, _)) = timed_tasks.last() {
if moment <= Instant::now() {
let (_, runnable) = timed_tasks.pop().unwrap();
runnable.run();
ran = true;
}
}
ran
}
fn park(&self) {
self.parker.lock().park()
}
fn unparker(&self) -> Unparker {
self.parker.lock().unparker()
}
}
+10 -5
View File
@@ -2,8 +2,9 @@
use crate::{
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
Keymap, Menu, PathPromptOptions, Platform, PlatformDisplay, PlatformInput,
PlatformTextSystem, PlatformWindow, Result, SemanticVersion, Task, WindowOptions,
ForegroundExecutor, Keymap, LinuxDispatcher, Menu, PathPromptOptions, Platform,
PlatformDisplay, PlatformInput, PlatformTextSystem, PlatformWindow, Result, SemanticVersion,
Task, WindowOptions,
};
use futures::channel::oneshot;
@@ -17,10 +18,11 @@ use std::{
};
use time::UtcOffset;
pub(crate) struct LinuxPlatform(Mutex<LinuxPlatformState>);
pub(crate) struct LinuxPlatformState {
background_executor: BackgroundExecutor,
foreground_executor: ForegroundExecutor,
}
impl Default for LinuxPlatform {
@@ -31,18 +33,21 @@ impl Default for LinuxPlatform {
impl LinuxPlatform {
pub(crate) fn new() -> Self {
let dispatcher = Arc::new(LinuxDispatcher::new());
Self(Mutex::new(LinuxPlatformState {
background_executor: BackgroundExecutor::new(dispatcher.clone()),
foreground_executor: ForegroundExecutor::new(dispatcher),
}))
}
}
impl Platform for LinuxPlatform {
fn background_executor(&self) -> BackgroundExecutor {
unimplemented!()
self.0.lock().background_executor.clone()
}
fn foreground_executor(&self) -> crate::ForegroundExecutor {
unimplemented!()
self.0.lock().foreground_executor.clone()
}
fn text_system(&self) -> Arc<dyn PlatformTextSystem> {