Merge pull request #29 from alsm/master

Close channel to signal goroutines to quit and waitgroup to confirm that...
This commit is contained in:
Thomas Jager 2014-05-03 00:32:17 +02:00
commit 2e87f54e96
2 changed files with 28 additions and 40 deletions

35
irc.go
View File

@ -37,12 +37,12 @@ const (
// Read data from a connection. To be used as a goroutine.
func (irc *Connection) readLoop() {
defer irc.Done()
br := bufio.NewReaderSize(irc.socket, 512)
for {
select {
case <-irc.endread:
irc.readerExit <- true
case <-irc.end:
return
default:
// Set a read deadline based on the combined timeout and ping frequency
@ -97,21 +97,19 @@ func (irc *Connection) readLoop() {
irc.RunCallbacks(event)
}
}
irc.readerExit <- true
return
}
// Loop to write to a connection. To be used as a goroutine.
func (irc *Connection) writeLoop() {
defer irc.Done()
for {
select {
case <-irc.endwrite:
irc.writerExit <- true
case <-irc.end:
return
default:
b, ok := <-irc.pwrite
if !ok || b == "" || irc.socket == nil {
irc.writerExit <- true
return
}
@ -130,17 +128,17 @@ func (irc *Connection) writeLoop() {
if err != nil {
irc.Error <- err
irc.writerExit <- true
return
}
}
}
irc.writerExit <- true
return
}
// Pings the server if we have not received any messages for 5 minutes
// to keep the connection alive. To be used as a goroutine.
func (irc *Connection) pingLoop() {
defer irc.Done()
ticker := time.NewTicker(1 * time.Minute) // Tick every minute for monitoring
ticker2 := time.NewTicker(irc.PingFreq) // Tick at the ping frequency.
for {
@ -158,10 +156,9 @@ func (irc *Connection) pingLoop() {
irc.nickcurrent = irc.nick
irc.SendRawf("NICK %s", irc.nick)
}
case <-irc.endping:
case <-irc.end:
ticker.Stop()
ticker2.Stop()
irc.pingerExit <- true
return
}
}
@ -284,15 +281,11 @@ func (irc *Connection) Mode(target string, modestring ...string) {
// A disconnect sends all buffered messages (if possible),
// stops all goroutines and then closes the socket.
func (irc *Connection) Disconnect() {
irc.endping <- true
irc.endwrite <- true
irc.endread <- true
close(irc.end)
close(irc.pwrite)
close(irc.pread)
<-irc.readerExit
<-irc.writerExit
<-irc.pingerExit
irc.Wait()
irc.socket.Close()
irc.socket = nil
if irc.netsock != nil {
@ -362,6 +355,7 @@ func (irc *Connection) Connect(server string) error {
irc.pwrite = make(chan string, 10)
irc.Error = make(chan error, 2)
irc.Add(3)
go irc.readLoop()
go irc.writeLoop()
go irc.pingLoop()
@ -390,12 +384,7 @@ func IRC(nick, user string) *Connection {
nick: nick,
user: user,
Log: log.New(os.Stdout, "", log.LstdFlags),
readerExit: make(chan bool),
writerExit: make(chan bool),
pingerExit: make(chan bool),
endping: make(chan bool),
endread: make(chan bool),
endwrite: make(chan bool),
end: make(chan struct{}),
Version: VERSION,
KeepAlive: 4 * time.Minute,
Timeout: 1 * time.Minute,

View File

@ -8,10 +8,12 @@ import (
"crypto/tls"
"log"
"net"
"sync"
"time"
)
type Connection struct {
sync.WaitGroup
Debug bool
Error chan error
Password string
@ -25,8 +27,7 @@ type Connection struct {
socket net.Conn
netsock net.Conn
pread, pwrite chan string
readerExit, writerExit, pingerExit chan bool
endping, endread, endwrite chan bool
end chan struct{}
nick string //The nickname we want.
nickcurrent string //The nickname we currently have.
@ -43,7 +44,6 @@ type Connection struct {
stopped bool
}
// A struct to represent an event.
type Event struct {
Code string
@ -55,7 +55,6 @@ type Event struct {
Arguments []string
}
// Retrieve the last message from Event arguments.
// This function leaves the arguments untouched and
// returns an empty string if there are none.