github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/experimental/close.go (about)

     1  package experimental
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/bananabytelabs/wazero/internal/close"
     7  )
     8  
     9  // CloseNotifier is a notification hook, invoked when a module is closed.
    10  //
    11  // Note: This is experimental progress towards #1197, and likely to change. Do
    12  // not expose this in shared libraries as it can cause version locks.
    13  type CloseNotifier interface {
    14  	// CloseNotify is a notification that occurs *before* an api.Module is
    15  	// closed. `exitCode` is zero on success or in the case there was no exit
    16  	// code.
    17  	//
    18  	// Notes:
    19  	//   - This does not return an error because the module will be closed
    20  	//     unconditionally.
    21  	//   - Do not panic from this function as it doing so could cause resource
    22  	//     leaks.
    23  	//   - While this is only called once per module, if configured for
    24  	//     multiple modules, it will be called for each, e.g. on runtime close.
    25  	CloseNotify(ctx context.Context, exitCode uint32)
    26  }
    27  
    28  // ^-- Note: This might need to be a part of the listener or become a part of
    29  // host state implementation. For example, if this is used to implement state
    30  // cleanup for host modules, possibly something like below would be better, as
    31  // it could be implemented in a way that allows concurrent module use.
    32  //
    33  //	// key is like a context key, stateFactory is invoked per instantiate and
    34  //	// is associated with the key (exposed as `Module.State` similar to go
    35  //	// context). Using a key is better than the module name because we can
    36  //	// de-dupe it for host modules that can be instantiated into different
    37  //	// names. Also, you can make the key package private.
    38  //	HostModuleBuilder.WithState(key any, stateFactory func() Cleanup)`
    39  //
    40  // Such a design could work to isolate state only needed for wasip1, for
    41  // example the dirent cache. However, if end users use this for different
    42  // things, we may need separate designs.
    43  //
    44  // In summary, the purpose of this iteration is to identify projects that
    45  // would use something like this, and then we can figure out which way it
    46  // should go.
    47  
    48  // CloseNotifyFunc is a convenience for defining inlining a CloseNotifier.
    49  type CloseNotifyFunc func(ctx context.Context, exitCode uint32)
    50  
    51  // CloseNotify implements CloseNotifier.CloseNotify.
    52  func (f CloseNotifyFunc) CloseNotify(ctx context.Context, exitCode uint32) {
    53  	f(ctx, exitCode)
    54  }
    55  
    56  // WithCloseNotifier registers the given CloseNotifier into the given
    57  // context.Context.
    58  func WithCloseNotifier(ctx context.Context, notifier CloseNotifier) context.Context {
    59  	if notifier != nil {
    60  		return context.WithValue(ctx, close.NotifierKey{}, notifier)
    61  	}
    62  	return ctx
    63  }