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"
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]]
name = "kifu-core"
version = "0.1.0"
@ -15,12 +42,157 @@ dependencies = [
"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]]
name = "pin-project-lite"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "tokio"
version = "1.26.0"
@ -28,10 +200,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
dependencies = [
"autocfg",
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"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]]
name = "windows-sys"
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
[dependencies]
tokio = { version = "1.26", features = [ "sync" ] }
tokio = { version = "1.26", features = [ "full" ] }

View File

@ -16,41 +16,23 @@ pub enum Response {
PlayingFieldView(PlayingFieldView),
}
fn dispatch(state: Arc<RwLock<AppState>>, request: Request) -> Response {
#[derive(Clone)]
pub struct CoreApp {
state: Arc<RwLock<AppState>>,
}
impl CoreApp {
pub fn new() -> Self {
let state = Arc::new(RwLock::new(AppState::new()));
Self { state }
}
pub async fn dispatch(&self, request: Request) -> Response {
match request {
Request::PlayingField => Response::PlayingFieldView(playing_field()),
}
}
pub struct CoreApp {
request_rx: Receiver<Request>,
response_tx: Sender<Response>,
state: Arc<RwLock<AppState>>,
}
impl CoreApp {
pub fn new() -> (Self, Sender<Request>, Receiver<Response>) {
let (request_tx, request_rx) = channel(5);
let (response_tx, response_rx) = channel(5);
let state = Arc::new(RwLock::new(AppState::new()));
(
Self {
request_rx,
response_tx,
state,
},
request_tx,
response_rx,
)
}
pub async fn run(&mut self) {
loop {
let msg = self.request_rx.recv().await.unwrap();
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},
time::Duration,
};
use tokio::sync::mpsc::{Receiver, Sender};
use tokio::{
runtime::Runtime,
sync::mpsc::{Receiver, Sender},
};
#[tokio::main]
async fn main() {
let (mut core, request_tx, response_rx) = CoreApp::new();
let core_handle = tokio::spawn(async move {
#[derive(Clone)]
pub struct CoreApi {
gtk_tx: gtk::glib::Sender<Response>,
rt: Arc<Runtime>,
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()
.application_id("com.luminescent-dreams.kifu-gtk")
.build();
let _ = tokio::spawn({
let request_tx = request_tx.clone();
async move {
let _ = request_tx.send(Request::PlayingField).await;
}
});
app.connect_activate(move |app| {
app.connect_activate({
let runtime = runtime.clone();
move |app| {
let (gtk_tx, gtk_rx) =
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);
window.present();
gtk_rx.attach(None, |message| {
println!("message: {:?}", message);
Continue(true)
});
api.dispatch(Request::PlayingField);
}
});
println!("running the gtk loop");
app.run();
});
core_handle.await;
gtk_handle.await;
}
async fn connector(gtk_tx: gtk::glib::Sender<Response>, mut response_rx: Receiver<Response>) {
loop {
let msg = response_rx.recv().await;
match msg {
Some(msg) => gtk_tx.send(msg).unwrap(),
None => (),
}
}
let _ = runtime.block_on(async { core_handle.await });
}