-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathstriped_channel.go
71 lines (61 loc) · 1.68 KB
/
striped_channel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package sync
import (
"fmt"
"sync"
)
const (
hashEntriesPerChannel = 200
)
// StripedChannel is a partitioned channel that consistently maps a key space
// to a set of channels.
type StripedChannel struct {
channels []chan interface{}
hashRing *ring
closeFunc sync.Once
}
// NewStripedChannel returns a new StripedChannel with a static number of
// channels.
func NewStripedChannel(count, queueSize uint) *StripedChannel {
channels := make([]chan interface{}, count)
ringEntries := make(map[string]interface{})
for i := range channels {
channels[i] = make(chan interface{}, queueSize)
ringEntries[fmt.Sprintf("chan%d", i)] = i
}
return &StripedChannel{
channels: channels,
hashRing: newRing(ringEntries, hashEntriesPerChannel),
}
}
// GetChannels returns the set of all receiver channels.
func (c *StripedChannel) GetChannels() []<-chan interface{} {
receivers := make([]<-chan interface{}, len(c.channels))
for i, channel := range c.channels {
receivers[i] = channel
}
return receivers
}
// Send sends the value to the channel that maps to the key. It is non-blocking
// and returns whether the value was put on the channel.
func (c *StripedChannel) Send(key []byte, value interface{}) bool {
sharded := c.hashRing.shard(key).(int)
select {
case c.channels[sharded] <- value:
default:
return false
}
return true
}
// BlockingSend is a blocking variation of Send.
func (c *StripedChannel) BlockingSend(key []byte, value interface{}) {
sharded := c.hashRing.shard(key).(int)
c.channels[sharded] <- value
}
// Close closes all underlying channels.
func (c *StripedChannel) Close() {
c.closeFunc.Do(func() {
for _, channel := range c.channels {
close(channel)
}
})
}