mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-22 10:42:52 +01:00
Merge pull request #1607 from slingamn/semaphore_update
simplify semaphore release code
This commit is contained in:
commit
f0796b2eb5
@ -61,15 +61,15 @@ func NewChannel(s *Server, name, casefoldedName string, registered bool) *Channe
|
||||
config := s.Config()
|
||||
|
||||
channel := &Channel{
|
||||
createdTime: time.Now().UTC(), // may be overwritten by applyRegInfo
|
||||
members: make(MemberSet),
|
||||
name: name,
|
||||
nameCasefolded: casefoldedName,
|
||||
server: s,
|
||||
createdTime: time.Now().UTC(), // may be overwritten by applyRegInfo
|
||||
members: make(MemberSet),
|
||||
name: name,
|
||||
nameCasefolded: casefoldedName,
|
||||
server: s,
|
||||
writerSemaphore: utils.NewSemaphore(1),
|
||||
}
|
||||
|
||||
channel.initializeLists()
|
||||
channel.writerSemaphore.Initialize(1)
|
||||
channel.history.Initialize(0, 0)
|
||||
|
||||
if !registered {
|
||||
|
@ -356,20 +356,20 @@ func (server *Server) RunClient(conn IRCConn) {
|
||||
Duration: config.Accounts.LoginThrottling.Duration,
|
||||
Limit: config.Accounts.LoginThrottling.MaxAttempts,
|
||||
},
|
||||
server: server,
|
||||
accountName: "*",
|
||||
nick: "*", // * is used until actual nick is given
|
||||
nickCasefolded: "*",
|
||||
nickMaskString: "*", // * is used until actual nick is given
|
||||
realIP: realIP,
|
||||
proxiedIP: proxiedIP,
|
||||
requireSASL: requireSASL,
|
||||
nextSessionID: 1,
|
||||
server: server,
|
||||
accountName: "*",
|
||||
nick: "*", // * is used until actual nick is given
|
||||
nickCasefolded: "*",
|
||||
nickMaskString: "*", // * is used until actual nick is given
|
||||
realIP: realIP,
|
||||
proxiedIP: proxiedIP,
|
||||
requireSASL: requireSASL,
|
||||
nextSessionID: 1,
|
||||
writerSemaphore: utils.NewSemaphore(1),
|
||||
}
|
||||
if requireSASL {
|
||||
client.requireSASLMessage = banMsg
|
||||
}
|
||||
client.writerSemaphore.Initialize(1)
|
||||
client.history.Initialize(config.History.ClientLength, time.Duration(config.History.AutoresizeWindow))
|
||||
client.brbTimer.Initialize(client)
|
||||
session := &Session{
|
||||
@ -445,6 +445,8 @@ func (server *Server) AddAlwaysOnClient(account ClientAccount, channelToStatus m
|
||||
realname: realname,
|
||||
|
||||
nextSessionID: 1,
|
||||
|
||||
writerSemaphore: utils.NewSemaphore(1),
|
||||
}
|
||||
|
||||
if client.checkAlwaysOnExpirationNoMutex(config, true) {
|
||||
@ -456,7 +458,6 @@ func (server *Server) AddAlwaysOnClient(account ClientAccount, channelToStatus m
|
||||
for _, m := range uModes {
|
||||
client.SetMode(m, true)
|
||||
}
|
||||
client.writerSemaphore.Initialize(1)
|
||||
client.history.Initialize(0, 0)
|
||||
client.brbTimer.Initialize(client)
|
||||
|
||||
|
@ -37,5 +37,5 @@ func (serversem *ServerSemaphores) Initialize() {
|
||||
if capacity > MaxServerSemaphoreCapacity {
|
||||
capacity = MaxServerSemaphoreCapacity
|
||||
}
|
||||
serversem.ClientDestroy.Initialize(capacity)
|
||||
serversem.ClientDestroy = utils.NewSemaphore(capacity)
|
||||
}
|
||||
|
@ -612,11 +612,11 @@ func (server *Server) applyConfig(config *Config) (err error) {
|
||||
if initial {
|
||||
maxIPConc := int(config.Server.IPCheckScript.MaxConcurrency)
|
||||
if maxIPConc != 0 {
|
||||
server.semaphores.IPCheckScript.Initialize(maxIPConc)
|
||||
server.semaphores.IPCheckScript = utils.NewSemaphore(maxIPConc)
|
||||
}
|
||||
maxAuthConc := int(config.Accounts.AuthScript.MaxConcurrency)
|
||||
if maxAuthConc != 0 {
|
||||
server.semaphores.AuthScript.Initialize(maxAuthConc)
|
||||
server.semaphores.AuthScript = utils.NewSemaphore(maxAuthConc)
|
||||
}
|
||||
|
||||
if err := overrideServicePrefixes(config.Server.OverrideServicesHostname); err != nil {
|
||||
|
@ -40,10 +40,10 @@ type Socket struct {
|
||||
// NewSocket returns a new Socket.
|
||||
func NewSocket(conn IRCConn, maxSendQBytes int) *Socket {
|
||||
result := Socket{
|
||||
conn: conn,
|
||||
maxSendQBytes: maxSendQBytes,
|
||||
conn: conn,
|
||||
maxSendQBytes: maxSendQBytes,
|
||||
writerSemaphore: utils.NewSemaphore(1),
|
||||
}
|
||||
result.writerSemaphore.Initialize(1)
|
||||
return &result
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@ package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -14,21 +12,21 @@ import (
|
||||
// A semaphore of capacity 1 can be used as a trylock.
|
||||
type Semaphore (chan empty)
|
||||
|
||||
// Initialize initializes a semaphore to a given capacity.
|
||||
func (semaphore *Semaphore) Initialize(capacity int) {
|
||||
*semaphore = make(chan empty, capacity)
|
||||
// NewSemaphore creates and initializes a semaphore to a given capacity.
|
||||
func NewSemaphore(capacity int) Semaphore {
|
||||
return make(chan empty, capacity)
|
||||
}
|
||||
|
||||
// Acquire acquires a semaphore, blocking if necessary.
|
||||
func (semaphore *Semaphore) Acquire() {
|
||||
(*semaphore) <- empty{}
|
||||
func (semaphore Semaphore) Acquire() {
|
||||
semaphore <- empty{}
|
||||
}
|
||||
|
||||
// TryAcquire tries to acquire a semaphore, returning whether the acquire was
|
||||
// successful. It never blocks.
|
||||
func (semaphore *Semaphore) TryAcquire() (acquired bool) {
|
||||
func (semaphore Semaphore) TryAcquire() (acquired bool) {
|
||||
select {
|
||||
case (*semaphore) <- empty{}:
|
||||
case semaphore <- empty{}:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
@ -38,14 +36,14 @@ func (semaphore *Semaphore) TryAcquire() (acquired bool) {
|
||||
// AcquireWithTimeout tries to acquire a semaphore, blocking for a maximum
|
||||
// of approximately `d` while waiting for it. It returns whether the acquire
|
||||
// was successful.
|
||||
func (semaphore *Semaphore) AcquireWithTimeout(timeout time.Duration) (acquired bool) {
|
||||
func (semaphore Semaphore) AcquireWithTimeout(timeout time.Duration) (acquired bool) {
|
||||
if timeout < 0 {
|
||||
return semaphore.TryAcquire()
|
||||
}
|
||||
|
||||
timer := time.NewTimer(timeout)
|
||||
select {
|
||||
case (*semaphore) <- empty{}:
|
||||
case semaphore <- empty{}:
|
||||
acquired = true
|
||||
case <-timer.C:
|
||||
acquired = false
|
||||
@ -57,9 +55,9 @@ func (semaphore *Semaphore) AcquireWithTimeout(timeout time.Duration) (acquired
|
||||
// AcquireWithContext tries to acquire a semaphore, blocking at most until
|
||||
// the context expires. It returns whether the acquire was successful.
|
||||
// Note that if the context is already expired, the acquire may succeed anyway.
|
||||
func (semaphore *Semaphore) AcquireWithContext(ctx context.Context) (acquired bool) {
|
||||
func (semaphore Semaphore) AcquireWithContext(ctx context.Context) (acquired bool) {
|
||||
select {
|
||||
case (*semaphore) <- empty{}:
|
||||
case semaphore <- empty{}:
|
||||
acquired = true
|
||||
case <-ctx.Done():
|
||||
acquired = false
|
||||
@ -67,15 +65,7 @@ func (semaphore *Semaphore) AcquireWithContext(ctx context.Context) (acquired bo
|
||||
return
|
||||
}
|
||||
|
||||
// Release releases a semaphore. It never blocks. (This is not a license
|
||||
// to program spurious releases.)
|
||||
func (semaphore *Semaphore) Release() {
|
||||
select {
|
||||
case <-(*semaphore):
|
||||
// good
|
||||
default:
|
||||
// spurious release
|
||||
log.Printf("spurious semaphore release (full to capacity %d)", cap(*semaphore))
|
||||
debug.PrintStack()
|
||||
}
|
||||
// Release releases a semaphore.
|
||||
func (semaphore Semaphore) Release() {
|
||||
<-semaphore
|
||||
}
|
||||
|
@ -10,8 +10,7 @@ import (
|
||||
|
||||
func TestTryAcquire(t *testing.T) {
|
||||
count := 3
|
||||
var sem Semaphore
|
||||
sem.Initialize(count)
|
||||
sem := NewSemaphore(count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
assertEqual(sem.TryAcquire(), true, t)
|
||||
@ -24,8 +23,7 @@ func TestTryAcquire(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAcquireWithTimeout(t *testing.T) {
|
||||
var sem Semaphore
|
||||
sem.Initialize(1)
|
||||
sem := NewSemaphore(1)
|
||||
|
||||
assertEqual(sem.TryAcquire(), true, t)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user