1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2024-10-05 17:18:48 +00:00

Voice: UDP now thread unsafe for performance

This commit omits thread safe guarantees in the UDP voice connection.
This is done because the UDP connection should not be shared across
threads, so those guarantees are now omitted for performance.

Session will still guard a UDP connection around a read mutex, because
Session itself has thread safe guarantees. This may change in the
future.
This commit is contained in:
diamondburned 2020-11-17 11:34:22 -08:00 committed by diamondburned
parent 81b1a0a902
commit 1b8af1513e

View file

@ -18,15 +18,11 @@ var Dialer = net.Dialer{
Timeout: 10 * time.Second,
}
// ErrClosed is returned if a Write was called on a closed connection.
var ErrClosed = errors.New("UDP connection closed")
// Connection represents a voice connection. It is not thread-safe.
type Connection struct {
GatewayIP string
GatewayPort uint16
mutex chan struct{} // for ctx
context context.Context
conn net.Conn
ssrc uint32
@ -94,7 +90,6 @@ func DialConnectionCtx(ctx context.Context, addr string, ssrc uint32) (*Connecti
// 50 sends per second, 960 samples each at 48kHz
frequency: *rate.NewLimiter(rate.Every(20*time.Millisecond), 1),
context: context.Background(),
mutex: make(chan struct{}, 1),
packet: packet,
ssrc: ssrc,
conn: conn,
@ -110,17 +105,10 @@ func (c *Connection) UseSecret(secret [32]byte) {
// UseContext lets the connection use the given context for its Write method.
// WriteCtx will override this context.
func (c *Connection) UseContext(ctx context.Context) error {
c.mutex <- struct{}{}
defer func() { <-c.mutex }()
return c.useContext(ctx)
}
func (c *Connection) useContext(ctx context.Context) error {
if c.conn == nil {
return ErrClosed
}
if c.context == ctx {
return nil
}
@ -135,40 +123,16 @@ func (c *Connection) useContext(ctx context.Context) error {
}
func (c *Connection) Close() error {
c.mutex <- struct{}{}
err := c.conn.Close()
c.conn = nil
<-c.mutex
return err
return c.conn.Close()
}
// Write sends bytes into the voice UDP connection.
func (c *Connection) Write(b []byte) (int, error) {
select {
case c.mutex <- struct{}{}:
defer func() { <-c.mutex }()
case <-c.context.Done():
return 0, c.context.Err()
}
if c.conn == nil {
return 0, ErrClosed
}
return c.write(b)
}
// WriteCtx sends bytes into the voice UDP connection with a timeout.
func (c *Connection) WriteCtx(ctx context.Context, b []byte) (int, error) {
select {
case c.mutex <- struct{}{}:
defer func() { <-c.mutex }()
case <-c.context.Done():
return 0, c.context.Err()
case <-ctx.Done():
return 0, ctx.Err()
}
if err := c.useContext(ctx); err != nil {
return 0, errors.Wrap(err, "failed to use context")
}