mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-10 04:27:54 +00:00
Add CPUSetBuilder, make CPUSet immutable.
This commit is contained in:
parent
e686ecb6ea
commit
515d86faa0
@ -26,21 +26,57 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CPUSet is a set-like data structure for CPU IDs.
|
// Builder is a mutable builder for CPUSet. Functions that mutate instances
|
||||||
type CPUSet map[int]struct{}
|
// of this type are not thread-safe.
|
||||||
|
type Builder struct {
|
||||||
|
result CPUSet
|
||||||
|
done bool
|
||||||
|
}
|
||||||
|
|
||||||
// NewCPUSet return CPUSet based on provided cpu id's
|
// NewBuilder returns a mutable CPUSet builder.
|
||||||
func NewCPUSet(cpus ...int) CPUSet {
|
func NewBuilder() Builder {
|
||||||
res := CPUSet{}
|
return Builder{
|
||||||
for _, c := range cpus {
|
result: CPUSet{
|
||||||
res.Add(c)
|
elems: map[int]struct{}{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return res
|
}
|
||||||
|
|
||||||
|
// Add adds the supplied elements to the result. Calling Add after calling
|
||||||
|
// Result has no effect.
|
||||||
|
func (b Builder) Add(elems ...int) {
|
||||||
|
if b.done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range elems {
|
||||||
|
b.result.elems[elem] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result returns the result CPUSet containing all elements that were
|
||||||
|
// previously added to this builder. Subsequent calls to Add have no effect.
|
||||||
|
func (b Builder) Result() CPUSet {
|
||||||
|
b.done = true
|
||||||
|
return b.result
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPUSet is a thread-safe, immutable set-like data structure for CPU IDs.
|
||||||
|
type CPUSet struct {
|
||||||
|
elems map[int]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCPUSet returns a new CPUSet containing the supplied elements.
|
||||||
|
func NewCPUSet(cpus ...int) CPUSet {
|
||||||
|
b := NewBuilder()
|
||||||
|
for _, c := range cpus {
|
||||||
|
b.Add(c)
|
||||||
|
}
|
||||||
|
return b.Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the number of elements in this set.
|
// Size returns the number of elements in this set.
|
||||||
func (s CPUSet) Size() int {
|
func (s CPUSet) Size() int {
|
||||||
return len(s)
|
return len(s.elems)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty returns true if there are zero elements in this set.
|
// IsEmpty returns true if there are zero elements in this set.
|
||||||
@ -50,60 +86,45 @@ func (s CPUSet) IsEmpty() bool {
|
|||||||
|
|
||||||
// Contains returns true if the supplied element is present in this set.
|
// Contains returns true if the supplied element is present in this set.
|
||||||
func (s CPUSet) Contains(cpu int) bool {
|
func (s CPUSet) Contains(cpu int) bool {
|
||||||
_, found := s[cpu]
|
_, found := s.elems[cpu]
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add mutates this set to contain the supplied elements.
|
|
||||||
func (s CPUSet) Add(cpus ...int) {
|
|
||||||
for _, cpu := range cpus {
|
|
||||||
s[cpu] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove mutates this set to not contain the supplied elements, if they
|
|
||||||
// exists.
|
|
||||||
func (s CPUSet) Remove(cpus ...int) {
|
|
||||||
for _, cpu := range cpus {
|
|
||||||
delete(s, cpu)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equals returns true if the supplied set contains exactly the same elements
|
// Equals returns true if the supplied set contains exactly the same elements
|
||||||
// as this set (s IsSubsetOf s2 and s2 IsSubsetOf s).
|
// as this set (s IsSubsetOf s2 and s2 IsSubsetOf s).
|
||||||
func (s CPUSet) Equals(s2 CPUSet) bool {
|
func (s CPUSet) Equals(s2 CPUSet) bool {
|
||||||
return reflect.DeepEqual(s, s2)
|
return reflect.DeepEqual(s.elems, s2.elems)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter returns a new CPU set that contains all of the elements from this
|
// Filter returns a new CPU set that contains all of the elements from this
|
||||||
// set that match the supplied predicate, without mutating the source set.
|
// set that match the supplied predicate, without mutating the source set.
|
||||||
func (s CPUSet) Filter(predicate func(int) bool) CPUSet {
|
func (s CPUSet) Filter(predicate func(int) bool) CPUSet {
|
||||||
result := NewCPUSet()
|
b := NewBuilder()
|
||||||
for cpu := range s {
|
for cpu := range s.elems {
|
||||||
if predicate(cpu) {
|
if predicate(cpu) {
|
||||||
result.Add(cpu)
|
b.Add(cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return b.Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterNot returns a new CPU set that contains all of the elements from this
|
// FilterNot returns a new CPU set that contains all of the elements from this
|
||||||
// set that do not match the supplied predicate, without mutating the source
|
// set that do not match the supplied predicate, without mutating the source
|
||||||
// set.
|
// set.
|
||||||
func (s CPUSet) FilterNot(predicate func(int) bool) CPUSet {
|
func (s CPUSet) FilterNot(predicate func(int) bool) CPUSet {
|
||||||
result := NewCPUSet()
|
b := NewBuilder()
|
||||||
for cpu := range s {
|
for cpu := range s.elems {
|
||||||
if !predicate(cpu) {
|
if !predicate(cpu) {
|
||||||
result.Add(cpu)
|
b.Add(cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return b.Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSubsetOf returns true if the supplied set contains all the elements
|
// IsSubsetOf returns true if the supplied set contains all the elements
|
||||||
func (s CPUSet) IsSubsetOf(s2 CPUSet) bool {
|
func (s CPUSet) IsSubsetOf(s2 CPUSet) bool {
|
||||||
result := true
|
result := true
|
||||||
for cpu := range s {
|
for cpu := range s.elems {
|
||||||
if !s2.Contains(cpu) {
|
if !s2.Contains(cpu) {
|
||||||
result = false
|
result = false
|
||||||
break
|
break
|
||||||
@ -116,14 +137,14 @@ func (s CPUSet) IsSubsetOf(s2 CPUSet) bool {
|
|||||||
// set and all of the elements from the supplied set, without mutating
|
// set and all of the elements from the supplied set, without mutating
|
||||||
// either source set.
|
// either source set.
|
||||||
func (s CPUSet) Union(s2 CPUSet) CPUSet {
|
func (s CPUSet) Union(s2 CPUSet) CPUSet {
|
||||||
result := NewCPUSet()
|
b := NewBuilder()
|
||||||
for cpu := range s {
|
for cpu := range s.elems {
|
||||||
result.Add(cpu)
|
b.Add(cpu)
|
||||||
}
|
}
|
||||||
for cpu := range s2 {
|
for cpu := range s2.elems {
|
||||||
result.Add(cpu)
|
b.Add(cpu)
|
||||||
}
|
}
|
||||||
return result
|
return b.Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intersection returns a new CPU set that contains all of the elements
|
// Intersection returns a new CPU set that contains all of the elements
|
||||||
@ -144,7 +165,7 @@ func (s CPUSet) Difference(s2 CPUSet) CPUSet {
|
|||||||
// this set.
|
// this set.
|
||||||
func (s CPUSet) ToSlice() []int {
|
func (s CPUSet) ToSlice() []int {
|
||||||
result := []int{}
|
result := []int{}
|
||||||
for cpu := range s {
|
for cpu := range s.elems {
|
||||||
result = append(result, cpu)
|
result = append(result, cpu)
|
||||||
}
|
}
|
||||||
sort.Ints(result)
|
sort.Ints(result)
|
||||||
@ -161,7 +182,6 @@ func (s CPUSet) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
elems := s.ToSlice()
|
elems := s.ToSlice()
|
||||||
sort.Ints(elems)
|
|
||||||
|
|
||||||
type rng struct {
|
type rng struct {
|
||||||
start int
|
start int
|
||||||
@ -210,11 +230,11 @@ func MustParse(s string) CPUSet {
|
|||||||
//
|
//
|
||||||
// See: http://man7.org/linux/man-pages/man7/cpuset.7.html#FORMATS
|
// See: http://man7.org/linux/man-pages/man7/cpuset.7.html#FORMATS
|
||||||
func Parse(s string) (CPUSet, error) {
|
func Parse(s string) (CPUSet, error) {
|
||||||
result := NewCPUSet()
|
b := NewBuilder()
|
||||||
|
|
||||||
// Handle empty string.
|
// Handle empty string.
|
||||||
if s == "" {
|
if s == "" {
|
||||||
return result, nil
|
return b.Result(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split CPU list string:
|
// Split CPU list string:
|
||||||
@ -227,34 +247,34 @@ func Parse(s string) (CPUSet, error) {
|
|||||||
// Handle ranges that consist of only one element like "34".
|
// Handle ranges that consist of only one element like "34".
|
||||||
elem, err := strconv.Atoi(boundaries[0])
|
elem, err := strconv.Atoi(boundaries[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return NewCPUSet(), err
|
||||||
}
|
}
|
||||||
result.Add(elem)
|
b.Add(elem)
|
||||||
} else if len(boundaries) == 2 {
|
} else if len(boundaries) == 2 {
|
||||||
// Handle multi-element ranges like "0-5".
|
// Handle multi-element ranges like "0-5".
|
||||||
start, err := strconv.Atoi(boundaries[0])
|
start, err := strconv.Atoi(boundaries[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return NewCPUSet(), err
|
||||||
}
|
}
|
||||||
end, err := strconv.Atoi(boundaries[1])
|
end, err := strconv.Atoi(boundaries[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return NewCPUSet(), err
|
||||||
}
|
}
|
||||||
// Add all elements to the result.
|
// Add all elements to the result.
|
||||||
// e.g. "0-5", "46-48" => [0, 1, 2, 3, 4, 5, 46, 47, 48].
|
// e.g. "0-5", "46-48" => [0, 1, 2, 3, 4, 5, 46, 47, 48].
|
||||||
for e := start; e <= end; e++ {
|
for e := start; e <= end; e++ {
|
||||||
result.Add(e)
|
b.Add(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result, nil
|
return b.Result(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone returns a copy of this CPU set.
|
// Clone returns a copy of this CPU set.
|
||||||
func (s CPUSet) Clone() CPUSet {
|
func (s CPUSet) Clone() CPUSet {
|
||||||
res := NewCPUSet()
|
b := NewBuilder()
|
||||||
for k, v := range s {
|
for elem := range s.elems {
|
||||||
res[k] = v
|
b.Add(elem)
|
||||||
}
|
}
|
||||||
return res
|
return b.Result()
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,23 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestCPUSetBuilder(t *testing.T) {
|
||||||
|
b := NewBuilder()
|
||||||
|
elems := []int{1, 2, 3, 4, 5}
|
||||||
|
for _, elem := range elems {
|
||||||
|
b.Add(elem)
|
||||||
|
}
|
||||||
|
result := b.Result()
|
||||||
|
for _, elem := range elems {
|
||||||
|
if !result.Contains(elem) {
|
||||||
|
t.Fatalf("expected cpuset to contain element %d: [%v]", elem, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(elems) != result.Size() {
|
||||||
|
t.Fatalf("expected cpuset %s to have the same size as %v", result, elems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCPUSetSize(t *testing.T) {
|
func TestCPUSetSize(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
cpuset CPUSet
|
cpuset CPUSet
|
||||||
@ -82,29 +99,6 @@ func TestCPUSetContains(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCPUSetAdd(t *testing.T) {
|
|
||||||
result := NewCPUSet()
|
|
||||||
for _, elem := range []int{1, 2, 3, 4, 5} {
|
|
||||||
result.Add(elem)
|
|
||||||
if !result.Contains(elem) {
|
|
||||||
t.Fatalf("expected cpuset to contain element %d: [%v]", elem, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCPUSetRemove(t *testing.T) {
|
|
||||||
result := NewCPUSet(1, 2, 3, 4, 5)
|
|
||||||
for _, elem := range []int{1, 2, 3, 4, 5} {
|
|
||||||
result.Remove(elem)
|
|
||||||
if result.Contains(elem) {
|
|
||||||
t.Fatalf("expected cpuset to not contain element %d: [%v]", elem, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !result.IsEmpty() {
|
|
||||||
t.Fatalf("expected cpuset to be empty: [%v]", result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCPUSetEqual(t *testing.T) {
|
func TestCPUSetEqual(t *testing.T) {
|
||||||
shouldEqual := []struct {
|
shouldEqual := []struct {
|
||||||
s1 CPUSet
|
s1 CPUSet
|
||||||
|
Loading…
Reference in New Issue
Block a user