diff --git a/hold/hold.go b/hold/hold.go new file mode 100644 index 000000000..dd10c7070 --- /dev/null +++ b/hold/hold.go @@ -0,0 +1,68 @@ +package hold + +import "github.com/nu7hatch/gouuid" + +type holdchan chan interface{} +type gethold struct { + id *uuid.UUID + reply chan holdchan +} +type delhold struct { + id *uuid.UUID +} + +type Holder struct { + data map[uuid.UUID]holdchan + getchan chan gethold + delchan chan delhold +} + +var Hold Holder + +func (self *Holder) DelChan(id *uuid.UUID) { + req := delhold{id} + self.delchan <- req +} + +func (self *Holder) GetChan(id *uuid.UUID) holdchan { + reply := make(chan holdchan) + req := gethold{id, reply} + self.getchan <- req + return <-reply +} + +func (self *Holder) Get(id *uuid.UUID) interface{} { + ch := self.GetChan(id) + return <-ch +} + +func (self *Holder) Set(id *uuid.UUID, value interface{}) { + ch := self.GetChan(id) + go func() { + ch <- value + self.DelChan(id) + }() +} + +func (self *Holder) run() { + var greq gethold + var dreq delhold + for { + select { + case greq = <-self.getchan: + item, ok := self.data[*greq.id] + if !ok { + item = make(holdchan) + self.data[*greq.id] = item + } + greq.reply <- item + case dreq = <-self.delchan: + delete(self.data, *dreq.id) + } + } +} + +func init() { + Hold = Holder{make(map[uuid.UUID]holdchan), make(chan gethold), make(chan delhold)} + go Hold.run() +} diff --git a/hold/hold_test.go b/hold/hold_test.go new file mode 100644 index 000000000..a57edcc8f --- /dev/null +++ b/hold/hold_test.go @@ -0,0 +1,27 @@ +package hold + +import ( + "testing" + "time" + + "github.com/nu7hatch/gouuid" + . "github.com/smartystreets/goconvey/convey" +) + +func TestHoldChan(t *testing.T) { + Convey("set then get", t, func() { + id, _ := uuid.NewV4() + Hold.Set(id, "derp") + derp := Hold.Get(id) + So(derp, ShouldEqual, "derp") + }) + Convey("get then set", t, func() { + id, _ := uuid.NewV4() + go func() { + time.Sleep(time.Second / 10) + Hold.Set(id, "derpsy") + }() + derp := Hold.Get(id) + So(derp, ShouldEqual, "derpsy") + }) +}