feat: Switch from smol runtime to tokio

This commit is contained in:
Michael Aaron Murphy 2022-03-27 17:38:37 +02:00 committed by Michael Murphy
parent 4153f9f060
commit dbfb3921ae
23 changed files with 242 additions and 235 deletions

178
Cargo.lock generated
View file

@ -62,17 +62,6 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "async-fs"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b3ca4f8ff117c37c278a2f7415ce9be55560b846b5bc4412aaa5d29c1c3dae2"
dependencies = [
"async-lock",
"blocking",
"futures-lite",
]
[[package]] [[package]]
name = "async-io" name = "async-io"
version = "1.6.0" version = "1.6.0"
@ -101,17 +90,6 @@ dependencies = [
"event-listener", "event-listener",
] ]
[[package]]
name = "async-net"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5373304df79b9b4395068fb080369ec7178608827306ce4d081cba51cac551df"
dependencies = [
"async-io",
"blocking",
"futures-lite",
]
[[package]] [[package]]
name = "async-oneshot" name = "async-oneshot"
version = "0.5.0" version = "0.5.0"
@ -131,23 +109,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "async-process"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6"
dependencies = [
"async-io",
"blocking",
"cfg-if",
"event-listener",
"futures-lite",
"libc",
"once_cell",
"signal-hook",
"winapi",
]
[[package]] [[package]]
name = "async-recursion" name = "async-recursion"
version = "0.3.2" version = "0.3.2"
@ -200,12 +161,6 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "atomic-waker"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -230,20 +185,6 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "blocking"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc"
dependencies = [
"async-channel",
"async-task",
"atomic-waker",
"fastrand",
"futures-lite",
"once_cell",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.9.1" version = "3.9.1"
@ -784,7 +725,7 @@ dependencies = [
"cfg-if", "cfg-if",
"js-sys", "js-sys",
"libc", "libc",
"wasi", "wasi 0.10.2+wasi-snapshot-preview1",
"wasm-bindgen", "wasm-bindgen",
] ]
@ -1171,6 +1112,29 @@ version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "mio"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
dependencies = [
"libc",
"log",
"miow",
"ntapi",
"wasi 0.11.0+wasi-snapshot-preview1",
"winapi",
]
[[package]]
name = "miow"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "nanorand" name = "nanorand"
version = "0.7.0" version = "0.7.0"
@ -1203,6 +1167,15 @@ dependencies = [
"memoffset", "memoffset",
] ]
[[package]]
name = "ntapi"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.13.1" version = "1.13.1"
@ -1404,13 +1377,14 @@ dependencies = [
name = "pop-launcher" name = "pop-launcher"
version = "1.1.1" version = "1.1.1"
dependencies = [ dependencies = [
"blocking",
"const_format", "const_format",
"dirs 4.0.0", "dirs 4.0.0",
"futures", "futures",
"serde", "serde",
"serde_json", "serde_json",
"serde_with", "serde_with",
"tokio",
"tokio-stream",
] ]
[[package]] [[package]]
@ -1419,7 +1393,7 @@ version = "1.1.1"
dependencies = [ dependencies = [
"pop-launcher-plugins", "pop-launcher-plugins",
"pop-launcher-service", "pop-launcher-service",
"smol", "tokio",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
] ]
@ -1446,9 +1420,9 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"slab", "slab",
"smol",
"strsim", "strsim",
"sysfs-class", "sysfs-class",
"tokio",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
"url", "url",
@ -1463,9 +1437,7 @@ name = "pop-launcher-service"
version = "1.1.1" version = "1.1.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-io",
"async-oneshot", "async-oneshot",
"async-process",
"async-trait", "async-trait",
"flume", "flume",
"futures", "futures",
@ -1479,8 +1451,9 @@ dependencies = [
"serde_json", "serde_json",
"serde_with", "serde_with",
"slab", "slab",
"smol",
"strsim", "strsim",
"tokio",
"tokio-stream",
"toml", "toml",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
@ -1775,16 +1748,6 @@ dependencies = [
"lazy_static", "lazy_static",
] ]
[[package]]
name = "signal-hook"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.0" version = "1.4.0"
@ -1817,24 +1780,6 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "smol"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85cf3b5351f3e783c1d79ab5fc604eeed8b8ae9abd36b166e8b87a089efd85e4"
dependencies = [
"async-channel",
"async-executor",
"async-fs",
"async-io",
"async-lock",
"async-net",
"async-process",
"blocking",
"futures-lite",
"once_cell",
]
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.4" version = "0.4.4"
@ -1949,6 +1894,45 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
dependencies = [
"bytes 1.1.0",
"libc",
"memchr",
"mio",
"once_cell",
"pin-project-lite",
"signal-hook-registry",
"tokio-macros",
"winapi",
]
[[package]]
name = "tokio-macros"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio-stream"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.8" version = "0.5.8"
@ -2127,6 +2111,12 @@ version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.79" version = "0.2.79"

View file

@ -11,10 +11,17 @@ edition = "2018"
members = ["bin", "plugins", "service"] members = ["bin", "plugins", "service"]
[dependencies] [dependencies]
blocking = "1.2.0"
const_format = "0.2.22" const_format = "0.2.22"
dirs = "4.0.0" dirs = "4.0.0"
futures = "0.3.21" futures = "0.3.21"
serde = { version = "1.0.136", features = ["derive"] } serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79" serde_json = "1.0.79"
serde_with = "1.12.0" serde_with = "1.12.0"
[dependencies.tokio]
version = "1.17.0"
features = ["io-std", "io-util"]
[dependencies.tokio-stream]
version = "0.1.8"
features = ["io-util"]

View file

@ -10,6 +10,9 @@ publish = false
[dependencies] [dependencies]
pop-launcher-plugins = { path = "../plugins" } pop-launcher-plugins = { path = "../plugins" }
pop-launcher-service = { path = "../service" } pop-launcher-service = { path = "../service" }
smol = "1.2.5"
tracing = "0.1.32" tracing = "0.1.32"
tracing-subscriber = { version = "0.3.9", features = ["env-filter"] } tracing-subscriber = { version = "0.3.9", features = ["env-filter"] }
[dependencies.tokio]
version = "1.17.0"
features = ["rt"]

View file

@ -3,10 +3,10 @@
use pop_launcher_plugins as plugins; use pop_launcher_plugins as plugins;
use pop_launcher_service as service; use pop_launcher_service as service;
use smol::block_on;
use std::io; use std::io;
fn main() { #[tokio::main(flavor = "current_thread")]
async fn main() {
tracing_subscriber::fmt() tracing_subscriber::fmt()
.with_writer(io::stderr) .with_writer(io::stderr)
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
@ -16,17 +16,17 @@ fn main() {
let start = plugin.rfind('/').map(|v| v + 1).unwrap_or(0); let start = plugin.rfind('/').map(|v| v + 1).unwrap_or(0);
let cmd = &plugin.as_str()[start..]; let cmd = &plugin.as_str()[start..];
match cmd { match cmd {
"calc" => block_on(plugins::calc::main()), "calc" => plugins::calc::main().await,
"desktop-entries" => block_on(plugins::desktop_entries::main()), "desktop-entries" => plugins::desktop_entries::main().await,
"find" => block_on(plugins::find::main()), "find" => plugins::find::main().await,
"files" => block_on(plugins::files::main()), "files" => plugins::files::main().await,
"pop-launcher" => block_on(service::main()), "pop-launcher" => service::main().await,
"pop-shell" => block_on(plugins::pop_shell::main()), "pop-shell" => plugins::pop_shell::main().await,
"pulse" => block_on(plugins::pulse::main()), "pulse" => plugins::pulse::main().await,
"recent" => block_on(plugins::recent::main()), "recent" => plugins::recent::main().await,
"scripts" => block_on(plugins::scripts::main()), "scripts" => plugins::scripts::main().await,
"terminal" => block_on(plugins::terminal::main()), "terminal" => plugins::terminal::main().await,
"web" => block_on(plugins::web::main()), "web" => plugins::web::main().await,
unknown => { unknown => {
eprintln!("unknown cmd: {}", unknown); eprintln!("unknown cmd: {}", unknown);
} }

1
debian/rules vendored
View file

@ -2,6 +2,7 @@
VENDOR ?= 1 VENDOR ?= 1
CLEAN ?= 1 CLEAN ?= 1
DEBUG ?= 0
DESTDIR=debian/tmp DESTDIR=debian/tmp
%: %:

View file

@ -20,7 +20,6 @@ ron = "0.7.0"
serde = "1.0.136" serde = "1.0.136"
serde_json = "1.0.79" serde_json = "1.0.79"
slab = "0.4.5" slab = "0.4.5"
smol = "1.2.5"
strsim = "0.10.0" strsim = "0.10.0"
tracing = "0.1.32" tracing = "0.1.32"
tracing-subscriber = "0.3.9" tracing-subscriber = "0.3.9"
@ -35,3 +34,7 @@ anyhow = "1.0.56"
flume = "0.10.12" flume = "0.10.12"
dirs = "4.0.0" dirs = "4.0.0"
futures = "0.3.21" futures = "0.3.21"
[dependencies.tokio]
version = "1.17.0"
features = ["fs", "io-std", "macros", "process", "rt"]

View file

@ -1,14 +1,14 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
// Copyright © 2021 System76 // Copyright © 2021 System76
use futures::{AsyncBufReadExt, AsyncWriteExt, StreamExt}; use futures::StreamExt;
use pop_launcher::*; use pop_launcher::*;
use regex::Regex; use regex::Regex;
use smol::{ use std::{borrow::Cow, io, process::Stdio};
process::{Command, Stdio}, use tokio::{
Unblock, io::{AsyncBufReadExt, AsyncWriteExt},
process::Command,
}; };
use std::{borrow::Cow, io};
pub async fn main() { pub async fn main() {
let mut requests = json_input_stream(async_stdin()); let mut requests = json_input_stream(async_stdin());
@ -37,7 +37,7 @@ pub async fn main() {
pub struct App { pub struct App {
pub decimal_comma: bool, pub decimal_comma: bool,
out: Unblock<io::Stdout>, out: tokio::io::Stdout,
outcome: Option<String>, outcome: Option<String>,
regex: Regex, regex: Regex,
} }
@ -158,14 +158,17 @@ async fn qcalc(regex: &mut Regex, expression: &str, decimal_comma: bool) -> Opti
} }
}; };
let mut reader = futures::io::BufReader::new(stdout).lines().skip(2); let mut reader = tokio::io::BufReader::new(stdout).lines();
let mut output = String::new(); let mut output = String::new();
let _ = reader.next_line().await;
let _ = reader.next_line().await;
fn has_issue(line: &str) -> bool { fn has_issue(line: &str) -> bool {
line.starts_with("error") || line.starts_with("warning") line.starts_with("error") || line.starts_with("warning")
} }
while let Some(Ok(line)) = reader.next().await { while let Ok(Some(line)) = reader.next_line().await {
let line = line.trim(); let line = line.trim();
if line.is_empty() { if line.is_empty() {
@ -260,9 +263,9 @@ mod tests {
); );
} }
#[test] #[tokio::test]
fn approximate_result_formatting() { async fn approximate_result_formatting() {
let task = smol::spawn(async { let task = tokio::spawn(async {
let mut app = App { let mut app = App {
decimal_comma: false, decimal_comma: false,
..Default::default() ..Default::default()
@ -271,10 +274,8 @@ mod tests {
app.outcome.take() app.outcome.take()
}); });
smol::block_on(async { if let Some(result) = task.await.unwrap() {
if let Some(result) = task.await {
assert_eq!("≈ 2.333333333", result); assert_eq!("≈ 2.333333333", result);
} }
})
} }
} }

View file

@ -5,11 +5,12 @@ mod graphics;
use crate::*; use crate::*;
use freedesktop_desktop_entry::{default_paths, DesktopEntry, Iter as DesktopIter, PathSource}; use freedesktop_desktop_entry::{default_paths, DesktopEntry, Iter as DesktopIter, PathSource};
use futures::{AsyncWrite, StreamExt}; use futures::StreamExt;
use pop_launcher::*; use pop_launcher::*;
use std::borrow::Cow; use std::borrow::Cow;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::path::PathBuf; use std::path::PathBuf;
use tokio::io::AsyncWrite;
#[derive(Debug, Eq)] #[derive(Debug, Eq)]
struct Item { struct Item {

View file

@ -3,8 +3,7 @@
use futures::prelude::*; use futures::prelude::*;
use pop_launcher::*; use pop_launcher::*;
use smol::Unblock; use std::{collections::BTreeMap, path::PathBuf};
use std::{collections::BTreeMap, io, path::PathBuf};
#[derive(Clone)] #[derive(Clone)]
struct Item { struct Item {
@ -38,7 +37,7 @@ pub async fn main() {
pub struct App { pub struct App {
entries: BTreeMap<PathBuf, Vec<Item>>, entries: BTreeMap<PathBuf, Vec<Item>>,
home: PathBuf, home: PathBuf,
out: Unblock<io::Stdout>, out: tokio::io::Stdout,
search_results: Vec<Item>, search_results: Vec<Item>,
} }

View file

@ -3,11 +3,13 @@
use futures::*; use futures::*;
use pop_launcher::*; use pop_launcher::*;
use smol::process::{Child, ChildStdout, Command, Stdio};
use std::cell::Cell; use std::cell::Cell;
use std::io; use std::io;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Stdio;
use std::rc::Rc; use std::rc::Rc;
use tokio::io::AsyncBufReadExt;
use tokio::process::{Child, ChildStdout, Command};
enum Event { enum Event {
Activate(u32), Activate(u32),
@ -37,12 +39,10 @@ pub async fn main() {
Event::Activate(id) => { Event::Activate(id) => {
if let Some(selection) = app.search_results.get(id as usize) { if let Some(selection) = app.search_results.get(id as usize) {
let path = selection.clone(); let path = selection.clone();
let handle = smol::spawn(async move { tokio::spawn(async move {
crate::xdg_open(&path); crate::xdg_open(&path);
}); });
handle.detach();
crate::send(&mut app.out, PluginResponse::Close).await; crate::send(&mut app.out, PluginResponse::Close).await;
} }
} }
@ -114,7 +114,7 @@ pub async fn main() {
struct SearchContext { struct SearchContext {
pub active: Rc<Cell<bool>>, pub active: Rc<Cell<bool>>,
pub interrupt_rx: flume::Receiver<()>, pub interrupt_rx: flume::Receiver<()>,
pub out: smol::Unblock<io::Stdout>, pub out: tokio::io::Stdout,
pub search_results: Vec<PathBuf>, pub search_results: Vec<PathBuf>,
} }
@ -148,7 +148,7 @@ impl SearchContext {
tracing::debug!("searching for {}", search); tracing::debug!("searching for {}", search);
let (mut child, mut stdout) = match query(&search).await { let (mut child, mut stdout) = match query(&search).await {
Ok((child, stdout)) => (child, futures::io::BufReader::new(stdout).lines()), Ok((child, stdout)) => (child, tokio::io::BufReader::new(stdout).lines()),
Err(why) => { Err(why) => {
tracing::error!("failed to spawn fdfind process: {}", why); tracing::error!("failed to spawn fdfind process: {}", why);
@ -176,19 +176,16 @@ impl SearchContext {
'stream: loop { 'stream: loop {
let interrupt = async { let interrupt = async {
let _ = self.interrupt_rx.recv_async().await; let _ = self.interrupt_rx.recv_async().await;
None Ok(None)
}; };
match crate::or(interrupt, stdout.next()).await { match crate::or(interrupt, stdout.next_line()).await {
Some(result) => match result { Ok(Some(line)) => append = line,
Ok(line) => append = line, Ok(None) => break 'stream,
Err(why) => { Err(why) => {
tracing::error!("error on stdout line read: {}", why); tracing::error!("error on stdout line read: {}", why);
break 'stream; break 'stream;
} }
},
None => break 'stream,
} }
self.append(id, append).await; self.append(id, append).await;
@ -201,7 +198,7 @@ impl SearchContext {
} }
let _ = child.kill(); let _ = child.kill();
let _ = child.status().await; let _ = child.wait().await;
} }
} }

View file

@ -12,9 +12,9 @@ pub mod scripts;
pub mod terminal; pub mod terminal;
pub mod web; pub mod web;
use futures::{AsyncWrite, AsyncWriteExt};
use pop_launcher::PluginResponse; use pop_launcher::PluginResponse;
use std::{borrow::Cow, ffi::OsStr, future::Future, path::Path}; use std::{borrow::Cow, ffi::OsStr, future::Future, path::Path};
use tokio::io::{AsyncWrite, AsyncWriteExt};
pub async fn send<W: AsyncWrite + Unpin>(tx: &mut W, response: PluginResponse) { pub async fn send<W: AsyncWrite + Unpin>(tx: &mut W, response: PluginResponse) {
if let Ok(mut bytes) = serde_json::to_string(&response) { if let Ok(mut bytes) = serde_json::to_string(&response) {
@ -47,5 +47,5 @@ pub fn mime_from_path(path: &Path) -> Cow<'static, str> {
/// Launches a file with its default appplication via `xdg-open`. /// Launches a file with its default appplication via `xdg-open`.
pub fn xdg_open<S: AsRef<OsStr>>(file: S) { pub fn xdg_open<S: AsRef<OsStr>>(file: S) {
let _ = smol::process::Command::new("xdg-open").arg(file).spawn(); let _ = tokio::process::Command::new("xdg-open").arg(file).spawn();
} }

View file

@ -3,10 +3,11 @@
use crate::*; use crate::*;
use freedesktop_desktop_entry as fde; use freedesktop_desktop_entry as fde;
use futures::{AsyncWrite, AsyncWriteExt, StreamExt}; use futures::StreamExt;
use pop_launcher::*; use pop_launcher::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{convert::TryFrom, fs, path::PathBuf, sync::Arc}; use std::{convert::TryFrom, fs, path::PathBuf, sync::Arc};
use tokio::io::{AsyncWrite, AsyncWriteExt};
use zbus::Connection; use zbus::Connection;
use zvariant::{Signature, Type}; use zvariant::{Signature, Type};

View file

@ -4,7 +4,6 @@
use async_pidfd::AsyncPidFd; use async_pidfd::AsyncPidFd;
use futures::prelude::*; use futures::prelude::*;
use pop_launcher::*; use pop_launcher::*;
use smol::Unblock;
use std::io; use std::io;
struct Selection { struct Selection {
@ -15,7 +14,7 @@ struct Selection {
pub struct App { pub struct App {
selections: Vec<Selection>, selections: Vec<Selection>,
out: Unblock<io::Stdout>, out: tokio::io::Stdout,
} }
impl Default for App { impl Default for App {
@ -77,7 +76,7 @@ impl App {
let sinks = pactl_sinks(); let sinks = pactl_sinks();
while let Ok(id) = sinks.recv_async().await { while let Ok(id) = sinks.recv_async().await {
handles.push(smol::spawn(async move { handles.push(tokio::spawn(async move {
let args = &[arg1, id.as_str(), arg2]; let args = &[arg1, id.as_str(), arg2];
let _ = command_spawn(cmd, args).await; let _ = command_spawn(cmd, args).await;
})); }));
@ -136,25 +135,25 @@ async fn command_spawn(cmd: &str, args: &[&str]) -> io::Result<()> {
fn pactl_sinks() -> flume::Receiver<String> { fn pactl_sinks() -> flume::Receiver<String> {
let (tx, rx) = flume::bounded(4); let (tx, rx) = flume::bounded(4);
smol::spawn(async move { tokio::spawn(async move {
let child = smol::process::Command::new("pactl") let child = tokio::process::Command::new("pactl")
.env("LANG", "C") .env("LANG", "C")
.args(&["list", "sinks"]) .args(&["list", "sinks"])
.stdout(smol::process::Stdio::piped()) .stdout(std::process::Stdio::piped())
.spawn(); .spawn();
if let Ok(mut child) = child { if let Ok(mut child) = child {
if let Some(stdout) = child.stdout.take() { if let Some(stdout) = child.stdout.take() {
let mut lines = futures::io::BufReader::new(stdout).lines(); use tokio::io::AsyncBufReadExt;
while let Some(Ok(line)) = lines.next().await { let mut lines = tokio::io::BufReader::new(stdout).lines();
while let Ok(Some(line)) = lines.next_line().await {
if let Some(stripped) = line.strip_prefix("Sink #") { if let Some(stripped) = line.strip_prefix("Sink #") {
let _ = tx.send_async(stripped.trim().to_owned()).await; let _ = tx.send_async(stripped.trim().to_owned()).await;
} }
} }
} }
} }
}) });
.detach();
rx rx
} }

View file

@ -5,12 +5,11 @@ use futures::prelude::*;
use gtk::prelude::*; use gtk::prelude::*;
use pop_launcher::*; use pop_launcher::*;
use slab::Slab; use slab::Slab;
use smol::Unblock; use std::borrow::Cow;
use std::{borrow::Cow, io};
pub struct App { pub struct App {
manager: gtk::RecentManager, manager: gtk::RecentManager,
out: Unblock<io::Stdout>, out: tokio::io::Stdout,
uris: Slab<String>, uris: Slab<String>,
} }

View file

@ -5,13 +5,12 @@ use crate::*;
use pop_launcher::*; use pop_launcher::*;
use flume::Sender; use flume::Sender;
use futures::{AsyncBufReadExt, StreamExt}; use futures::StreamExt;
use smol::process::{Command, Stdio};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::{ use std::path::{Path, PathBuf};
io, use std::process::Stdio;
path::{Path, PathBuf}, use tokio::io::AsyncBufReadExt;
}; use tokio::process::Command;
const LOCAL_PATH: &str = ".local/share/pop-launcher/scripts"; const LOCAL_PATH: &str = ".local/share/pop-launcher/scripts";
const SYSTEM_ADMIN_PATH: &str = "/etc/pop-launcher/scripts"; const SYSTEM_ADMIN_PATH: &str = "/etc/pop-launcher/scripts";
@ -42,7 +41,7 @@ pub async fn main() {
pub struct App { pub struct App {
scripts: Vec<ScriptInfo>, scripts: Vec<ScriptInfo>,
out: smol::Unblock<io::Stdout>, out: tokio::io::Stdout,
} }
impl App { impl App {
@ -156,9 +155,9 @@ async fn load_from(path: &Path, paths: &mut VecDeque<PathBuf>, tx: Sender<Script
continue; continue;
} }
smol::spawn(async move { tokio::spawn(async move {
let mut file = match smol::fs::File::open(&path).await { let mut file = match tokio::fs::File::open(&path).await {
Ok(file) => futures::io::BufReader::new(file).lines(), Ok(file) => tokio::io::BufReader::new(file).lines(),
Err(why) => { Err(why) => {
tracing::error!("cannot open script at {}: {}", path.display(), why); tracing::error!("cannot open script at {}: {}", path.display(), why);
return; return;
@ -172,7 +171,7 @@ async fn load_from(path: &Path, paths: &mut VecDeque<PathBuf>, tx: Sender<Script
let mut first = true; let mut first = true;
while let Some(Ok(line)) = file.next().await { while let Ok(Some(line)) = file.next_line().await {
if !line.starts_with('#') { if !line.starts_with('#') {
break; break;
} }
@ -200,8 +199,7 @@ async fn load_from(path: &Path, paths: &mut VecDeque<PathBuf>, tx: Sender<Script
} }
let _ = tx.send_async(info).await; let _ = tx.send_async(info).await;
}) });
.detach();
} }
} }
} }

View file

@ -3,12 +3,11 @@
use futures::prelude::*; use futures::prelude::*;
use pop_launcher::*; use pop_launcher::*;
use smol::Unblock; use std::path::PathBuf;
use std::{io, path::PathBuf};
pub struct App { pub struct App {
last_query: Option<String>, last_query: Option<String>,
out: Unblock<io::Stdout>, out: tokio::io::Stdout,
shell_only: bool, shell_only: bool,
} }

View file

@ -2,7 +2,6 @@
// Copyright © 2021 System76 // Copyright © 2021 System76
use std::borrow::Cow; use std::borrow::Cow;
use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::Duration; use std::time::Duration;
@ -11,7 +10,6 @@ use futures::StreamExt;
use isahc::config::{Configurable, RedirectPolicy}; use isahc::config::{Configurable, RedirectPolicy};
use isahc::http::header::CONTENT_TYPE; use isahc::http::header::CONTENT_TYPE;
use isahc::{AsyncReadResponseExt, HttpClient}; use isahc::{AsyncReadResponseExt, HttpClient};
use smol::Unblock;
use url::Url; use url::Url;
use pop_launcher::*; use pop_launcher::*;
@ -42,7 +40,7 @@ pub async fn main() {
pub struct App { pub struct App {
config: Config, config: Config,
queries: Vec<String>, queries: Vec<String>,
out: Unblock<io::Stdout>, out: tokio::io::Stdout,
client: HttpClient, client: HttpClient,
cache: PathBuf, cache: PathBuf,
} }
@ -145,7 +143,7 @@ impl App {
let favicon_path = favicon_path.to_path_buf(); let favicon_path = favicon_path.to_path_buf();
smol::spawn(async move { tokio::spawn(async move {
let favicon_url = favicon_url_from_page_source(&domain, &client) let favicon_url = favicon_url_from_page_source(&domain, &client)
.await .await
.unwrap_or_else(|| { .unwrap_or_else(|| {
@ -162,15 +160,14 @@ impl App {
std::fs::create_dir_all(cache_dir).expect("error creating cache directory"); std::fs::create_dir_all(cache_dir).expect("error creating cache directory");
} }
let copy = smol::fs::write(&favicon_path, icon).await; let copy = tokio::fs::write(&favicon_path, icon).await;
if let Err(err) = copy { if let Err(err) = copy {
tracing::error!("error writing favicon to {:?}: {}", &favicon_path, err); tracing::error!("error writing favicon to {:?}: {}", &favicon_path, err);
} }
} }
None => tracing::error!("no icon found for {}", domain), None => tracing::error!("no icon found for {}", domain),
} }
}) });
.detach();
} }
} }

View file

@ -5,25 +5,30 @@ license = "MPL-2.0"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
anyhow = "1.0.55" anyhow = "1.0.56"
async-io = "1.6.0"
async-oneshot = "0.5.0" async-oneshot = "0.5.0"
async-trait = "0.1.52" async-trait = "0.1.53"
futures = "0.3.21" futures = "0.3.21"
futures_codec = "0.4.1" futures_codec = "0.4.1"
gen-z = "0.1.0" gen-z = "0.1.0"
num_cpus = "1.13.1" num_cpus = "1.13.1"
pop-launcher = { path = "../" } pop-launcher = { path = "../" }
regex = "1.5.4" regex = "1.5.5"
ron = "0.7.0" ron = "0.7.0"
serde = { version = "1.0.136", features = ["derive"] } serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79" serde_json = "1.0.79"
serde_with = "1.12.0" serde_with = "1.12.0"
slab = "0.4.5" slab = "0.4.5"
smol = "1.2.5"
strsim = "0.10.0" strsim = "0.10.0"
toml = "0.5.8" toml = "0.5.8"
tracing = "0.1.31" tracing = "0.1.32"
tracing-subscriber = { version = "0.3.9", features = ["fmt"] } tracing-subscriber = { version = "0.3.9", features = ["fmt"] }
async-process = "1.3.0"
flume = "0.10.12" flume = "0.10.12"
[dependencies.tokio]
version = "1.17.0"
features = ["io-std", "process", "rt"]
[dependencies.tokio-stream]
version = "0.1.8"
features = ["io-util"]

View file

@ -1,10 +1,12 @@
// Copyright 2021 System76 <info@system76.com> // Copyright 2021 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use async_process as process; use futures::{Stream, StreamExt};
use futures::{AsyncBufReadExt, AsyncWriteExt, Stream, StreamExt};
use pop_launcher::{Request, Response}; use pop_launcher::{Request, Response};
use std::io; use std::io;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt};
use tokio::process;
use tokio_stream::wrappers::LinesStream;
pub struct IpcClient { pub struct IpcClient {
pub child: process::Child, pub child: process::Child,
@ -14,8 +16,8 @@ pub struct IpcClient {
impl IpcClient { impl IpcClient {
pub fn new() -> io::Result<(Self, impl Stream<Item = Response>)> { pub fn new() -> io::Result<(Self, impl Stream<Item = Response>)> {
let mut child = process::Command::new("pop-launcher") let mut child = process::Command::new("pop-launcher")
.stdin(process::Stdio::piped()) .stdin(std::process::Stdio::piped())
.stdout(process::Stdio::piped()) .stdout(std::process::Stdio::piped())
.spawn()?; .spawn()?;
let stdin = child let stdin = child
@ -28,10 +30,8 @@ impl IpcClient {
.take() .take()
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "failed to find child stdout"))?; .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "failed to find child stdout"))?;
let responses = let responses = LinesStream::new(tokio::io::BufReader::new(stdout).lines()).filter_map(
futures::io::BufReader::new(stdout) |result| async move {
.lines()
.filter_map(|result| async move {
if let Ok(line) = result { if let Ok(line) = result {
if let Ok(event) = serde_json::from_str::<Response>(&line) { if let Ok(event) = serde_json::from_str::<Response>(&line) {
return Some(event); return Some(event);
@ -39,7 +39,8 @@ impl IpcClient {
} }
None None
}); },
);
let client = Self { child, stdin }; let client = Self { child, stdin };
@ -57,6 +58,6 @@ impl IpcClient {
pub async fn exit(mut self) { pub async fn exit(mut self) {
let _ = self.send(Request::Exit).await; let _ = self.send(Request::Exit).await;
let _ = self.child.status().await; let _ = self.child.wait().await;
} }
} }

View file

@ -34,7 +34,7 @@ pub struct PluginHelp {
pub async fn main() { pub async fn main() {
// Listens for a stream of requests from stdin. // Listens for a stream of requests from stdin.
let input_stream = json_input_stream(async_stdin()).filter_map(|result| { let input_stream = json_input_stream(tokio::io::stdin()).filter_map(|result| {
future::ready(match result { future::ready(match result {
Ok(request) => Some(request), Ok(request) => Some(request),
Err(why) => { Err(why) => {
@ -124,7 +124,7 @@ impl<O: futures::Sink<Response> + Unpin> Service<O> {
futures::pin_mut!(f1); futures::pin_mut!(f1);
futures::pin_mut!(f2); futures::pin_mut!(f2);
futures::future::select(f1, f2).await.factor_first().0; let _ = futures::future::select(f1, f2).await.factor_first().0;
} }
async fn response_handler(&mut self, service_rx: Receiver<Event>) { async fn response_handler(&mut self, service_rx: Receiver<Event>) {
@ -229,10 +229,9 @@ impl<O: futures::Sink<Response> + Unpin> Service<O> {
let init = init.clone(); let init = init.clone();
let service_tx = service_tx.clone(); let service_tx = service_tx.clone();
smol::spawn(async move { tokio::spawn(async move {
init(id, service_tx).run(request_rx).await; init(id, service_tx).run(request_rx).await;
}) });
.detach();
request_tx request_tx
}), }),

View file

@ -15,10 +15,10 @@ pub fn from_paths() -> impl Stream<Item = (PathBuf, PluginConfig, Option<Regex>)
stream::iter(crate::plugin_paths()) stream::iter(crate::plugin_paths())
.flat_map(|path| from_path(path.to_path_buf())) .flat_map(|path| from_path(path.to_path_buf()))
.map(|(source, config)| { .map(|(source, config)| {
smol::unblock(move || crate::plugins::config::load(&source, &config)) tokio::task::spawn_blocking(move || crate::plugins::config::load(&source, &config))
}) })
.buffered(num_cpus::get()) .buffered(num_cpus::get())
.filter_map(|x| async move { x }) .filter_map(|x| async move { x.ok().flatten() })
} }
/// Loads all plugin information found in the given path. /// Loads all plugin information found in the given path.

View file

@ -6,6 +6,7 @@ pub mod load;
use std::{ use std::{
io, io,
path::PathBuf, path::PathBuf,
process::Stdio,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
Arc, Arc,
@ -15,10 +16,11 @@ use std::{
use crate::{Event, Indice, Plugin, PluginResponse, Request}; use crate::{Event, Indice, Plugin, PluginResponse, Request};
use async_oneshot::oneshot; use async_oneshot::oneshot;
use flume::Sender; use flume::Sender;
use futures::{AsyncWriteExt, StreamExt}; use futures::StreamExt;
use smol::{ use tokio::{
process::{Child, Command, Stdio}, io::AsyncWriteExt,
Task, process::{Child, Command},
task::JoinHandle,
}; };
use tracing::{event, Level}; use tracing::{event, Level};
@ -28,7 +30,7 @@ pub struct ExternalPlugin {
name: String, name: String,
pub cmd: PathBuf, pub cmd: PathBuf,
pub args: Vec<String>, pub args: Vec<String>,
process: Option<(Task<()>, Child, async_oneshot::Sender<()>)>, process: Option<(JoinHandle<()>, Child, async_oneshot::Sender<()>)>,
detached: Arc<AtomicBool>, detached: Arc<AtomicBool>,
searching: Arc<AtomicBool>, searching: Arc<AtomicBool>,
} }
@ -53,7 +55,7 @@ impl ExternalPlugin {
} }
} }
pub fn launch(&mut self) -> Option<&mut (Task<()>, Child, async_oneshot::Sender<()>)> { pub fn launch(&mut self) -> Option<&mut (JoinHandle<()>, Child, async_oneshot::Sender<()>)> {
event!(Level::DEBUG, "{}: launching plugin", self.name()); event!(Level::DEBUG, "{}: launching plugin", self.name());
let child = Command::new(&self.cmd) let child = Command::new(&self.cmd)
@ -74,7 +76,7 @@ impl ExternalPlugin {
let id = self.id; let id = self.id;
// Spawn a background task to forward JSON responses from the child process. // Spawn a background task to forward JSON responses from the child process.
let task = smol::spawn(async move { let task = tokio::spawn(async move {
let tx_ = tx.clone(); let tx_ = tx.clone();
let searching_ = searching.clone(); let searching_ = searching.clone();
let name_ = name.clone(); let name_ = name.clone();
@ -105,7 +107,13 @@ impl ExternalPlugin {
let _ = trip_rx.await; let _ = trip_rx.await;
}; };
let _ = crate::or(responder, trip).await; futures::pin_mut!(responder);
futures::pin_mut!(trip);
let _ = futures::future::select(responder, trip)
.await
.factor_first()
.0;
// Ensure that a task that was searching sends a finished signal if it dies. // Ensure that a task that was searching sends a finished signal if it dies.
if searching.swap(false, Ordering::SeqCst) { if searching.swap(false, Ordering::SeqCst) {
@ -128,9 +136,9 @@ impl ExternalPlugin {
pub async fn process_check(&mut self) { pub async fn process_check(&mut self) {
if let Some(mut child) = self.process.take() { if let Some(mut child) = self.process.take() {
match child.1.try_status() { match child.1.try_wait() {
Err(_) | Ok(Some(_)) => { Err(_) | Ok(Some(_)) => {
child.0.cancel().await; child.0.abort();
} }
Ok(None) => self.process = Some(child), Ok(None) => self.process = Some(child),
} }

View file

@ -1,19 +1,18 @@
// Copyright 2021 System76 <info@system76.com> // Copyright 2021 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use blocking::Unblock; use futures::{Stream, StreamExt};
use futures::{AsyncBufReadExt, AsyncRead, Stream, StreamExt};
use serde::Deserialize; use serde::Deserialize;
use std::io; use tokio::io::{AsyncBufReadExt, AsyncRead};
/// stdin with AsyncRead support /// stdin with AsyncRead support
pub fn async_stdin() -> Unblock<io::Stdin> { pub fn async_stdin() -> tokio::io::Stdin {
Unblock::new(io::stdin()) tokio::io::stdin()
} }
/// stdout with AsyncWrite support /// stdout with AsyncWrite support
pub fn async_stdout() -> Unblock<io::Stdout> { pub fn async_stdout() -> tokio::io::Stdout {
Unblock::new(io::stdout()) tokio::io::stdout()
} }
/// Creates a stream that parses JSON input line-by-line /// Creates a stream that parses JSON input line-by-line
@ -22,8 +21,8 @@ where
I: AsyncRead + Unpin + Send, I: AsyncRead + Unpin + Send,
S: for<'a> Deserialize<'a>, S: for<'a> Deserialize<'a>,
{ {
futures::io::BufReader::new(input) let line_reader = tokio::io::BufReader::new(input).lines();
.lines() tokio_stream::wrappers::LinesStream::new(line_reader)
.take_while(|x| futures::future::ready(x.is_ok())) .take_while(|x| futures::future::ready(x.is_ok()))
.map(Result::unwrap) .map(Result::unwrap)
.map(|line| serde_json::from_str::<S>(&line)) .map(|line| serde_json::from_str::<S>(&line))