func (a *allocatorHelper) takeIdlePackages() {
	a.Debug("* takeIdlePackages()...")
	offline := a.sys.Offlined()
	pkgs := pickIds(a.sys.PackageIDs(),
		func(id idset.ID) bool {
			cset := a.topology.pkg[id].Difference(offline)
			return cset.Intersection(a.from).Equals(cset)
		})
	sort.Slice(pkgs,
		func(i, j int) bool {
			if res := a.topology.cpuPriorities.cmpCPUSet(a.topology.pkg[pkgs[i]], a.topology.pkg[pkgs[j]], a.prefer, -1); res != 0 {
				return res > 0
			}
			return pkgs[i] < pkgs[j]
		})
	a.Debug(" => idle packages sorted by preference: %v", pkgs)
	for _, id := range pkgs {
		cset := a.topology.pkg[id].Difference(offline)
		a.Debug(" => considering package %v (#%s)...", id, cset)
		if a.cnt >= cset.Size() {
			a.Debug(" => taking package %v...", id)
			a.result = a.result.Union(cset)
			a.from = a.from.Difference(cset)
			a.cnt -= cset.Size()
			if a.cnt == 0 {
				break
			}
		}
	}
}
Allocate full idle CPU packages.
package cpuallocator
import (
	"fmt"
	"sort"
	"k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
	logger "github.com/intel/cri-resource-manager/pkg/log"
	"github.com/intel/cri-resource-manager/pkg/sysfs"
	"github.com/intel/cri-resource-manager/pkg/utils"
	"github.com/intel/goresctrl/pkg/sst"
	idset "github.com/intel/goresctrl/pkg/utils"
)
type AllocFlag uint
const (
	AllocIdlePackages AllocFlag = 1 << iota
	AllocIdleNodes
	AllocIdleCores
	AllocDefault = AllocIdlePackages | AllocIdleCores
	logSource = "cpuallocator"
)
type allocatorHelper struct {
	logger.Logger                
	sys           sysfs.System   
	topology      topologyCache  
	flags         AllocFlag      
	from          cpuset.CPUSet  
	prefer        CPUPriority    
	cnt           int            
	result        cpuset.CPUSet  
	pkgs []sysfs.CPUPackage  
	cpus []sysfs.CPU         
}
type CPUAllocator interface {
	AllocateCpus(from *cpuset.CPUSet, cnt int, prefer CPUPriority) (cpuset.CPUSet, error)
	ReleaseCpus(from *cpuset.CPUSet, cnt int, prefer CPUPriority) (cpuset.CPUSet, error)
}
type CPUPriority int
const (
	PriorityHigh CPUPriority = iota
	PriorityNormal
	PriorityLow
	NumCPUPriorities
	PriorityNone = NumCPUPriorities
)
type cpuAllocator struct {
	logger.Logger
	sys           sysfs.System   
	topologyCache topologyCache  
}
type topologyCache struct {
	pkg  map[idset.ID]cpuset.CPUSet
	node map[idset.ID]cpuset.CPUSet
	core map[idset.ID]cpuset.CPUSet
	cpuPriorities cpuPriorities  
}
type cpuPriorities [NumCPUPriorities]cpuset.CPUSet
type IDFilter func(idset.ID) bool
type IDSorter func(int, int) bool
var log = logger.NewLogger(logSource)
func NewCPUAllocator(sys sysfs.System) CPUAllocator {
	ca := cpuAllocator{
		Logger:        log,
		sys:           sys,
		topologyCache: newTopologyCache(sys),
	}
	return &ca
}
func pickIds(idSlice []idset.ID, f IDFilter) []idset.ID {
	ids := make([]idset.ID, len(idSlice))
	idx := 0
	for _, id := range idSlice {
		if f == nil || f(id) {
			ids[idx] = id
			idx++
		}
	}
	return ids[0:idx]
}
func newAllocatorHelper(sys sysfs.System, topo topologyCache) *allocatorHelper {
	a := &allocatorHelper{
		Logger:   log,
		sys:      sys,
		topology: topo,
		flags:    AllocDefault,
	}
	return a
}