Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul dependencies and features #208

Merged
merged 58 commits into from
Apr 22, 2024

Conversation

REALERvolker1
Copy link
Contributor

Hey there

I kinda went crazy refactoring dependency and feature-related code.

Here are some issues I (hopefully) resolved:

If you want to wait for v4 for these changes, that's definitely OK with me.

Oh yeah and I switched from futures::future to std::future, I hope ya don't mind ;)

@yavko
Copy link
Member

yavko commented Apr 9, 2024

wow this is a lot

@yavko yavko added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file labels Apr 9, 2024
src/event_listener/shared.rs Outdated Show resolved Hide resolved
src/data/mod.rs Show resolved Hide resolved
src/ctl.rs Outdated Show resolved Hide resolved
@REALERvolker1
Copy link
Contributor Author

I also made a function in event-listener/shared.rs called event_parser_v2 that is unused at the moment, but it is cleaner than the current one. Also, as far as I know, it could be faster.

@REALERvolker1
Copy link
Contributor Author

Alright, I'm pretty sure with this, what do you all think?

@yavko
Copy link
Member

yavko commented Apr 14, 2024

Why'd you get rid of the unsafe impls

@REALERvolker1
Copy link
Contributor Author

I removed the unsafe impls because they seemed unnecessary. When manually testing, I found that the removal did not affect anything. They are basically just glorified Strings, Vecs, and Ints. Was there a specific reason why they were Send + Sync?

@JarKz
Copy link
Contributor

JarKz commented Apr 15, 2024

Did you tested in async environment?

@REALERvolker1
Copy link
Contributor Author

I tested grabbing hyprland data with multiple tasks, both sync and async. I will test with event listener really quick (I have to rewrite that one because I removed it earlier)

@REALERvolker1
Copy link
Contributor Author

It just works for me, here are my files

Cargo.toml
[package]
name = "hyprtest"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
futures-util = "0.3.30"
hyprland = "0.3.13"
hyprland_vlk_git = { version = "0.3.13", path = "../hyprland-rs", package = "hyprland", features = [
    "ahash",
    "parking_lot",
] }
tokio = { version = "1.37.0", features = [
    "rt",
    "macros",
    "parking_lot",
    "time",
    "rt-multi-thread",
] }
main.rs
use futures_util::StreamExt;
use std::{collections::HashMap, io::Write, sync::Arc, time::Duration};

// const FILE_NAME: &str = "./results_hyprland_release.txt";
// use hyprland::{
//     async_closure, data,
//     event_listener::AsyncEventListener,
//     shared::{HyprData, HyprDataActive, HyprError},
//     Result,
// };

const FILE_NAME: &str = "./results_hyprland_vlk_git.txt";
use hyprland_vlk_git::{
    async_closure, data,
    event_listener::AsyncEventListener,
    shared::{HyprData, HyprDataActive, HyprError},
    Result,
};

const TASK_COUNT: u8 = 15;

#[derive(Debug)]
pub enum Message {
    Async(MessageData),
    Sync(MessageData),
}

#[derive(Debug, Default)]
pub struct Body {
    pub sync_m: Option<Message>,
    pub async_m: Option<Message>,
}
impl Body {
    pub fn add_msg(&mut self, msg: Message) {
        match msg {
            Message::Async(_) => self.async_m = Some(msg),
            Message::Sync(_) => self.sync_m = Some(msg),
        }
    }
    pub fn unwrapped(self) -> (Message, Message) {
        (self.sync_m.unwrap(), self.async_m.unwrap())
    }
}

#[derive(Debug)]
pub struct MessageData {
    pub task_id: u8,
    pub is_async: bool,
    pub time: Duration,
    pub monitor: data::Monitor,
    pub workspace: data::Workspace,
    pub devices: data::Devices,
    pub fullscreen_state: data::FullscreenState,
    pub layers: data::Layers,
    pub binds: data::Binds,
}

fn main() -> Result<()> {
    println!("Testing file: {FILE_NAME}");

    let data_test = async move {
        let mut fh = std::fs::File::create(FILE_NAME)?;
        writeln!(fh, "Async\tSync\tEverything is in microseconds")?;

        let (s, mut receiver) = tokio::sync::mpsc::unbounded_channel();
        let sender = Arc::new(s);

        let mut handles = Vec::new();

        let rt = tokio::runtime::Handle::current();

        for id in 1u8..=TASK_COUNT {
            let a_sender = sender.clone();
            let s_sender = sender.clone();

            let a_future = async move {
                let my_time = tokio::time::Instant::now();
                let data = tokio::join!(
                    data::Monitor::get_active_async(),
                    data::Workspace::get_active_async(),
                    data::Devices::get_async(),
                    data::FullscreenState::get_async(),
                    data::Layers::get_async(),
                    data::Binds::get_async(),
                );
                let time = my_time.elapsed();
                let m_data = MessageData {
                    task_id: id,
                    is_async: true,
                    time,
                    monitor: data.0?,
                    workspace: data.1?,
                    devices: data.2?,
                    fullscreen_state: data.3?,
                    layers: data.4?,
                    binds: data.5?,
                };

                a_sender.send((id, Message::Async(m_data))).unwrap();

                Ok::<_, HyprError>(())
            };

            let s_function = move || {
                let my_time = tokio::time::Instant::now();
                let data = (
                    data::Monitor::get_active(),
                    data::Workspace::get_active(),
                    data::Devices::get(),
                    data::FullscreenState::get(),
                    data::Layers::get(),
                    data::Binds::get(),
                );
                let time = my_time.elapsed();
                let m_data = MessageData {
                    task_id: id,
                    is_async: false,
                    time,
                    monitor: data.0?,
                    workspace: data.1?,
                    devices: data.2?,
                    fullscreen_state: data.3?,
                    layers: data.4?,
                    binds: data.5?,
                };

                s_sender.send((id, Message::Sync(m_data))).unwrap();

                Ok::<_, HyprError>(())
            };

            let a = rt.spawn(a_future);
            let s = rt.spawn_blocking(s_function);

            handles.push(a);
            handles.push(s);

            // sleep 1 second to let hyprland discombobulate
            tokio::time::sleep(Duration::from_secs(1)).await;
            println!("Task {id}/{TASK_COUNT} started");
        }

        drop(sender);

        let mut unordered = handles
            .into_iter()
            .collect::<futures_util::stream::FuturesUnordered<_>>();

        while let Some(f) = unordered.next().await {
            if let Err(e) = f {
                println!("Error: {e}");
            }
        }

        let mut messages: HashMap<u8, Body> = HashMap::new();

        while let Some((id, msg)) = receiver.recv().await {
            let entry = messages.entry(id).or_insert(Default::default());
            entry.add_msg(msg);
        }

        // println!("Async: {async_time}us, Sync: {sync_time}us");
        // writeln!(fh, "{async_time}\t{sync_time}")?;

        // Lots of output to stdout
        println!("{:#?}", messages);

        Ok::<_, HyprError>(())
    };

    let listener_test = async move {
        let mut tasks = Vec::new();

        macro_rules! el {
            ($($func:tt),+$(,)?) => {
                $(
                    let task = tokio::spawn(async move {
                        let mut listener = AsyncEventListener::new();

                        listener.$func(async_closure![|m| {
                            println!("{m:?}");
                        }]);

                        listener.start_listener_async().await?;

                        Ok::<_, HyprError>(())
                    });

                    tasks.push(task);
                )+
            };
        }

        el![add_active_monitor_change_handler, add_layer_open_handler];

        futures_util::future::join_all(tasks).await;

        Ok::<_, HyprError>(())
    };

    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()?
        .block_on(listener_test)?;

    Ok(())
}

@yavko
Copy link
Member

yavko commented Apr 15, 2024

I removed the unsafe impls because they seemed unnecessary. When manually testing, I found that the removal did not affect anything. They are basically just glorified Strings, Vecs, and Ints. Was there a specific reason why they were Send + Sync?

Reason for it is so I could use rust async over ffi boundary, if you can get it to work without then you can remove it. Also you could make it a feature flag

@REALERvolker1
Copy link
Contributor Author

Can you provide a code snippet so I can test it over ffi?

@yavko
Copy link
Member

yavko commented Apr 16, 2024

Can you provide a code snippet so I can test it over ffi?

Can't find it but the feature flag should be good enough

@REALERvolker1
Copy link
Contributor Author

Commit 400, GG!

@REALERvolker1
Copy link
Contributor Author

Anything else I should do before you merge?

@yavko
Copy link
Member

yavko commented Apr 17, 2024

Anything else I should do before you merge?

No, i wasn't sure if you were done, I'll do a final review when I get home

Copy link
Member

@yavko yavko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks great

src/event_listener/shared.rs Outdated Show resolved Hide resolved
src/event_listener/shared.rs Outdated Show resolved Hide resolved
src/event_listener/shared.rs Outdated Show resolved Hide resolved
src/shared.rs Outdated Show resolved Hide resolved
@yavko
Copy link
Member

yavko commented Apr 19, 2024

also fix merge conflict

@REALERvolker1
Copy link
Contributor Author

Hey sorry I was busy. I couldn't figure out how to resolve it so I just manually did the changes 😅

@yavko
Copy link
Member

yavko commented Apr 20, 2024

fixed conflict for you, also plz fix other requests

@REALERvolker1
Copy link
Contributor Author

Hey sorry about that I have been super busy with other stuff. I got that stuff though

@REALERvolker1
Copy link
Contributor Author

REALERvolker1 commented Apr 22, 2024

I would be willing to add more library usage examples in another pull request, this pr is big enough already

@yavko
Copy link
Member

yavko commented Apr 22, 2024

I would be willing to add more library usage examples in another pull request, this pr is big enough already

Sick thx

@yavko yavko merged commit 13733ae into hyprland-community:master Apr 22, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove async-trait Replace strum with derive_more Switch to fixed dependency versions
3 participants