mirror of
https://github.com/gissleh/irc.git
synced 2026-10-19 04:12:53 +00:00
Removed locking of global handlers, and updated documentation to highlight thread unsafety. This will help concurrency. The pattern of adding and removing handlers is discouraged and made impossible
This commit is contained in:
@@ -1,49 +1,26 @@
|
|||||||
package irc
|
package irc
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Handler is a function that is part of the irc event loop. It will receive all
|
// A Handler is a function that is part of the irc event loop. It will receive all
|
||||||
// events that haven't been killed up to that point.
|
// events.
|
||||||
type Handler func(event *Event, client *Client)
|
type Handler func(event *Event, client *Client)
|
||||||
|
|
||||||
var eventHandler struct {
|
var eventHandler struct {
|
||||||
mutex sync.RWMutex
|
|
||||||
handlers []Handler
|
handlers []Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
func emit(event *Event, client *Client) {
|
func emit(event *Event, client *Client) {
|
||||||
eventHandler.mutex.RLock()
|
|
||||||
for _, handler := range eventHandler.handlers {
|
for _, handler := range eventHandler.handlers {
|
||||||
handler(event, client)
|
handler(event, client)
|
||||||
}
|
}
|
||||||
eventHandler.mutex.RUnlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle adds a new handler to the irc handling. It returns a pointer that can be passed to RemoveHandler
|
// Handle adds a new handler to the irc handling. The handler may be called from multiple threads at the same
|
||||||
// later on to unsubscribe.
|
// time, so external resources should be locked if there are multiple clients. Adding handlers is not thread
|
||||||
func Handle(handler Handler) *Handler {
|
// safe and should be done prior to clients being created.Handle. Also, this handler will block the individual
|
||||||
eventHandler.mutex.Lock()
|
// client's event loop, so long operations that include network requests and the like should be done in a
|
||||||
defer eventHandler.mutex.Unlock()
|
// goroutine with the needed data **copied** from the handler function.
|
||||||
|
func Handle(handler Handler) {
|
||||||
eventHandler.handlers = append(eventHandler.handlers, handler)
|
eventHandler.handlers = append(eventHandler.handlers, handler)
|
||||||
return &eventHandler.handlers[len(eventHandler.handlers)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveHandler unregisters a handler.
|
|
||||||
func RemoveHandler(handlerPtr *Handler) (ok bool) {
|
|
||||||
eventHandler.mutex.Lock()
|
|
||||||
defer eventHandler.mutex.Unlock()
|
|
||||||
|
|
||||||
for i := range eventHandler.handlers {
|
|
||||||
if &eventHandler.handlers[i] == handlerPtr {
|
|
||||||
eventHandler.handlers = append(eventHandler.handlers[:i], eventHandler.handlers[i+1:]...)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ func TestHandle(t *testing.T) {
|
|||||||
t.Error("Event wasn't handled")
|
t.Error("Event wasn't handled")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !irc.RemoveHandler(handle) {
|
|
||||||
t.Error("Couldn't remove handler")
|
|
||||||
}
|
|
||||||
|
|
||||||
handled = false
|
handled = false
|
||||||
client.EmitSync(context.Background(), event)
|
client.EmitSync(context.Background(), event)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user