jazzfool / reclutch

Rust UI Core
Other
157 stars 4 forks source link

Refactoring + reorganizing project parts #2

Closed fogti closed 4 years ago

fogti commented 4 years ago

Reference: https://www.reddit.com/r/rust/comments/dr04ce/reclutch_a_simple_rust_ui_foundation/f6e1bu2/

I think it is a good idea to split the reclutch sources into multiple independent parts, because the Event traits+structs have no dependencies with the widget+gfx backend.

Additional notes regarding reclutch-event

That split is necessary to prevent the atomics+locking costs when the signal-handling only happens inside one thread (GUI-events often only happen inside one dedicated thread), and, on the other hand, allow cross-thread events (non-GUI-events often spread over various threads. crossbeam-channel is often preferred for simple thread communication via message-passing, but doesn't work (as far as I know) when multiple independent listeners need to listen on the same events (broadcasting)). It is neat to cover both inside a common interface. I tried experimenting with archery, but that won't really cover this use case neatly.

jazzfool commented 4 years ago

Looks good so far.

jazzfool commented 4 years ago

Also I believe cleanup can be optimized; right now we look for the lowest index, which is O(n), but if we keep track of the lowest index through peek, add/remove_listener then we can speed up that part of the cleanup process.

fogti commented 4 years ago

When we call cleanup after every peek, we can assume more about the state of the listeners map. Edit: ok. I tried it and ran it through the benchmarks. It doesn't improve the timings. code, better code

jazzfool commented 4 years ago

Another approach is to use BTreeMap, it would reduce iter().min() time from O(n) to O(log n).

I've branched the current code and I've split the code into a workspace in master. Namely I want to keep the original event implementation by default within the core package and have advanced events as a feature of the core package.

fogti commented 4 years ago

Another approach is to merge the listeners+events, e.g. transform from Struct-of-Arrays to Array-of-Structs. Edit: Tested, worse timings.

I tested BTreeMap. It is slower than SlotMap.

fogti commented 4 years ago

P.S. rebase of #3 against #2 : zserik:count-down-action

fogti commented 4 years ago

Another thing which would be interesting: A more advanced usage of events would be filtered cascading, e.g. all events from Event A, such that predicate/Fn f returns true are automatically cloned and pushed to Event B (and maybe dropped from Event A).

Another use case would be waiting for one of serval event (queues) to become ready. I implemented a POC using crossbeam-channel here

Edit: done.

jazzfool commented 4 years ago

I think rather than cascading events, there could be a specialized implementation of EventListen based on multiple sub-listeners, where it listens to multiple events at one time, and when peek is called it concatenates all the events from each of it's sub-listeners.

We should also be thinking about nonts performance. The Rc/RefCell has some overhead which may become noticeable in a very large UI.

fogti commented 4 years ago

ok, I opened a new draft PR.

another suggestion: maybe rename the derive(Widget) to derive(WidgetChildren) for better consistency?