-
Notifications
You must be signed in to change notification settings - Fork 22
Statically declaring handler functions #238
Comments
This should work, as a means to statically allocate the listeners: struct Bar;
struct Foo {
first: Option<unsafe extern "C" fn(&mut Bar, *mut ())>
}
static mut foo: Foo = Foo { first: None }; This will compile down to a nullable pointer, while also being safe to check against at runtime. All we need is to write the boiler plate code that takes a builder that replaces the static instance with those functions and then re-write the |
Adding the unsound tag until I have looked at the code in practice and ensured it is sound. |
One issue with this approach is that it effectively adds two code paths to arrive at the same place. Currently, we just use boxed We could change the resource creation to instead of returning a However we still need a struct that has pointers to static functions passed to the builder for static manager handlers (which again, is mutually exclusive with the dynamic option because it doesn't make sense to listen for it twice, especially with our memory model) and that now means we need to define the signature for these callback functions twice: once in the struct for static allocation and again in the trait for dynamic allocation. If there is a way to allow passing a |
Actually now that I work on this more I've come to the rather startling conclusion that the manager handlers don't actually need to be dynamically dispatched ever! There is only ever one variant and the data you want to store in them can just as easily be stored in the global compositor state instead. This means you'll never have to pass This can also change the return types of the managers to not be a box but rather a builder result that can either be I think the easiest way to attack this whole problem is splitting this into two issues: one is that the managers should always be static, and the second being you should be able to choose for the resource handlers. See #239. |
Currently the only way to declare new handler functions from
ManagerHandler
s is to dynamically allocate listeners along with state structs.However, often it's not necessary since the same handler function is used and is part of a zero sized type (so there's no state). So it should be possible to avoid allocation in this case.
This can be achieved by adding a new option to the
compositor::Builder
that takes a<manager_type>::Builder
for each function. Once it takes a static builder it will be a runtime error (at builder time) to construct a dynamic manager handler for that resource.For actually allocating that static handler so that we can access the handler functions afterwards (which currently is achieved by using a
repr(C)
boxed struct) we could have the manager handler builder passed to us from the compositor builder internally build out to arepr(C)
type that is somehow statically allocated (and implements the manager handler trait to call the functions it has as members).Another option is to use a
lazy_static!
internally, but that incurs branching overhead on each access even if it is safe.The last problem is how to solve this in the context of
wayland_listener!
, which currently assumes a handler is dynamically allocated along with its listener state. Ultimately the "correct" option might be to take all the$code
that currently exists there and abstract it out to a function that takes an&ManagerTrait
. That way it can reference a dynamically allocated or static object.The text was updated successfully, but these errors were encountered: