[niepce] rust: use async_channel instead of glib::channel
- From: Hubert Figuière <hub src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [niepce] rust: use async_channel instead of glib::channel
- Date: Sat, 3 Jul 2021 16:26:59 +0000 (UTC)
commit b6a3ebc678db9e902e31deae4a6f21c6dce84c04
Author: Hubert Figuière <hub figuiere net>
Date: Fri Jul 2 00:54:30 2021 -0400
rust: use async_channel instead of glib::channel
Cargo.lock | 35 ++++++++++++++++++++++++
crates/npc-engine/Cargo.toml | 1 +
crates/npc-engine/src/db/library.rs | 12 ++++----
crates/npc-engine/src/library/notification.rs | 7 +++--
crates/npc-engine/src/library/thumbnail_cache.rs | 31 +++++++++++----------
crates/npc-fwk/Cargo.toml | 1 +
crates/npc-fwk/src/toolkit/mod.rs | 16 +++++++++--
niepce-main/Cargo.toml | 1 +
niepce-main/src/libraryclient/mod.rs | 28 +++++++++----------
src/niepce/notificationcenter.cpp | 1 -
10 files changed, 92 insertions(+), 41 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 93adc6d..2b2afcc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -17,6 +17,17 @@ version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
+[[package]]
+name = "async-channel"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
+dependencies = [
+ "concurrent-queue",
+ "event-listener",
+ "futures-core",
+]
+
[[package]]
name = "atk"
version = "0.14.0"
@@ -64,6 +75,12 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+[[package]]
+name = "cache-padded"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
+
[[package]]
name = "cairo-rs"
version = "0.14.0"
@@ -150,12 +167,27 @@ dependencies = [
"vec_map",
]
+[[package]]
+name = "concurrent-queue"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
+dependencies = [
+ "cache-padded",
+]
+
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+[[package]]
+name = "event-listener"
+version = "2.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
+
[[package]]
name = "exempi"
version = "2.6.0"
@@ -600,6 +632,7 @@ dependencies = [
name = "niepce_rust"
version = "0.1.0"
dependencies = [
+ "async-channel",
"cairo-rs",
"cbindgen",
"gdk",
@@ -621,6 +654,7 @@ dependencies = [
name = "npc-engine"
version = "0.1.0"
dependencies = [
+ "async-channel",
"cbindgen",
"chrono",
"exempi",
@@ -639,6 +673,7 @@ dependencies = [
name = "npc-fwk"
version = "0.1.0"
dependencies = [
+ "async-channel",
"cairo-rs",
"cbindgen",
"chrono",
diff --git a/crates/npc-engine/Cargo.toml b/crates/npc-engine/Cargo.toml
index a865f42..1386ecf 100644
--- a/crates/npc-engine/Cargo.toml
+++ b/crates/npc-engine/Cargo.toml
@@ -8,6 +8,7 @@ build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+async-channel = "1.6.1"
chrono = "0.4.0"
exempi = { version = "2.6.0", git = "https://github.com/hfiguiere/exempi-rs.git", rev="99e8ba5" }
gdk-pixbuf-sys = "*"
diff --git a/crates/npc-engine/src/db/library.rs b/crates/npc-engine/src/db/library.rs
index d53242c..bc52c17 100644
--- a/crates/npc-engine/src/db/library.rs
+++ b/crates/npc-engine/src/db/library.rs
@@ -22,7 +22,6 @@ use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::result;
-use std::sync::mpsc;
use chrono::Utc;
use rusqlite;
@@ -40,6 +39,7 @@ use crate::db::libfolder::LibFolder;
use crate::db::libmetadata::LibMetadata;
use crate::library::notification::LibNotification;
use npc_fwk;
+use npc_fwk::toolkit;
use npc_fwk::PropertyValue;
#[repr(i32)]
@@ -81,7 +81,7 @@ pub struct Library {
impl Library {
#[cfg(test)]
pub fn new_in_memory() -> Library {
- let (sender, _) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
+ let (sender, _) = async_channel::unbounded();
let mut lib = Library {
// maindir: dir,
dbpath: PathBuf::default(),
@@ -129,7 +129,8 @@ impl Library {
if let Some(ref conn) = self.dbconn {
let sender = self.sender.clone();
if let Err(err) = conn.create_scalar_function("rewrite_xmp", 0, false, move |_| {
- if let Err(err) = sender.send(LibNotification::XmpNeedsUpdate) {
+ if let Err(err) =
+ toolkit::thread_context().block_on(sender.send(LibNotification::XmpNeedsUpdate)) {
// This not fatal, at least the data should be saved.
// But still, it's not good.
err_out!("Error sending XmpNeedsUpdate notification: {}", err);
@@ -335,8 +336,9 @@ impl Library {
pub fn notify(
&self,
notif: LibNotification,
- ) -> std::result::Result<(), mpsc::SendError<LibNotification>> {
- self.sender.send(notif)
+ ) -> std::result::Result<(), async_channel::SendError<LibNotification>> {
+ toolkit::thread_context().block_on(
+ self.sender.send(notif))
}
pub fn add_jpeg_file_to_bundle(&self, file_id: LibraryId, fsfile_id: LibraryId) -> Result<()> {
diff --git a/crates/npc-engine/src/library/notification.rs b/crates/npc-engine/src/library/notification.rs
index 9c0dc15..260c269 100644
--- a/crates/npc-engine/src/library/notification.rs
+++ b/crates/npc-engine/src/library/notification.rs
@@ -1,7 +1,7 @@
/*
* niepce - engine/library/notification.rs
*
- * Copyright (C) 2017-2020 Hubert Figuière
+ * Copyright (C) 2017-2021 Hubert Figuière
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@ use super::queriedcontent::QueriedContent;
use crate::db::libfile::FileStatus;
use crate::db::{Keyword, Label, LibFolder, LibMetadata, LibraryId, NiepceProperties};
use npc_fwk::base::PropertyIndex;
+use npc_fwk::toolkit;
use npc_fwk::toolkit::thumbnail;
use npc_fwk::toolkit::PortableChannel;
use npc_fwk::PropertyValue;
@@ -148,13 +149,13 @@ pub unsafe extern "C" fn engine_library_notify_filestatus_changed(
id: LibraryId,
status: FileStatus,
) -> bool {
- if let Err(err) = (*channel)
+ if let Err(err) = toolkit::thread_context().block_on((*channel)
.0
.clone()
.send(LibNotification::FileStatusChanged(FileStatusChange {
id,
status,
- }))
+ })))
{
err_out!("Error sending notification: {}", err);
return false;
diff --git a/crates/npc-engine/src/library/thumbnail_cache.rs
b/crates/npc-engine/src/library/thumbnail_cache.rs
index 5fb36a5..0d15003 100644
--- a/crates/npc-engine/src/library/thumbnail_cache.rs
+++ b/crates/npc-engine/src/library/thumbnail_cache.rs
@@ -1,7 +1,7 @@
/*
* niepce - library/thumbnail_cache.rs
*
- * Copyright (C) 2020 Hubert Figuière
+ * Copyright (C) 2020-2021 Hubert Figuière
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,7 +28,6 @@ use std::sync::atomic;
use std::thread;
use gdk_pixbuf;
-use glib;
use crate::db::libfile::{FileStatus, LibFile};
use crate::db::LibraryId;
@@ -36,6 +35,7 @@ use crate::library::notification;
use crate::library::notification::LibNotification::{FileStatusChanged, ThumbnailLoaded};
use crate::library::notification::{FileStatusChange, LcChannel, LibNotification};
use crate::library::queriedcontent::QueriedContent;
+use npc_fwk::toolkit;
use npc_fwk::toolkit::thumbnail::Thumbnail;
/// Thumbnail task
@@ -89,11 +89,11 @@ pub struct ThumbnailCache {
cache_dir: PathBuf,
tasks: Tasks,
running: Running,
- sender: glib::Sender<LibNotification>,
+ sender: async_channel::Sender<LibNotification>,
}
impl ThumbnailCache {
- fn new(dir: &Path, sender: glib::Sender<LibNotification>) -> Self {
+ fn new(dir: &Path, sender: async_channel::Sender<LibNotification>) -> Self {
Self {
cache_dir: PathBuf::from(dir),
tasks: sync::Arc::new((sync::Mutex::new(VecDeque::new()), sync::Condvar::new())),
@@ -102,7 +102,7 @@ impl ThumbnailCache {
}
}
- fn execute(task: ThumbnailTask, cache_dir: &Path, sender: glib::Sender<LibNotification>) {
+ fn execute(task: ThumbnailTask, cache_dir: &Path, sender: async_channel::Sender<LibNotification>) {
let w = task.width;
let h = task.height;
let libfile = task.file;
@@ -114,10 +114,10 @@ impl ThumbnailCache {
let pix = get_thumbnail(&libfile, w, h, &dest);
if !path.is_file() {
dbg_out!("file doesn't exist");
- if let Err(err) = sender.send(FileStatusChanged(FileStatusChange {
+ if let Err(err) =
toolkit::thread_context().block_on(sender.send(FileStatusChanged(FileStatusChange {
id,
status: FileStatus::Missing,
- })) {
+ }))) {
err_out!("Sending file status change notification failed: {}", err);
}
}
@@ -126,21 +126,24 @@ impl ThumbnailCache {
return;
}
// notify the thumbnail
- if let Err(err) = sender.send(ThumbnailLoaded(notification::Thumbnail {
- id,
- width: pix.get_width(),
- height: pix.get_height(),
- pix,
- })) {
+ if let Err(err) = toolkit::thread_context().block_on(
+ sender.send(ThumbnailLoaded(notification::Thumbnail {
+ id,
+ width: pix.get_width(),
+ height: pix.get_height(),
+ pix,
+ })))
+ {
err_out!("Sending thumbnail notification failed: {}", err);
}
+
}
fn main(
running: &Running,
tasks: &Tasks,
cache_dir: PathBuf,
- sender: glib::Sender<LibNotification>,
+ sender: async_channel::Sender<LibNotification>,
) {
while running.load(atomic::Ordering::Relaxed) {
let elem: Option<ThumbnailTask>;
diff --git a/crates/npc-fwk/Cargo.toml b/crates/npc-fwk/Cargo.toml
index 07148ee..c5de5d7 100644
--- a/crates/npc-fwk/Cargo.toml
+++ b/crates/npc-fwk/Cargo.toml
@@ -8,6 +8,7 @@ build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+async-channel = "1.6.1"
cairo-rs = "*"
chrono = "0.4.0"
exempi = { version = "2.6.0", git = "https://github.com/hfiguiere/exempi-rs.git", rev="99e8ba5" }
diff --git a/crates/npc-fwk/src/toolkit/mod.rs b/crates/npc-fwk/src/toolkit/mod.rs
index f3d6331..8f43017 100644
--- a/crates/npc-fwk/src/toolkit/mod.rs
+++ b/crates/npc-fwk/src/toolkit/mod.rs
@@ -1,7 +1,7 @@
/*
* niepce - crates/npc-fwk/src/toolkit/mod.rs
*
- * Copyright (C) 2020 Hubert Figuière
+ * Copyright (C) 2020-2021 Hubert Figuière
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,7 +24,17 @@ pub mod movieutils;
pub mod thumbnail;
pub mod widgets;
-pub type Sender<T> = glib::Sender<T>;
+pub type Sender<T> = async_channel::Sender<T>;
/// Wrapper type for the channel tuple to get passed down to the unsafe C++ code.
-pub struct PortableChannel<T>(pub Sender<T>, pub glib::SourceId);
+pub struct PortableChannel<T>(pub Sender<T>);
+
+pub fn thread_context() -> glib::MainContext {
+ glib::MainContext::thread_default()
+ .unwrap_or_else(|| {
+ let ctx = glib::MainContext::new();
+ ctx.push_thread_default();
+ ctx
+ })
+}
+
diff --git a/niepce-main/Cargo.toml b/niepce-main/Cargo.toml
index 7db2629..5c09382 100644
--- a/niepce-main/Cargo.toml
+++ b/niepce-main/Cargo.toml
@@ -6,6 +6,7 @@ build = "build.rs"
edition = "2018"
[dependencies]
+async-channel = "1.6.1"
once_cell = "^1.8.0"
gettext-rs = "0.3.0"
glib = "*"
diff --git a/niepce-main/src/libraryclient/mod.rs b/niepce-main/src/libraryclient/mod.rs
index ecda516..ee35477 100644
--- a/niepce-main/src/libraryclient/mod.rs
+++ b/niepce-main/src/libraryclient/mod.rs
@@ -44,7 +44,7 @@ pub struct LibraryClientWrapper {
}
impl LibraryClientWrapper {
- pub fn new(dir: PathBuf, sender: glib::Sender<LibNotification>) -> LibraryClientWrapper {
+ pub fn new(dir: PathBuf, sender: async_channel::Sender<LibNotification>) -> LibraryClientWrapper {
LibraryClientWrapper {
client: Arc::new(LibraryClient::new(dir, sender)),
}
@@ -65,7 +65,7 @@ pub struct LibraryClient {
}
impl LibraryClient {
- pub fn new(dir: PathBuf, sender: glib::Sender<LibNotification>) -> LibraryClient {
+ pub fn new(dir: PathBuf, sender: async_channel::Sender<LibNotification>) -> LibraryClient {
LibraryClient {
pimpl: ClientImpl::new(dir, sender),
trash_id: 0,
@@ -173,13 +173,18 @@ pub unsafe extern "C" fn lcchannel_new(
cb: extern "C" fn(n: *const LibNotification, data: *mut c_void) -> i32,
data: *mut c_void,
) -> *mut LcChannel {
- let (sender, receiver) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
- let source_id = receiver.attach(None, move |n: LibNotification| {
- let continuation = cb(&n, data) != 0;
- glib::Continue(continuation)
- });
+ let (sender, receiver) = async_channel::unbounded();
+ let event_handler = async move {
+ while let Ok(n) = receiver.recv().await {
+ if cb(&n, data) == 0 {
+ receiver.close();
+ break;
+ }
+ }
+ };
+ glib::MainContext::default().spawn_local(event_handler);
Box::into_raw(Box::new(PortableChannel::<LibNotification>(
- sender, source_id,
+ sender,
)))
}
@@ -188,13 +193,6 @@ pub unsafe extern "C" fn lcchannel_delete(obj: *mut LcChannel) {
Box::from_raw(obj);
}
-#[no_mangle]
-pub unsafe extern "C" fn lcchannel_destroy(obj: *mut LcChannel) {
- if let Some(source) = glib::MainContext::default().find_source_by_id(&(*obj).1) {
- source.destroy();
- }
-}
-
#[no_mangle]
pub unsafe extern "C" fn libraryclient_new(
path: *const c_char,
diff --git a/src/niepce/notificationcenter.cpp b/src/niepce/notificationcenter.cpp
index c1b375d..4cf8aee 100644
--- a/src/niepce/notificationcenter.cpp
+++ b/src/niepce/notificationcenter.cpp
@@ -42,7 +42,6 @@ NotificationCenter::NotificationCenter()
NotificationCenter::~NotificationCenter()
{
- ffi::lcchannel_destroy(m_channel.get());
}
void NotificationCenter::dispatch_lib_notification(const eng::LibNotification *n) const
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]