Created
August 23, 2014 21:23
-
-
Save yifan-gu/529f305dd89685fda299 to your computer and use it in GitHub Desktop.
simulator for HyParView protocol bootstraping
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math/rand" | |
"sync/atomic" | |
"time" | |
) | |
var makeup int32 | |
var breakup int32 | |
var messageSent int32 | |
type member struct { | |
fanout int | |
totalPool []*member | |
id int | |
friends []int | |
makeup chan int | |
breakup chan int | |
needNewFriend chan bool | |
} | |
func (m *member) run() { | |
for { | |
select { | |
case id := <-m.makeup: | |
atomic.AddInt32(&makeup, 1) | |
if len(m.friends) < m.fanout+2 { | |
m.friends = append(m.friends, id) | |
} else { | |
vindex := rand.Intn(len(m.friends)) | |
victim := m.friends[vindex] | |
m.totalPool[victim].breakup <- m.id | |
m.friends[vindex] = id | |
} | |
case id := <-m.breakup: | |
atomic.AddInt32(&breakup, 1) | |
index := -1 | |
for i := range m.friends { | |
if m.friends[i] == id { | |
index = i | |
break | |
} | |
} | |
if index >= 0 { | |
// Slot found for making new friends | |
newFriend := rand.Intn(len(m.totalPool)) | |
m.friends[index] = newFriend | |
m.totalPool[newFriend].makeup <- m.id | |
} | |
case <-m.needNewFriend: | |
if len(m.friends) < m.fanout { | |
newFriend := rand.Intn(len(m.totalPool)) | |
m.friends = append(m.friends, newFriend) | |
m.totalPool[newFriend].makeup <- m.id | |
} | |
if len(m.friends) < m.fanout { | |
m.needNewFriend <- true | |
} | |
} | |
atomic.AddInt32(&messageSent, 1) | |
} | |
} | |
func main() { | |
n := 10000 | |
fan := 5 | |
m := make([]*member, n) | |
for i := range m { | |
m[i] = &member{ | |
totalPool: m, | |
fanout: fan, | |
id: i, | |
friends: make([]int, 0, fan), | |
makeup: make(chan int, 1024), | |
breakup: make(chan int, 1024), | |
needNewFriend: make(chan bool, 1024), | |
} | |
} | |
for i := range m { | |
m[i].needNewFriend <- true | |
go m[i].run() | |
} | |
for j := 0; ; j++ { | |
select { | |
case <-time.After(time.Millisecond): | |
fmt.Println("round ", j) | |
for i := range m { | |
fmt.Println(i, ": ", m[i].friends) | |
} | |
fmt.Println("makeup: ", makeup, "breakup: ", breakup) | |
atomic.StoreInt32(&makeup, 0) | |
atomic.StoreInt32(&breakup, 0) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment