code: func computeAppResources(isolators types.Isolators) (appResources, error) {
  	res := appResources{}
  	var err error
  
  	withIsolator := func(name string, f func() error) error {
  		ok, err := cgroup.IsIsolatorSupported(name)
  		if err != nil {
  			return errwrap.Wrapf("could not check for isolator "+name, err)
  		}
  
  		if !ok {
  			fmt.Fprintf(os.Stderr, "warning: resource/%s isolator set but support disabled in the kernel, skipping\n", name)
  			return nil
  		}
  
  		return f()
  	}
  
  	for _, isolator := range isolators {
  		if err != nil {
  			return res, err
  		}
  
  		switch v := isolator.Value().(type) {
  		case *types.ResourceMemory:
  			err = withIsolator("memory", func() error {
  				if v.Limit() == nil {
  					return nil
  				}
  
  				val := uint64(v.Limit().Value())
  				res.MemoryLimit = &val
  				return nil
  			})
  		case *types.ResourceCPU:
  			err = withIsolator("cpu", func() error {
  				if v.Limit() == nil {
  					return nil
  				}
  				if v.Limit().Value() > MaxMilliValue {
  					return fmt.Errorf("cpu limit exceeds the maximum millivalue: %v", v.Limit().String())
  				}
  
  				val := uint64(v.Limit().MilliValue() / 10)
  				res.CPUQuota = &val
  				return nil
  			})
  		case *types.LinuxCPUShares:
  			err = withIsolator("cpu", func() error {
  				val := uint64(*v)
  				res.LinuxCPUShares = &val
  				return nil
  			})
  		case *types.LinuxOOMScoreAdj:
  			val := int(*v)
  			res.LinuxOOMScoreAdjust = &val
  		}
  	}
  
  	return res, err
  }
docs: // computeAppResources processes any isolators that manipulate cgroups.