Browse Source

replace some utils.Semaphore with (*sync.Mutex).TryLock

See #1994
tags/v2.11.0-rc1
Shivaram Lingamneni 1 year ago
parent
commit
746309e386
3 changed files with 39 additions and 46 deletions
  1. 16
    17
      irc/channel.go
  2. 15
    18
      irc/client.go
  3. 8
    11
      irc/socket.go

+ 16
- 17
irc/channel.go View File

@@ -47,10 +47,10 @@ type Channel struct {
47 47
 	userLimit         int
48 48
 	accountToUMode    map[string]modes.Mode
49 49
 	history           history.Buffer
50
-	stateMutex        sync.RWMutex    // tier 1
51
-	writerSemaphore   utils.Semaphore // tier 1.5
52
-	joinPartMutex     sync.Mutex      // tier 3
53
-	ensureLoaded      utils.Once      // manages loading stored registration info from the database
50
+	stateMutex        sync.RWMutex // tier 1
51
+	writebackLock     sync.Mutex   // tier 1.5
52
+	joinPartMutex     sync.Mutex   // tier 3
53
+	ensureLoaded      utils.Once   // manages loading stored registration info from the database
54 54
 	dirtyBits         uint
55 55
 	settings          ChannelSettings
56 56
 }
@@ -61,12 +61,11 @@ func NewChannel(s *Server, name, casefoldedName string, registered bool) *Channe
61 61
 	config := s.Config()
62 62
 
63 63
 	channel := &Channel{
64
-		createdTime:     time.Now().UTC(), // may be overwritten by applyRegInfo
65
-		members:         make(MemberSet),
66
-		name:            name,
67
-		nameCasefolded:  casefoldedName,
68
-		server:          s,
69
-		writerSemaphore: utils.NewSemaphore(1),
64
+		createdTime:    time.Now().UTC(), // may be overwritten by applyRegInfo
65
+		members:        make(MemberSet),
66
+		name:           name,
67
+		nameCasefolded: casefoldedName,
68
+		server:         s,
70 69
 	}
71 70
 
72 71
 	channel.initializeLists()
@@ -209,11 +208,11 @@ func (channel *Channel) MarkDirty(dirtyBits uint) {
209 208
 // ChannelManager's lock (that way, no one can join and make the channel dirty again
210 209
 // between this method exiting and the actual deletion).
211 210
 func (channel *Channel) IsClean() bool {
212
-	if !channel.writerSemaphore.TryAcquire() {
211
+	if !channel.writebackLock.TryLock() {
213 212
 		// a database write (which may fail) is in progress, the channel cannot be cleaned up
214 213
 		return false
215 214
 	}
216
-	defer channel.writerSemaphore.Release()
215
+	defer channel.writebackLock.Unlock()
217 216
 
218 217
 	channel.stateMutex.RLock()
219 218
 	defer channel.stateMutex.RUnlock()
@@ -225,7 +224,7 @@ func (channel *Channel) IsClean() bool {
225 224
 }
226 225
 
227 226
 func (channel *Channel) wakeWriter() {
228
-	if channel.writerSemaphore.TryAcquire() {
227
+	if channel.writebackLock.TryLock() {
229 228
 		go channel.writeLoop()
230 229
 	}
231 230
 }
@@ -235,7 +234,7 @@ func (channel *Channel) writeLoop() {
235 234
 	for {
236 235
 		// TODO(#357) check the error value of this and implement timed backoff
237 236
 		channel.performWrite(0)
238
-		channel.writerSemaphore.Release()
237
+		channel.writebackLock.Unlock()
239 238
 
240 239
 		channel.stateMutex.RLock()
241 240
 		isDirty := channel.dirtyBits != 0
@@ -249,7 +248,7 @@ func (channel *Channel) writeLoop() {
249 248
 			return // nothing to do
250 249
 		} // else: isDirty, so we need to write again
251 250
 
252
-		if !channel.writerSemaphore.TryAcquire() {
251
+		if !channel.writebackLock.TryLock() {
253 252
 			return
254 253
 		}
255 254
 	}
@@ -272,8 +271,8 @@ func (channel *Channel) Store(dirtyBits uint) (err error) {
272 271
 		}
273 272
 	}()
274 273
 
275
-	channel.writerSemaphore.Acquire()
276
-	defer channel.writerSemaphore.Release()
274
+	channel.writebackLock.Lock()
275
+	defer channel.writebackLock.Unlock()
277 276
 	return channel.performWrite(dirtyBits)
278 277
 }
279 278
 

+ 15
- 18
irc/client.go View File

@@ -113,7 +113,7 @@ type Client struct {
113 113
 	vhost              string
114 114
 	history            history.Buffer
115 115
 	dirtyBits          uint
116
-	writerSemaphore    utils.Semaphore // tier 1.5
116
+	writebackLock      sync.Mutex // tier 1.5
117 117
 }
118 118
 
119 119
 type saslStatus struct {
@@ -335,16 +335,15 @@ func (server *Server) RunClient(conn IRCConn) {
335 335
 			Duration: config.Accounts.LoginThrottling.Duration,
336 336
 			Limit:    config.Accounts.LoginThrottling.MaxAttempts,
337 337
 		},
338
-		server:          server,
339
-		accountName:     "*",
340
-		nick:            "*", // * is used until actual nick is given
341
-		nickCasefolded:  "*",
342
-		nickMaskString:  "*", // * is used until actual nick is given
343
-		realIP:          realIP,
344
-		proxiedIP:       proxiedIP,
345
-		requireSASL:     requireSASL,
346
-		nextSessionID:   1,
347
-		writerSemaphore: utils.NewSemaphore(1),
338
+		server:         server,
339
+		accountName:    "*",
340
+		nick:           "*", // * is used until actual nick is given
341
+		nickCasefolded: "*",
342
+		nickMaskString: "*", // * is used until actual nick is given
343
+		realIP:         realIP,
344
+		proxiedIP:      proxiedIP,
345
+		requireSASL:    requireSASL,
346
+		nextSessionID:  1,
348 347
 	}
349 348
 	if requireSASL {
350 349
 		client.requireSASLMessage = banMsg
@@ -424,8 +423,6 @@ func (server *Server) AddAlwaysOnClient(account ClientAccount, channelToStatus m
424 423
 		realname: realname,
425 424
 
426 425
 		nextSessionID: 1,
427
-
428
-		writerSemaphore: utils.NewSemaphore(1),
429 426
 	}
430 427
 
431 428
 	if client.checkAlwaysOnExpirationNoMutex(config, true) {
@@ -1772,7 +1769,7 @@ func (client *Client) markDirty(dirtyBits uint) {
1772 1769
 }
1773 1770
 
1774 1771
 func (client *Client) wakeWriter() {
1775
-	if client.writerSemaphore.TryAcquire() {
1772
+	if client.writebackLock.TryLock() {
1776 1773
 		go client.writeLoop()
1777 1774
 	}
1778 1775
 }
@@ -1780,13 +1777,13 @@ func (client *Client) wakeWriter() {
1780 1777
 func (client *Client) writeLoop() {
1781 1778
 	for {
1782 1779
 		client.performWrite(0)
1783
-		client.writerSemaphore.Release()
1780
+		client.writebackLock.Unlock()
1784 1781
 
1785 1782
 		client.stateMutex.RLock()
1786 1783
 		isDirty := client.dirtyBits != 0
1787 1784
 		client.stateMutex.RUnlock()
1788 1785
 
1789
-		if !isDirty || !client.writerSemaphore.TryAcquire() {
1786
+		if !isDirty || !client.writebackLock.TryLock() {
1790 1787
 			return
1791 1788
 		}
1792 1789
 	}
@@ -1844,8 +1841,8 @@ func (client *Client) Store(dirtyBits uint) (err error) {
1844 1841
 		}
1845 1842
 	}()
1846 1843
 
1847
-	client.writerSemaphore.Acquire()
1848
-	defer client.writerSemaphore.Release()
1844
+	client.writebackLock.Lock()
1845
+	defer client.writebackLock.Unlock()
1849 1846
 	client.performWrite(dirtyBits)
1850 1847
 	return nil
1851 1848
 }

+ 8
- 11
irc/socket.go View File

@@ -8,8 +8,6 @@ import (
8 8
 	"errors"
9 9
 	"io"
10 10
 	"sync"
11
-
12
-	"github.com/ergochat/ergo/irc/utils"
13 11
 )
14 12
 
15 13
 var (
@@ -27,7 +25,7 @@ type Socket struct {
27 25
 	maxSendQBytes int
28 26
 
29 27
 	// this is a trylock enforcing that only one goroutine can write to `conn` at a time
30
-	writerSemaphore utils.Semaphore
28
+	writeLock sync.Mutex
31 29
 
32 30
 	buffers       [][]byte
33 31
 	totalLength   int
@@ -40,9 +38,8 @@ type Socket struct {
40 38
 // NewSocket returns a new Socket.
41 39
 func NewSocket(conn IRCConn, maxSendQBytes int) *Socket {
42 40
 	result := Socket{
43
-		conn:            conn,
44
-		maxSendQBytes:   maxSendQBytes,
45
-		writerSemaphore: utils.NewSemaphore(1),
41
+		conn:          conn,
42
+		maxSendQBytes: maxSendQBytes,
46 43
 	}
47 44
 	return &result
48 45
 }
@@ -128,8 +125,8 @@ func (socket *Socket) BlockingWrite(data []byte) (err error) {
128 125
 	}()
129 126
 
130 127
 	// blocking acquire of the trylock
131
-	socket.writerSemaphore.Acquire()
132
-	defer socket.writerSemaphore.Release()
128
+	socket.writeLock.Lock()
129
+	defer socket.writeLock.Unlock()
133 130
 
134 131
 	// first, flush any buffered data, to preserve the ordering guarantees
135 132
 	closed := socket.performWrite()
@@ -146,7 +143,7 @@ func (socket *Socket) BlockingWrite(data []byte) (err error) {
146 143
 
147 144
 // wakeWriter starts the goroutine that actually performs the write, without blocking
148 145
 func (socket *Socket) wakeWriter() {
149
-	if socket.writerSemaphore.TryAcquire() {
146
+	if socket.writeLock.TryLock() {
150 147
 		// acquired the trylock; send() will release it
151 148
 		go socket.send()
152 149
 	}
@@ -182,12 +179,12 @@ func (socket *Socket) send() {
182 179
 		socket.performWrite()
183 180
 		// surrender the trylock, avoiding a race where a write comes in after we've
184 181
 		// checked readyToWrite() and it returned false, but while we still hold the trylock:
185
-		socket.writerSemaphore.Release()
182
+		socket.writeLock.Unlock()
186 183
 		// check if more data came in while we held the trylock:
187 184
 		if !socket.readyToWrite() {
188 185
 			return
189 186
 		}
190
-		if !socket.writerSemaphore.TryAcquire() {
187
+		if !socket.writeLock.TryLock() {
191 188
 			// failed to acquire; exit and wait for the holder to observe readyToWrite()
192 189
 			// after releasing it
193 190
 			return

Loading…
Cancel
Save