Skip to content

Instantly share code, notes, and snippets.

@ibigbug
Created May 25, 2016 04:31
Show Gist options
  • Save ibigbug/3cf44c8276719e628cb265dba4820cfa to your computer and use it in GitHub Desktop.
Save ibigbug/3cf44c8276719e628cb265dba4820cfa to your computer and use it in GitHub Desktop.
package safemap
import (
"fmt"
)
const (
remove commandAction = iota
end
find
insert
length
update
)
type commandAction int
type SafeMap interface {
Insert(string, interface{})
Delete(string)
Find(string) (interface{}, bool)
Len() int
Update(string, UpdateFunc)
Close() map[string]interface{}
}
type UpdateFunc func(interface{}, bool) interface{}
type commandData struct {
action commandAction
key string
value interface{}
result chan<- interface{}
data chan<- map[string]interface{}
updater UpdateFunc
}
/* internal safeMap as the chan of commandData*/
type safeMap chan commandData
/* instead of insert the data directly into the map, here we send the message commandData to the channal*/
func (sm safeMap) Insert(key string, value interface{}) {
sm <- commandData{action: insert, key: key, value: value}
}
func (sm safeMap) Delete(key string) {
sm <- commandData{action: remove, key: key}
}
/*the contract for the Find to communcation with underline channel*/
type findResult struct {
value interface{}
found bool
}
/* when find the element from the map, instead of get the element from map
ask the channel for data, and get the value via a channel
the Find method creates it's own reply channel so that it can receive a response from the safemap channel
*/
func (sm safeMap) Find(key string) (value interface{}, found bool) {
reply := make(chan interface{})
sm <- commandData{action: find, key: key, result: reply}
result := (<-reply).(findResult)
return result.value, result.found
}
func (sm safeMap) Len() int {
reply := make(chan interface{})
sm <- commandData{action: length, result: reply}
result := (<-reply).(int)
return result
}
/*
safemap.Update(key, func(value interface{}, found bool) interface{} {
if found {
return value.(flout64) * 12
}
return 0.0
})
*/
func (sm safeMap) Update(key string, updater UpdateFunc) {
sm <- commandData{action: update, key: key, updater: updater}
}
func (sm safeMap) Close() map[string]interface{} {
reply := make(chan map[string]interface{})
sm <- commandData{action: end, data: reply}
return <-reply
}
func (sm safeMap) run() {
store := make(map[string]interface{})
for command := range sm {
switch command.action {
case insert:
fmt.Println("insert")
store[command.key] = command.value
case remove:
fmt.Println("remove")
delete(store, command.key)
case find:
value, found := store[command.key]
command.result <- findResult{value, found}
case length:
command.result <- len(store)
case update:
value, found := store[command.key]
store[command.key] = command.updater(value, found)
case end:
close(sm)
command.data <- store
}
}
}
func New() SafeMap {
sm := make(safeMap)
go sm.run()
return sm
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment