Coroutine-safe maps found on the Internet are all implemented using mutex locks or read and write locks. Here, a single coroutine is used to implement them, that is, all addition, deletion, search and modification operations are integrated into a goroutine, so that there will definitely be no problem of multi-thread concurrent access.
The basic idea is to start a long-running goroutine in the background, block the request req in your channel, and req is divided into different requests, such as reading key, writing key, etc., and then perform various operations in this goroutine.
Example: The Get method sends a request to readSig (channel). The request is a pointer to readReq. When the run method receives the signal, it reads the underlying map and writes the value to readReq's value (value is a channel). The receive value blocked by the Get method, and returns the value when received.
ps: It took more than two hours to finish writing, but I just did a simple test, and I didn’t test in depth, and I didn’t test the performance. In the future, I will test the correctness and how the performance is compared to the locked writing method.
package util type smap struct { m map[interface{}]interface{} readSig chan *readReq writeSig chan *writeReq lenSig chan *lenReq terminateSig chan bool delSig chan *delReq scanSig chan *scanReq } type readReq struct { key interface{} value interface{} ok chan bool } type writeReq struct { key interface{} value interface{} ok chan bool } type lenReq struct { len chan int } type delReq struct { key interface{} ok chan bool } type scanReq struct { do func(interface{}, interface{}) doWithBreak func(interface{}, interface{}) bool brea int done chan bool } // NewSmap returns an instance of the pointer of safemap func NewSmap() *smap { var mp smap = make(map[interface{}]interface{}) = make(chan *readReq) = make(chan *writeReq) = make(chan *lenReq) = make(chan *delReq) = make(chan *scanReq) go () return &mp } //background function to operate map in one goroutine //this can ensure that the map is Concurrent security. func (s *smap) run() { for { select { case read := <-: if value, ok := []; ok { = value <- true } else { <- false } case write := <-: [] = <- true case l := <-: <- len() case sc := <-: if == 0 { for k, v := range { (k, v) } } else { for k, v := range { ret := (k, v) if ret { break } } } <- true case d := <-: delete(, ) <- true case <-: return } } } //Get returns the value of key which provided. //if the key not found in map, ok will be false. func (s *smap) Get(key interface{}) (interface{}, bool) { req := &readReq{ key: key, ok: make(chan bool), } <- req ok := <- return , ok } //Set set the key and value to map //ok returns true indicates that key and value is successfully added to map func (s *smap) Set(key interface{}, value interface{}) bool { req := &writeReq{ key: key, value: value, ok: make(chan bool), } <- req return <- //TODO is temporarily synchronous, and there may be problems with the use of asynchronous.} //Clear clears all the key and value in map. func (s *smap) Clear() { = make(map[interface{}]interface{}) } //Size returns the size of map. func (s *smap) Size() int { req := &lenReq{ len: make(chan int), } <- req return <- } //terminate function. this function is usually called for debug. //after this do NOT use smap again, because it can make your program block. func (s *smap) TerminateBackGoroutine() { <- true } //Del delete the key in map func (s *smap) Del(key interface{}) bool { req := &delReq{ key: key, ok: make(chan bool), } <- req return <- } //scan the map. do is a function which operate all of the key and value in map func (s *smap) EachItem(do func(interface{}, interface{})) { req := &scanReq{ do: do, brea: 0, done: make(chan bool), } <- req <- } //scan the map util function 'do' returns true. do is a function which operate all of the key and value in map func (s *smap) EachItemBreak(do func(interface{}, interface{}) bool, condition bool) { req := &scanReq{ doWithBreak: do, brea: 1, done: make(chan bool), } <- req <- } //Exists checks whether the key which provided is exists in map func (s *smap) Exists(key interface{}) bool { if _,found := (key); found { return true } return false }
Github address:/hackssssss/safemap
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.