{"action":"created","issue":{"url":"https://api.github.com/repos/vberger/wayland-client-rs/issues/59","repository_url":"https://api.github.com/repos/vberger/wayland-client-rs","labels_url":"https://api.github.com/repos/vberger/wayland-client-rs/issues/59/labels{/name}","comments_url":"https://api.github.com/repos/vberger/wayland-client-rs/issues/59/comments","events_url":"https://api.github.com/repos/vberger/wayland-client-rs/issues/59/events","html_url":"https://github.com/vberger/wayland-client-rs/issues/59","id":168594712,"number":59,"title":"[discussion] Lib design","user":{"login":"vberger","id":3009227,"avatar_url":"https://avatars.githubusercontent.com/u/3009227?v=3","gravatar_id":"","url":"https://api.github.com/users/vberger","html_url":"https://github.com/vberger","followers_url":"https://api.github.com/users/vberger/followers","following_url":"https://api.github.com/users/vberger/following{/other_user}","gists_url":"https://api.github.com/users/vberger/gists{/gist_id}","starred_url":"https://api.github.com/users/vberger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vberger/subscriptions","organizations_url":"https://api.github.com/users/vberger/orgs","repos_url":"https://api.github.com/users/vberger/repos","events_url":"https://api.github.com/users/vberger/events{/privacy}","received_events_url":"https://api.github.com/users/vberger/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/vberger/wayland-client-rs/labels/C-client","name":"C-client","color":"fbca04"},{"url":"https://api.github.com/repos/vberger/wayland-client-rs/labels/C-scanner","name":"C-scanner","color":"fbca04"},{"url":"https://api.github.com/repos/vberger/wayland-client-rs/labels/C-server","name":"C-server","color":"fbca04"},{"url":"https://api.github.com/repos/vberger/wayland-client-rs/labels/T-cleanup","name":"T-cleanup","color":"207de5"},{"url":"https://api.github.com/repos/vberger/wayland-client-rs/labels/T-enhancement","name":"T-enhancement","color":"207de5"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/vberger/wayland-client-rs/milestones/4","html_url":"https://github.com/vberger/wayland-client-rs/milestones/v0.7","labels_url":"https://api.github.com/repos/vberger/wayland-client-rs/milestones/4/labels","id":1915198,"number":4,"title":"v0.7","description":"","creator":{"login":"vberger","id":3009227,"avatar_url":"https://avatars.githubusercontent.com/u/3009227?v=3","gravatar_id":"","url":"https://api.github.com/users/vberger","html_url":"https://github.com/vberger","followers_url":"https://api.github.com/users/vberger/followers","following_url":"https://api.github.com/users/vberger/following{/other_user}","gists_url":"https://api.github.com/users/vberger/gists{/gist_id}","starred_url":"https://api.github.com/users/vberger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vberger/subscriptions","organizations_url":"https://api.github.com/users/vberger/orgs","repos_url":"https://api.github.com/users/vberger/repos","events_url":"https://api.github.com/users/vberger/events{/privacy}","received_events_url":"https://api.github.com/users/vberger/received_events","type":"User","site_admin":false},"open_issues":1,"closed_issues":0,"state":"open","created_at":"2016-08-01T08:44:26Z","updated_at":"2016-08-01T08:44:32Z","due_on":null,"closed_at":null},"comments":4,"created_at":"2016-08-01T08:38:49Z","updated_at":"2016-08-03T20:32:55Z","closed_at":null,"body":"This has bugged me for some time now, so I'm asking for outside input.\r\n\r\nThe wayland C library has a very callback oriented design: when you create an object, you register several functions to handle its events, in the form\r\n\r\n```c\r\nvoid event_vallback(wl_proxy* object, void* user_data, ...) { /* .. */ }\r\n```\r\n\r\nThis works in C because the language is ok with having pointers all other the place and shared mutable globals and all, which is obviously not an option with Rust.\r\n\r\nMy first attempt at this lib (`v0.1` and `v0.2`) was to just copy this design, and let the user provide closures for the callbacks. For safety reasons, closures had to be `Send+Sync+'static`, because wayland is supposed to be threadsafe, which led to a nightmare to handle program state, with lots of `Arc<Mutex<_>>` even on single-threaded programs, which is obviously bad.\r\n\r\nSecond attempt (`v0.3` to `v0.6`) wraps the events into an `EventIterator`, letting the user of the lib handle the dispatching themselves, and thus side stepping the issue with previous attempts.\r\n\r\nHowever this approach has its share of issues:\r\n\r\n- deeply nested enums to represent the events\r\n- no easy way to use a protocol extension but to patch `wayland-client`, as the events must be integrated in the `Event` enum\r\n- This design does not match at all for `wayland-server` : server-side, the lifetime of all protocol objects is controlled by the client, and thus is not really representable server-side out of a callback-based design.\r\n\r\nAll this makes me not completely happy with the current design. Especially given I'd like as much as possible to share a common design between `wayland-client` and `wayland-server`, and make it easy to use 3rd party protocol extensions. As such, I'm thinking about going back to callback-based design, but different from the first one.\r\n\r\nRather go by traits to define handlers. Probably one trait for each wayland object. The use would then give to the lib one or several objects implementing the appropriate handler traits, and let it do the dispatching of events. The interest of this approach is that as the lib has ownership of the object, all handler methods can take `&mut self` without need for more synchronization mechanisms, the rest is fully guaranteed by the wayland C library.\r\n\r\nThe two central methods of the `EventLoop` interface would probably be something like that\r\n\r\n```rust\r\nimpl<S> EventLoop<S> {\r\n    /// Handle all wayland pending events and dispatch them to appropriate handlers\r\n    fn dispatch(&smut self) { /* ... */ }\r\n\r\n    /// Get access to the internal state, to handle non-wayland events for example\r\n    fn get_state(&mut self) -> &mut S { /* ... */ }\r\n}\r\n```\r\n\r\nHere, the Rust borrowing rules can guarantee that no callback can be called while a reference to the state is held elsewhere, as callbacks are called during the execution of the `dispatch(...)` method. Note that the wayland C library also provide the necessary mechanisms to have more than one event-loop, and assign each wayland object to the appropriate one (for example to handle keyboard and drawing events in different threads).\r\n\r\nNow, I have still some unresolved questions about this:\r\n\r\n- Is this a good idea at all?\r\n- How to handle the registration of which handler traits are implemented and should be dispatched for?\r\n- Could it be possible to attache several state objects to the same event loop, each implementing a different subset of the handler traits?\r\n- Certainly several other questions that have not yet popped up..."},"comment":{"url":"https://api.github.com/repos/vberger/wayland-client-rs/issues/comments/237363710","html_url":"https://github.com/vberger/wayland-client-rs/issues/59#issuecomment-237363710","issue_url":"https://api.github.com/repos/vberger/wayland-client-rs/issues/59","id":237363710,"user":{"login":"Timidger","id":3515754,"avatar_url":"https://avatars.githubusercontent.com/u/3515754?v=3","gravatar_id":"","url":"https://api.github.com/users/Timidger","html_url":"https://github.com/Timidger","followers_url":"https://api.github.com/users/Timidger/followers","following_url":"https://api.github.com/users/Timidger/following{/other_user}","gists_url":"https://api.github.com/users/Timidger/gists{/gist_id}","starred_url":"https://api.github.com/users/Timidger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Timidger/subscriptions","organizations_url":"https://api.github.com/users/Timidger/orgs","repos_url":"https://api.github.com/users/Timidger/repos","events_url":"https://api.github.com/users/Timidger/events{/privacy}","received_events_url":"https://api.github.com/users/Timidger/received_events","type":"User","site_admin":false},"created_at":"2016-08-03T20:32:55Z","updated_at":"2016-08-03T20:32:55Z","body":"Sounds good. Though it's too bad `wayland-server` isn't usable yet, it does make feel better knowing that I wasn't crazy and I couldn't actually bind the protocol I wanted. I'll keep an eye on this project in the coming weeks."}}
{"actor":{"display_login":"Timidger"}}