Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Add g_idle_add() #47

Merged
merged 8 commits into from
Jun 19, 2015
Merged

Add g_idle_add() #47

merged 8 commits into from
Jun 19, 2015

Conversation

vojtechkral
Copy link
Contributor

No description provided.

@GuillaumeGomez
Copy link
Member

I don't get what you want to do. If the function g_idle_add isn't binded, why uncommenting it ?

@vojtechkral
Copy link
Contributor Author

I was expecting it to be used soon. If you want the whole thing at once, that's allright too...

@GuillaumeGomez
Copy link
Member

I'd prefer, otherwise it doesn't make sense. If didn't comment all unused functions, the only we'd have to know they're not binded would be with rust compiler warnings. Not very wonderful...

I'll let this PR open. When you have binded the function, please notify me.

Thanks in advance ! =D

@gkoz
Copy link
Member

gkoz commented Jun 15, 2015

I don't see anything wrong with having unused definitions in the sys crates (as long as they're correct).

Here, Rust is capable of expressing the SourceFunc type so substituting a gpointer for it doesn't look good.

@GuillaumeGomez
Copy link
Member

@gkoz: It's mostly to avoid warnings and make easier the future bindings. Otherwise, we could just uncomment all the non-binded functions and say it's fine. Or maybe I didn't understand the point here ?

@gkoz
Copy link
Member

gkoz commented Jun 15, 2015

There hardly can be such thing as an unused published member of a library, so there won't be any warnings.

Uncommenting everything wholesale would be problematic because someone has to review the definitions so it makes sense to avoid that effort while there's no need for it.

@GuillaumeGomez
Copy link
Member

Hum... Okay. But then why not providing directly the binding for this function ? That's where I'm lost.

@vojtechkral
Copy link
Contributor Author

I'll try to add the binding.

@gkoz Regarding GSourceFunc, I was basically copying what can be seen in g_timeout_add() - GSourceFunc is commented and a version with gpointer is used instead. Is there a reason for this?

@GuillaumeGomez
Copy link
Member

@vojtechkral: It was to avoid boring stuff haha (super explanation !). It was a (successfull) test I made, I wanted to do the same with a closure but for now there is an ICE in rust for it and I didn't try to avoid it (I'm working on cairo's documentation and rustdoc). For me, it's totally fine, it allows to avoid annoying stuff but I'm not sure that's the best solution... I'll dig to find more information.

@gkoz
Copy link
Member

gkoz commented Jun 15, 2015

This is why we shouldn't be committing hacks. People try to stay consistent with the hacks, leading to more hacks.

@GuillaumeGomez
Copy link
Member

Well, that's not really a hack.

@vojtechkral
Copy link
Contributor Author

Ok, I added a binding.

Using only a fn() for now, because I have no idea how to manage the lifetime of a closure. Glib doesn't seem to provide any means for this like it does with signals.

Here's code I used to test the thing: https://gist.github.com/vojtechkral/ea7112bff8eaff0d0ff2

@GuillaumeGomez
Copy link
Member

"to test the thing". It sounds very scary that way haha. Thanks a lot for your work ! I wait for travis and appveyor's confirmation and I merge.

@vojtechkral
Copy link
Contributor Author

Wait wait I don't think this is ready to merge yet, there's a commented-out function header with closure which I'm not sure what to do about yet.

A version with only a fn() would probably be ok though, at least for now...

@GuillaumeGomez
Copy link
Member

If you manage to make work a closure by passing it as a pointer, it could be nice. You can try if you feel like it. ;-)

@gkoz
Copy link
Member

gkoz commented Jun 16, 2015

You want g_idle_add_full actually, not g_idle_add. It's similar to g_signal_connect_data. Only, there we box a closure twice and give Box<Box<Fn()>> as user_data, but here I'm leaning toward Box<RefCell<Box<FnMut>>>: the added RefCell will make sure we don't violate the mutability guarantees.

@vojtechkral
Copy link
Contributor Author

Right, thanks. I'll have a look at how the signal closures are done...

@vojtechkral
Copy link
Contributor Author

@gkoz In the gtk signals.rs, I don't understand how Box<Box<Fn>> can be cast as a pointer to function for C... Isn't it a double pointer?

@gkoz
Copy link
Member

gkoz commented Jun 16, 2015

Note also how the event handlers return the Inhibit newtype on the Rust side to make the meaning of the return boolean explicit. This case calls for a similar type, the glib docs suggest Continue, it could also be Repeat.

@gkoz
Copy link
Member

gkoz commented Jun 16, 2015

@vojtechkral

In the gtk signals.rs, I don't understand how Box<Box> can be cast as a pointer to function for C... Isn't it a double pointer?

The closures are passed as user_data, any cdecl functions needed -- the callbacks (that in turn call the closures) and the destructor are plain functions.

@vojtechkral
Copy link
Contributor Author

Okay, I think I get it, will try to implement...

@vojtechkral
Copy link
Contributor Author

This is the code so far. Problem is if I try to use the FnMut() version instead, I get

error: cannot borrow immutable `Box` content as mutable

in the trampoline function.

PS. I'll add a proper return type later.

@gkoz
Copy link
Member

gkoz commented Jun 16, 2015

That's weird but can be sidestepped by using the DerefMut trait explicitly: http://is.gd/lOw3HJ, v2: http://is.gd/fqH1kr
Don't forget the 'static bound BTW. I've been guilty of this too. The inner box needs to be Box<FnMut() + 'static>.

@vojtechkral
Copy link
Contributor Author

It works now, yay :-)

In the future, timeout_func.rs and maybe others would probably benefit from some of the machinery in Idle. Maybe merge? Not sure how to structure this. Also documentation...


//! callback idle functions

pub mod idle {
Copy link
Member

Choose a reason for hiding this comment

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

This nested module seems redundant.

unsafe {
// Box::from_raw API stability workaround
let ptr = ptr as *mut RefCell<Box<FnMut() -> Continue + 'static>>;
let _: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = ::std::mem::transmute(ptr);
Copy link
Member

Choose a reason for hiding this comment

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

You're importing transmute already so the full path isn't needed.

@gkoz
Copy link
Member

gkoz commented Jun 16, 2015

We might take a moment to think how this and the timeout functions will work together, the implications for the module name so we don't have to rename it ina week.

@vojtechkral
Copy link
Contributor Author

Sure, by all means.

@gkoz
Copy link
Member

gkoz commented Jun 17, 2015

One way to approach this could be to name the module source and the function idle_add, move the timeout::add function into it as timeout_add, and any other g_source_* bindings could be added in the future.

@GuillaumeGomez
Copy link
Member

@gkoz: Isn't it possible to just move every non method function in a global namespace (like source if you want) ? It could be nice to give an easy access to "global" gtk functions.

@gkoz
Copy link
Member

gkoz commented Jun 17, 2015

@GuillaumeGomez This is mostly about the internal organization.

I don't mind reexports in the topmost namespace. I've come to believe that the flat namespace is a necessary evil after all, because that's what other language bindings do and it's very hard to design some structure that will make sense from all points of view. The module might not even be public.

@GuillaumeGomez
Copy link
Member

@gkoz: My bad, I thought you wanted to create a file and a namespace for each type of global gtk function. It seemed a bit too much for me. Splitting these functions inside modules is good, we'll just reexport them as one.

I don't think the flat namespace is "evil". However, if you have a better solution in mind, I'd be glad to know it ! ;-)

@gkoz
Copy link
Member

gkoz commented Jun 17, 2015

My current preference is that the types and functions a user might need would be reexported at the top. (This will likely mean that the constants will have long names with just G_ or GTK_ stripped.) The "internals" stuff used by the bindings (utilities like glib::translate) would not be reexported.

The traits and some essential types would put into prelude and we would recommend glob-importing the prelude only.

@GuillaumeGomez
Copy link
Member

Yes, that's what I meant. I think we don't understand each other on this. Nevermind haha.

@vojtechkral
Copy link
Contributor Author

Naming the module source makes sense, but only if you know GSourceFunc, which I don't think users do, mostly. However, all these functions are part of The Main Event Loop , so maybe naming the module mainloop would make sense? As in mainloop::add_idle(|| { ... }) etc.

Just my two cents

@gkoz
Copy link
Member

gkoz commented Jun 17, 2015

They call it MainContext mostly though. And it's a bit of a rabbit hole from there. But since we're going to reexport the functions at the crate root, the users won't have to hunt in the source module for them.

Oh, sorry, there is a MainLoop, yes. The point stands, you attach sources to a MainContext, so it's all intertangled.

@vojtechkral
Copy link
Contributor Author

I can convert the idle module + I suppose the timeout module to the flat model, but I reckon the scope of this PR shouldn't be broader than that right?

@gkoz
Copy link
Member

gkoz commented Jun 17, 2015

Yeah, the idle_add and a similar reimplementation of timeout_add seem sufficient for now.

@vojtechkral
Copy link
Contributor Author

Ok, done. Test code also updated. Hope everything's ok.

edit: Sorry for typo in commit msg...

}

const G_PRIORITY_DEFAULT: i32 = 0;
const G_PRIORITY_DEFAULT_IDLE: i32 = 200;
Copy link
Member

Choose a reason for hiding this comment

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

We drop the G and similar prefixes everywhere.

///
/// # Examples
///
/// ```
Copy link
Member

Choose a reason for hiding this comment

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

Could you also please mark the examples with ignore so cargo test won't complain that they don't compile (or alternatively make them compile)?
http://doc.rust-lang.org/book/documentation.html#running-documentation-tests

@vojtechkral
Copy link
Contributor Author

Ok, I've added ignore. Making the test compile would make them much longer and I don't even know if it can be done without gtk...

@gkoz
Copy link
Member

gkoz commented Jun 19, 2015

Good job, thanks!
ping @GuillaumeGomez

@GuillaumeGomez
Copy link
Member

@gkoz: Pong ! Thanks for taking care of this PR too !
@vojtechkral: Thanks for your work, I merge !

GuillaumeGomez added a commit that referenced this pull request Jun 19, 2015
@GuillaumeGomez GuillaumeGomez merged commit d1fc919 into gtk-rs:master Jun 19, 2015
@vojtechkral vojtechkral deleted the idle branch June 19, 2015 14:03
@vojtechkral
Copy link
Contributor Author

@gkoz Out of curiosity, what was the reason for the 'static bound again?

@gkoz
Copy link
Member

gkoz commented Jun 23, 2015

@vojtechkral We pass the ownership of the closure to the library, its lifetime is outside our control, it could outlive everything. There are ways like this to make some lifetime guarantees, but they're not terribly ergonomic either.

@vojtechkral
Copy link
Contributor Author

@gkoz Okay, thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants