3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-22 03:49:27 +01:00

genericize atomic config changes

This commit is contained in:
Shivaram Lingamneni 2022-05-03 11:06:57 -04:00
parent 66bf6244f3
commit c603d41d08
3 changed files with 35 additions and 9 deletions

View File

@ -7,7 +7,6 @@ import (
"net"
"sync/atomic"
"time"
"unsafe"
"github.com/ergochat/ergo/irc/caps"
"github.com/ergochat/ergo/irc/languages"
@ -16,11 +15,7 @@ import (
)
func (server *Server) Config() (config *Config) {
return (*Config)(atomic.LoadPointer(&server.config))
}
func (server *Server) SetConfig(config *Config) {
atomic.StorePointer(&server.config, unsafe.Pointer(config))
return server.config.Get()
}
func (server *Server) ChannelRegistrationEnabled() bool {

View File

@ -17,7 +17,6 @@ import (
"sync"
"syscall"
"time"
"unsafe"
"github.com/ergochat/irc-go/ircfmt"
"github.com/okzk/sdnotify"
@ -66,7 +65,7 @@ type Server struct {
channels ChannelManager
channelRegistry ChannelRegistry
clients ClientManager
config unsafe.Pointer
config utils.ConfigStore[Config]
configFilename string
connectionLimiter connection_limits.Limiter
ctime time.Time
@ -704,7 +703,7 @@ func (server *Server) applyConfig(config *Config) (err error) {
config.Server.Cloaks.SetSecret(LoadCloakSecret(server.store))
// activate the new config
server.SetConfig(config)
server.config.Set(config)
// load [dk]-lines, registered users and channels, etc.
if initial {

32
irc/utils/config.go Normal file
View File

@ -0,0 +1,32 @@
// Copyright (c) 2022 Shivaram Lingamneni
// released under the MIT license
package utils
import (
"sync/atomic"
"unsafe"
)
/*
This can be used to implement the following pattern:
1. Load and munge a config (this can be arbitrarily expensive)
2. Use Set() to install the config
3. Use Get() to access the config
4. As long as any individual config is not modified (by any goroutine)
after the initial call to Set(), this is free of data races, and Get()
is extremely cheap (on amd64 it compiles down to plain MOV instructions).
*/
type ConfigStore[T any] struct {
ptr unsafe.Pointer
}
func (c *ConfigStore[T]) Get() *T {
return (*T)(atomic.LoadPointer(&c.ptr))
}
func (c *ConfigStore[T]) Set(ptr *T) {
atomic.StorePointer(&c.ptr, unsafe.Pointer(ptr))
}