Files
gocryptotrader/exchanges/stream/stream_match.go
Adrian Gallagher 9a4eb9de84 CI: Fix golangci-lint linter issues, add prealloc linter and bump version depends for Go 1.18 (#915)
* Bump CI versions

* Specifically set go version as 1.17.x bumps it to 1.18

* Another

* Adjust AppVeyor

* Part 1 of linter issues

* Part 2

* Fix various linters and improvements

* Part 3

* Finishing touches

* Tests and EqualFold

* Fix nitterinos plus bonus requester jobs bump for exchanges with large number of tests

* Fix nitterinos and bump golangci-lint timeout for AppVeyor

* Address nits, ensure all books are returned on err due to syncer regression

* Fix the wiggins

* Fix duplication

* Fix nitterinos
2022-04-20 13:45:15 +10:00

81 lines
1.8 KiB
Go

package stream
import (
"errors"
"sync"
)
// NewMatch returns a new matcher
func NewMatch() *Match {
return &Match{
m: make(map[interface{}]chan []byte),
}
}
// Match is a distributed subtype that handles the matching of requests and
// responses in a timely manner, reducing the need to differentiate between
// connections. Stream systems fan in all incoming payloads to one routine for
// processing.
type Match struct {
m map[interface{}]chan []byte
mu sync.Mutex
}
// Incoming matches with request, disregarding the returned payload
func (m *Match) Incoming(signature interface{}) bool {
return m.IncomingWithData(signature, nil)
}
// IncomingWithData matches with requests and takes in the returned payload, to
// be processed outside of a stream processing routine
func (m *Match) IncomingWithData(signature interface{}, data []byte) bool {
m.mu.Lock()
defer m.mu.Unlock()
ch, ok := m.m[signature]
if ok {
select {
case ch <- data:
default:
// this shouldn't occur but if it does continue to process as normal
return false
}
return true
}
return false
}
// Sets the signature response channel for incoming data
func (m *Match) set(signature interface{}) (matcher, error) {
var ch chan []byte
m.mu.Lock()
if _, ok := m.m[signature]; ok {
m.mu.Unlock()
return matcher{}, errors.New("signature collision")
}
// This is buffered so we don't need to wait for receiver.
ch = make(chan []byte, 1)
m.m[signature] = ch
m.mu.Unlock()
return matcher{
C: ch,
sig: signature,
m: m,
}, nil
}
// matcher defines a payload matching return mechanism
type matcher struct {
C chan []byte
sig interface{}
m *Match
}
// Cleanup closes underlying channel and deletes signature from map
func (m *matcher) Cleanup() {
m.m.mu.Lock()
close(m.C)
delete(m.m.m, m.sig)
m.m.mu.Unlock()
}