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

PoC: Introduce host modules #484

Closed
wants to merge 7 commits into from
Closed

Conversation

evacchi
Copy link
Collaborator

@evacchi evacchi commented Aug 22, 2024

This is a PoC meant for discussion, it is not necessarily meant for merging.

Addresses #482 and potentially #464.

This PR refactors Wasip1 as a means to show an example and it introduces (temporarily in the wasi package) a few types:

  • HostModule and HostModule.Builder. The HostModule interface represents a bundle of FunctionSignatures with a name (the name of the module). The HostModule.Builder returns a concrete implementation called FunctionSignatureBundle.

  • HostModuleInstance is an interface representing an instance of a HostModule; it owns a reference to its host module "prototype" and it collects the HostFunctions that belong to that instance, matching with the signatures given in the HostModule. The HostModuleInstance can be also close()d (and potentially other lifecycle actions could be added, e.g. instantiate()). The HostModuleInstance.Builder constructs a concrete implementation called HostFunctionBundle.

  • FunctionSignature is a representation of a (Host) Function's signature. This is essentially a different representation for a FunctionImport so the two might collapse somehow, or at least share an ancestor.

  • FunctionSignatureBundle implements HostModule as explained above.

  • HostFunctionBundle implements HostModuleInstance as explained above.

A HostModule can be constructed using the builder as such:

        var wasip1 = HostModule.builder(MODULE_NAME)
                .withFunctionSignature("adapter_close_badfd", i32_t, i32_t)
                .withFunctionSignature("adapter_open_badfd", i32_t, i32_t)
                .withFunctionSignature("args_get", i32_i32_t, i32_t)
                // ...
               .build()

Notice how the HostModule does not define any implementation for the functions. The implementations are given at instantiation time. In order to create a HostModuleInstance we can use the HostModuleInstance.Builder as such:

        var inst = new WasiPreview1(...);
        var wasip1Instance HostModuleInstance.builder(hostModule)
                .bind("adapter_close_badfd", inst::adapterCloseBadfd)
                .bind("adapter_open_badfd", inst::adaptedOpenBadfd)
                .bind("args_get", inst::argsGet)
                // ...
                .build();

Notice:

  1. we need to instantiate an object instance of WasiPreview1 so that such instance is bound to the lifecycle of the HostModuleInstance.
  2. we can also optionally specify a close handler, that will be called to cleanup resources if any:
        var inst = new WasiPreview1(...);
        var wasip1Instance HostModuleInstance.builder(hostModule)
                .bind("adapter_close_badfd", inst::adapterCloseBadfd)
                .bind("adapter_open_badfd", inst::adaptedOpenBadfd)
                .bind("args_get", inst::argsGet)
                // ...
                .onClose(inst::close)
                .build();
  1. Nothing in the API prevents from instantiating multiple objects and providing separate implementations for each function
  2. the onClose handler is a simple Runnable, so it is possible to e.g. close() multiple object instances if necessary:
        var inst = new WasiPreview1(...);
        var altImpl = new CustomImpl(...);
        var wasip1Instance HostModuleInstance.builder(hostModule)
                .bind("adapter_close_badfd", inst::adapterCloseBadfd)
                .bind("adapter_open_badfd", altImpl::adaptedOpenBadfd) // altImpl used here
                .bind("args_get", inst::argsGet)
                // ...
                .onClose(() -> { inst.close(); altImpl.close(); })
                .build();

This API is slightly more verbose than just creating the HostFunctions explicitly, however, it can be code-generated, or a reflection-based API can be provided on top of it, as described in #482, except:

  1. the HostModule could be constructed from an interface
  2. the HostModuleInstance could be then constructed from any object implementing that interface

@evacchi evacchi requested review from andreaTP, electrum and bhelx and removed request for andreaTP and electrum August 22, 2024 15:50
Signed-off-by: Edoardo Vacchi <[email protected]>
Signed-off-by: Edoardo Vacchi <[email protected]>
Comment on lines +15 to +16
List<ValueType> paramTypes,
List<ValueType> returnTypes) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

note to self: we already have FunctionType!

@evacchi
Copy link
Collaborator Author

evacchi commented Sep 23, 2024

I am closing this because it slightly drifted and for now it is not necessary.

@evacchi evacchi closed this Sep 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant