Created
May 25, 2016 04:31
-
-
Save ibigbug/3cf44c8276719e628cb265dba4820cfa to your computer and use it in GitHub Desktop.
This file contains 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 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