Browse Source

Merge pull request #1949 from slingamn/generic_config.2

genericize atomic config changes
tags/v2.10.0-rc1
Shivaram Lingamneni 2 years ago
parent
commit
d5814c10ab
No account linked to committer's email address
3 changed files with 36 additions and 9 deletions
  1. 1
    6
      irc/getters.go
  2. 2
    3
      irc/server.go
  3. 33
    0
      irc/utils/config.go

+ 1
- 6
irc/getters.go View File

@@ -7,7 +7,6 @@ import (
7 7
 	"net"
8 8
 	"sync/atomic"
9 9
 	"time"
10
-	"unsafe"
11 10
 
12 11
 	"github.com/ergochat/ergo/irc/caps"
13 12
 	"github.com/ergochat/ergo/irc/languages"
@@ -16,11 +15,7 @@ import (
16 15
 )
17 16
 
18 17
 func (server *Server) Config() (config *Config) {
19
-	return (*Config)(atomic.LoadPointer(&server.config))
20
-}
21
-
22
-func (server *Server) SetConfig(config *Config) {
23
-	atomic.StorePointer(&server.config, unsafe.Pointer(config))
18
+	return server.config.Get()
24 19
 }
25 20
 
26 21
 func (server *Server) ChannelRegistrationEnabled() bool {

+ 2
- 3
irc/server.go View File

@@ -17,7 +17,6 @@ import (
17 17
 	"sync"
18 18
 	"syscall"
19 19
 	"time"
20
-	"unsafe"
21 20
 
22 21
 	"github.com/ergochat/irc-go/ircfmt"
23 22
 	"github.com/okzk/sdnotify"
@@ -66,7 +65,7 @@ type Server struct {
66 65
 	channels          ChannelManager
67 66
 	channelRegistry   ChannelRegistry
68 67
 	clients           ClientManager
69
-	config            unsafe.Pointer
68
+	config            utils.ConfigStore[Config]
70 69
 	configFilename    string
71 70
 	connectionLimiter connection_limits.Limiter
72 71
 	ctime             time.Time
@@ -706,7 +705,7 @@ func (server *Server) applyConfig(config *Config) (err error) {
706 705
 	config.Server.Cloaks.SetSecret(LoadCloakSecret(server.store))
707 706
 
708 707
 	// activate the new config
709
-	server.SetConfig(config)
708
+	server.config.Set(config)
710 709
 
711 710
 	// load [dk]-lines, registered users and channels, etc.
712 711
 	if initial {

+ 33
- 0
irc/utils/config.go View File

@@ -0,0 +1,33 @@
1
+// Copyright (c) 2022 Shivaram Lingamneni
2
+// released under the MIT license
3
+
4
+package utils
5
+
6
+import (
7
+	"sync/atomic"
8
+	"unsafe"
9
+)
10
+
11
+/*
12
+This can be used to implement the following pattern:
13
+
14
+1. Prepare a config object (this can be arbitrarily expensive)
15
+2. Take a pointer to the config object and use Set() to install it
16
+3. Use Get() to access the config from any goroutine
17
+4. To update the config, call Set() again with a new prepared config object
18
+5. As long as any individual config object is not modified (by any goroutine)
19
+   after it is installed with Set(), this is free of data races, and Get()
20
+   is extremely cheap (on amd64 it compiles down to plain MOV instructions).
21
+*/
22
+
23
+type ConfigStore[Config any] struct {
24
+	ptr unsafe.Pointer
25
+}
26
+
27
+func (c *ConfigStore[Config]) Get() *Config {
28
+	return (*Config)(atomic.LoadPointer(&c.ptr))
29
+}
30
+
31
+func (c *ConfigStore[Config]) Set(ptr *Config) {
32
+	atomic.StorePointer(&c.ptr, unsafe.Pointer(ptr))
33
+}

Loading…
Cancel
Save