Take direct control of the tokio runtime

Since the GTK thread wants to be the main one, it's easier to manually spawn the runtime handlers and to spawn new tasks to handle communication with the core. I added a basic struct to own the runtime, the core, and communication between the core and GTK
This commit is contained in:
Savanni D'Gerinel 2023-03-21 09:17:52 -04:00
parent d86d10428b
commit e1d3a7840d
4 changed files with 288 additions and 60 deletions

View File

@ -8,6 +8,33 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytes"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "kifu-core" name = "kifu-core"
version = "0.1.0" version = "0.1.0"
@ -15,12 +42,157 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "libc"
version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "mio"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys",
]
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.9" version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "proc-macro2"
version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "socket2"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.26.0" version = "1.26.0"
@ -28,10 +200,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys", "windows-sys",
] ]
[[package]]
name = "tokio-macros"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.45.0" version = "0.45.0"

View File

@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
tokio = { version = "1.26", features = [ "sync" ] } tokio = { version = "1.26", features = [ "full" ] }

View File

@ -16,41 +16,23 @@ pub enum Response {
PlayingFieldView(PlayingFieldView), PlayingFieldView(PlayingFieldView),
} }
fn dispatch(state: Arc<RwLock<AppState>>, request: Request) -> Response { #[derive(Clone)]
match request {
Request::PlayingField => Response::PlayingFieldView(playing_field()),
}
}
pub struct CoreApp { pub struct CoreApp {
request_rx: Receiver<Request>,
response_tx: Sender<Response>,
state: Arc<RwLock<AppState>>, state: Arc<RwLock<AppState>>,
} }
impl CoreApp { impl CoreApp {
pub fn new() -> (Self, Sender<Request>, Receiver<Response>) { pub fn new() -> Self {
let (request_tx, request_rx) = channel(5);
let (response_tx, response_rx) = channel(5);
let state = Arc::new(RwLock::new(AppState::new())); let state = Arc::new(RwLock::new(AppState::new()));
( Self { state }
Self {
request_rx,
response_tx,
state,
},
request_tx,
response_rx,
)
} }
pub async fn run(&mut self) { pub async fn dispatch(&self, request: Request) -> Response {
loop { match request {
let msg = self.request_rx.recv().await.unwrap(); Request::PlayingField => Response::PlayingFieldView(playing_field()),
let resp = dispatch(self.state.clone(), msg);
self.response_tx.send(resp).await.unwrap();
} }
} }
pub async fn run(&self) {}
} }

View File

@ -4,55 +4,75 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
time::Duration, time::Duration,
}; };
use tokio::sync::mpsc::{Receiver, Sender}; use tokio::{
runtime::Runtime,
sync::mpsc::{Receiver, Sender},
};
#[tokio::main] #[derive(Clone)]
async fn main() { pub struct CoreApi {
let (mut core, request_tx, response_rx) = CoreApp::new(); gtk_tx: gtk::glib::Sender<Response>,
let core_handle = tokio::spawn(async move { rt: Arc<Runtime>,
core.run().await; core: CoreApp,
}
impl CoreApi {
pub fn dispatch(&self, request: Request) {
self.rt.spawn({
let gtk_tx = self.gtk_tx.clone();
let core = self.core.clone();
async move { gtk_tx.send(core.dispatch(request).await) }
});
}
}
fn main() {
let runtime = Arc::new(
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap(),
);
let core = CoreApp::new();
let core_handle = runtime.spawn({
let core = core.clone();
async move {
core.run().await;
}
}); });
let gtk_handle = tokio::task::spawn_blocking(move || { let app = gtk::Application::builder()
let app = gtk::Application::builder() .application_id("com.luminescent-dreams.kifu-gtk")
.application_id("com.luminescent-dreams.kifu-gtk") .build();
.build();
let _ = tokio::spawn({ app.connect_activate({
let request_tx = request_tx.clone(); let runtime = runtime.clone();
async move { move |app| {
let _ = request_tx.send(Request::PlayingField).await;
}
});
app.connect_activate(move |app| {
let (gtk_tx, gtk_rx) = let (gtk_tx, gtk_rx) =
gtk::glib::MainContext::channel::<Response>(gtk::glib::PRIORITY_DEFAULT); gtk::glib::MainContext::channel::<Response>(gtk::glib::PRIORITY_DEFAULT);
let _ = tokio::task::spawn(connector(gtk_tx, response_rx)); let api = CoreApi {
gtk_tx,
rt: runtime.clone(),
core: core.clone(),
};
let window = gtk::ApplicationWindow::new(app); let window = gtk::ApplicationWindow::new(app);
window.present(); window.present();
gtk_rx.attach(None, |message| { gtk_rx.attach(None, |message| {
println!("message: {:?}", message); println!("message: {:?}", message);
Continue(true) Continue(true)
}); });
});
println!("running the gtk loop"); api.dispatch(Request::PlayingField);
app.run(); }
}); });
core_handle.await; println!("running the gtk loop");
gtk_handle.await; app.run();
}
async fn connector(gtk_tx: gtk::glib::Sender<Response>, mut response_rx: Receiver<Response>) { let _ = runtime.block_on(async { core_handle.await });
loop {
let msg = response_rx.recv().await;
match msg {
Some(msg) => gtk_tx.send(msg).unwrap(),
None => (),
}
}
} }