Recently I have developed a golang TCP network programming framework name Tao, in file util.go there's a concurrent map called ConnectionMap which I use to manage incoming TCP connections, it is a int64-to-Connection map read and writen by multiple go-routines.
Then I developed a remote control system based on Tao, a mobile app can control devices via this system. However I find something is wrong with ConnectionMap: some already-closed connections are not removed from this map and remain existed.
I'm not quite sure it is the reason that after a while the app can hardly connect to this sytem, but I am really confused that IS THIS THE RIGHT WAY TO WRITE A CONCURRENT MAP? IS SOMETHING WRONG WITH IT? Thank you.
type ConnectionMap struct{
sync.RWMutex
m map[int64]Connection
}
func NewConnectionMap() *ConnectionMap {
return &ConnectionMap{
m: make(map[int64]Connection),
}
}
func (cm *ConnectionMap)Clear() {
cm.Lock()
cm.m = make(map[int64]Connection)
cm.Unlock()
}
func (cm *ConnectionMap)Get(k int64) (Connection, bool) {
cm.RLock()
conn, ok := cm.m[k]
cm.RUnlock()
return conn, ok
}
func (cm *ConnectionMap)IterKeys() <-chan int64 {
kch := make(chan int64)
go func() {
cm.RLock()
for k, _ := range cm.m {
kch<- k
}
cm.RUnlock()
close(kch)
}()
return kch
}
func (cm *ConnectionMap)IterValues() <-chan Connection {
vch := make(chan Connection)
go func() {
cm.RLock()
for _, v := range cm.m {
vch<- v
}
cm.RUnlock()
close(vch)
}()
return vch
}
func (cm *ConnectionMap)Put(k int64, v Connection) {
cm.Lock()
cm.m[k] = v
cm.Unlock()
}
func (cm *ConnectionMap)Remove(k int64) {
cm.Lock()
delete(cm.m, k)
cm.Unlock()
}
func (cm *ConnectionMap)Size() int {
cm.RLock()
size := len(cm.m)
cm.RUnlock()
return size
}
func (cm *ConnectionMap)IsEmpty() bool {
return cm.Size() <= 0
}