github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/wasm/store_module_list.go (about)

     1  package wasm
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/wasilibs/wazerox/api"
     8  )
     9  
    10  // deleteModule makes the moduleName available for instantiation again.
    11  func (s *Store) deleteModule(m *ModuleInstance) error {
    12  	s.mux.Lock()
    13  	defer s.mux.Unlock()
    14  
    15  	// Remove this module name.
    16  	if m.prev != nil {
    17  		m.prev.next = m.next
    18  	}
    19  	if m.next != nil {
    20  		m.next.prev = m.prev
    21  	}
    22  	if s.moduleList == m {
    23  		s.moduleList = m.next
    24  	}
    25  	// Clear the m state so it does not enter any other branch
    26  	// on subsequent calls to deleteModule.
    27  	m.prev = nil
    28  	m.next = nil
    29  
    30  	if m.ModuleName != "" {
    31  		delete(s.nameToModule, m.ModuleName)
    32  
    33  		// Shrink the map if it's allocated more than twice the size of the list
    34  		newCap := len(s.nameToModule)
    35  		if newCap < nameToModuleShrinkThreshold {
    36  			newCap = nameToModuleShrinkThreshold
    37  		}
    38  		if newCap*2 <= s.nameToModuleCap {
    39  			nameToModule := make(map[string]*ModuleInstance, newCap)
    40  			for k, v := range s.nameToModule {
    41  				nameToModule[k] = v
    42  			}
    43  			s.nameToModule = nameToModule
    44  			s.nameToModuleCap = newCap
    45  		}
    46  	}
    47  	return nil
    48  }
    49  
    50  // module returns the module of the given name or error if not in this store
    51  func (s *Store) module(moduleName string) (*ModuleInstance, error) {
    52  	s.mux.RLock()
    53  	defer s.mux.RUnlock()
    54  	m, ok := s.nameToModule[moduleName]
    55  	if !ok {
    56  		return nil, fmt.Errorf("module[%s] not instantiated", moduleName)
    57  	}
    58  	return m, nil
    59  }
    60  
    61  // registerModule registers a ModuleInstance into the store.
    62  // This makes the ModuleInstance visible for import if it's not anonymous, and ensures it is closed when the store is.
    63  func (s *Store) registerModule(m *ModuleInstance) error {
    64  	s.mux.Lock()
    65  	defer s.mux.Unlock()
    66  
    67  	if s.nameToModule == nil {
    68  		return errors.New("already closed")
    69  	}
    70  
    71  	if m.ModuleName != "" {
    72  		if _, ok := s.nameToModule[m.ModuleName]; ok {
    73  			return fmt.Errorf("module[%s] has already been instantiated", m.ModuleName)
    74  		}
    75  		s.nameToModule[m.ModuleName] = m
    76  		if len(s.nameToModule) > s.nameToModuleCap {
    77  			s.nameToModuleCap = len(s.nameToModule)
    78  		}
    79  	}
    80  
    81  	// Add the newest node to the moduleNamesList as the head.
    82  	m.next = s.moduleList
    83  	if m.next != nil {
    84  		m.next.prev = m
    85  	}
    86  	s.moduleList = m
    87  	return nil
    88  }
    89  
    90  // Module implements wazero.Runtime Module
    91  func (s *Store) Module(moduleName string) api.Module {
    92  	m, err := s.module(moduleName)
    93  	if err != nil {
    94  		return nil
    95  	}
    96  	return m
    97  }