Add type to store bandwidths.

This commit is contained in:
Joachim Bauch 2025-11-06 09:14:30 +01:00
commit dc1c166fd1
No known key found for this signature in database
GPG key ID: 77C1D22D53E15F02
3 changed files with 172 additions and 0 deletions

79
api/bandwidth.go Normal file
View file

@ -0,0 +1,79 @@
/**
* Standalone signaling server for the Nextcloud Spreed app.
* Copyright (C) 2025 struktur AG
*
* @author Joachim Bauch <bauch@struktur.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package api
import (
"sync/atomic"
"github.com/strukturag/nextcloud-spreed-signaling/internal"
)
// Bandwidth stores a bandwidth in bits per second.
type Bandwidth uint64
// Bits returns the bandwidth in bits per second.
func (b Bandwidth) Bits() uint64 {
return uint64(b)
}
// Bytes returns the bandwidth in bytes per second.
func (b Bandwidth) Bytes() uint64 {
return b.Bits() / 8
}
// BandwidthFromBits creates a bandwidth from bits per second.
func BandwidthFromBits(b uint64) Bandwidth {
return Bandwidth(b)
}
// BandwithFromBits creates a bandwidth from megabits per second.
func BandwidthFromMegabits(b uint64) Bandwidth {
return Bandwidth(b * 1024 * 1024)
}
// BandwidthFromBytes creates a bandwidth from bytes per second.
func BandwidthFromBytes(b uint64) Bandwidth {
return Bandwidth(b * 8)
}
// AtomicBandwidth is an atomic Bandwidth. The zero value is zero.
// AtomicBandwidth must not be copied after first use.
type AtomicBandwidth struct {
// 64-bit members that are accessed atomically must be 64-bit aligned.
v uint64
_ internal.NoCopy
}
// Load atomically loads and returns the value stored in b.
func (b *AtomicBandwidth) Load() Bandwidth {
return Bandwidth(atomic.LoadUint64(&b.v)) // +checklocksignore
}
// Store atomically stores v into b.
func (b *AtomicBandwidth) Store(v Bandwidth) {
atomic.StoreUint64(&b.v, uint64(v)) // +checklocksignore
}
// Swap atomically stores v into b and returns the previous value.
func (b *AtomicBandwidth) Swap(v Bandwidth) Bandwidth {
return Bandwidth(atomic.SwapUint64(&b.v, uint64(v))) // +checklocksignore
}

58
api/bandwidth_test.go Normal file
View file

@ -0,0 +1,58 @@
/**
* Standalone signaling server for the Nextcloud Spreed app.
* Copyright (C) 2025 struktur AG
*
* @author Joachim Bauch <bauch@struktur.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package api
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestBandwidth(t *testing.T) {
t.Parallel()
assert := assert.New(t)
var b Bandwidth
assert.EqualValues(0, b.Bits())
assert.EqualValues(0, b.Bytes())
b = BandwidthFromBits(8000)
assert.EqualValues(8000, b.Bits())
assert.EqualValues(1000, b.Bytes())
b = BandwidthFromBytes(1000)
assert.EqualValues(8000, b.Bits())
assert.EqualValues(1000, b.Bytes())
b = BandwidthFromMegabits(2)
assert.EqualValues(2*1024*1024, b.Bits())
assert.EqualValues(2*1024*1024/8, b.Bytes())
var a AtomicBandwidth
assert.EqualValues(0, a.Load())
a.Store(1000)
assert.EqualValues(1000, a.Load())
old := a.Swap(2000)
assert.EqualValues(1000, old)
assert.EqualValues(2000, a.Load())
}

35
internal/nocopy.go Normal file
View file

@ -0,0 +1,35 @@
/**
* Standalone signaling server for the Nextcloud Spreed app.
* Copyright (C) 2025 struktur AG
*
* @author Joachim Bauch <bauch@struktur.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package internal
// NoCopy may be added to structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
//
// Note that it must not be embedded, due to the Lock and Unlock methods.
type NoCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*NoCopy) Lock() {}
func (*NoCopy) Unlock() {}