Browse Source

extract Semaphore to utils package

tags/v1.1.0-rc1
Shivaram Lingamneni 5 years ago
parent
commit
97e71dfef7
4 changed files with 59 additions and 48 deletions
  1. 4
    4
      irc/channel.go
  2. 3
    43
      irc/semaphores.go
  3. 3
    1
      irc/socket.go
  4. 49
    0
      irc/utils/semaphores.go

+ 4
- 4
irc/channel.go View File

39
 	userLimit         int
39
 	userLimit         int
40
 	accountToUMode    map[string]modes.Mode
40
 	accountToUMode    map[string]modes.Mode
41
 	history           history.Buffer
41
 	history           history.Buffer
42
-	stateMutex        sync.RWMutex // tier 1
43
-	writerSemaphore   Semaphore    // tier 1.5
44
-	joinPartMutex     sync.Mutex   // tier 3
45
-	ensureLoaded      utils.Once   // manages loading stored registration info from the database
42
+	stateMutex        sync.RWMutex    // tier 1
43
+	writerSemaphore   utils.Semaphore // tier 1.5
44
+	joinPartMutex     sync.Mutex      // tier 3
45
+	ensureLoaded      utils.Once      // manages loading stored registration info from the database
46
 	dirtyBits         uint
46
 	dirtyBits         uint
47
 }
47
 }
48
 
48
 

+ 3
- 43
irc/semaphores.go View File

3
 package irc
3
 package irc
4
 
4
 
5
 import (
5
 import (
6
-	"log"
7
 	"runtime"
6
 	"runtime"
8
-	"runtime/debug"
7
+
8
+	"github.com/oragono/oragono/irc/utils"
9
 )
9
 )
10
 
10
 
11
 // See #237 for context. Operations that might allocate large amounts of temporary
11
 // See #237 for context. Operations that might allocate large amounts of temporary
21
 	MaxServerSemaphoreCapacity = 32
21
 	MaxServerSemaphoreCapacity = 32
22
 )
22
 )
23
 
23
 
24
-// Semaphore is a counting semaphore. Note that a capacity of n requires O(n) storage.
25
-type Semaphore (chan bool)
26
-
27
 // ServerSemaphores includes a named Semaphore corresponding to each concurrency-limited
24
 // ServerSemaphores includes a named Semaphore corresponding to each concurrency-limited
28
 // sever operation.
25
 // sever operation.
29
 type ServerSemaphores struct {
26
 type ServerSemaphores struct {
30
 	// each distinct operation MUST have its own semaphore;
27
 	// each distinct operation MUST have its own semaphore;
31
 	// methods that acquire a semaphore MUST NOT call methods that acquire another
28
 	// methods that acquire a semaphore MUST NOT call methods that acquire another
32
-	ClientDestroy Semaphore
29
+	ClientDestroy utils.Semaphore
33
 }
30
 }
34
 
31
 
35
 // Initialize initializes a set of server semaphores.
32
 // Initialize initializes a set of server semaphores.
41
 	serversem.ClientDestroy.Initialize(capacity)
38
 	serversem.ClientDestroy.Initialize(capacity)
42
 	return
39
 	return
43
 }
40
 }
44
-
45
-// Initialize initializes a semaphore to a given capacity.
46
-func (semaphore *Semaphore) Initialize(capacity int) {
47
-	*semaphore = make(chan bool, capacity)
48
-	for i := 0; i < capacity; i++ {
49
-		(*semaphore) <- true
50
-	}
51
-}
52
-
53
-// Acquire acquires a semaphore, blocking if necessary.
54
-func (semaphore *Semaphore) Acquire() {
55
-	<-(*semaphore)
56
-}
57
-
58
-// TryAcquire tries to acquire a semaphore, returning whether the acquire was
59
-// successful. It never blocks.
60
-func (semaphore *Semaphore) TryAcquire() (acquired bool) {
61
-	select {
62
-	case <-(*semaphore):
63
-		return true
64
-	default:
65
-		return false
66
-	}
67
-}
68
-
69
-// Release releases a semaphore. It never blocks. (This is not a license
70
-// to program spurious releases.)
71
-func (semaphore *Semaphore) Release() {
72
-	select {
73
-	case (*semaphore) <- true:
74
-		// good
75
-	default:
76
-		// spurious release
77
-		log.Printf("spurious semaphore release (full to capacity %d)", cap(*semaphore))
78
-		debug.PrintStack()
79
-	}
80
-}

+ 3
- 1
irc/socket.go View File

15
 	"strings"
15
 	"strings"
16
 	"sync"
16
 	"sync"
17
 	"time"
17
 	"time"
18
+
19
+	"github.com/oragono/oragono/irc/utils"
18
 )
20
 )
19
 
21
 
20
 var (
22
 var (
34
 	maxSendQBytes int
36
 	maxSendQBytes int
35
 
37
 
36
 	// this is a trylock enforcing that only one goroutine can write to `conn` at a time
38
 	// this is a trylock enforcing that only one goroutine can write to `conn` at a time
37
-	writerSemaphore Semaphore
39
+	writerSemaphore utils.Semaphore
38
 
40
 
39
 	buffers       [][]byte
41
 	buffers       [][]byte
40
 	totalLength   int
42
 	totalLength   int

+ 49
- 0
irc/utils/semaphores.go View File

1
+// Copyright (c) 2018 Shivaram Lingamneni
2
+
3
+package utils
4
+
5
+import (
6
+	"log"
7
+	"runtime/debug"
8
+)
9
+
10
+// Semaphore is a counting semaphore. Note that a capacity of n requires O(n) storage.
11
+// A semaphore of capacity 1 can be used as a trylock.
12
+type Semaphore (chan bool)
13
+
14
+// Initialize initializes a semaphore to a given capacity.
15
+func (semaphore *Semaphore) Initialize(capacity int) {
16
+	*semaphore = make(chan bool, capacity)
17
+	for i := 0; i < capacity; i++ {
18
+		(*semaphore) <- true
19
+	}
20
+}
21
+
22
+// Acquire acquires a semaphore, blocking if necessary.
23
+func (semaphore *Semaphore) Acquire() {
24
+	<-(*semaphore)
25
+}
26
+
27
+// TryAcquire tries to acquire a semaphore, returning whether the acquire was
28
+// successful. It never blocks.
29
+func (semaphore *Semaphore) TryAcquire() (acquired bool) {
30
+	select {
31
+	case <-(*semaphore):
32
+		return true
33
+	default:
34
+		return false
35
+	}
36
+}
37
+
38
+// Release releases a semaphore. It never blocks. (This is not a license
39
+// to program spurious releases.)
40
+func (semaphore *Semaphore) Release() {
41
+	select {
42
+	case (*semaphore) <- true:
43
+		// good
44
+	default:
45
+		// spurious release
46
+		log.Printf("spurious semaphore release (full to capacity %d)", cap(*semaphore))
47
+		debug.PrintStack()
48
+	}
49
+}

Loading…
Cancel
Save