Skip to content

panii/erlang2go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Write goroutine in erlang style

package erlang_style_safemap

import (
    "github.com/panii/erlang2go/erlang"
)

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 safeMapProcess erlang.Process

const (
    remove erlang.Atom = iota
    end
    find
    insert
    length
    update
    result
)


// API
func New() SafeMap {
    var Pid = erlang.Spawn(func(Self erlang.Process) {
        run(Self)
    })
    
    return safeMapProcess(Pid)
}

func (Pid safeMapProcess) Insert(Key string, Value interface{}) {
    erlang.Send(erlang.Process(Pid), insert, Key, Value)
}

func (Pid safeMapProcess) Delete(Key string) {
    erlang.Send(erlang.Process(Pid), remove, Key)
}

func (Pid safeMapProcess) Find(Key string) (value interface{}, found bool) {
    var Self = erlang.Self()
    
    Self.Send(erlang.Process(Pid), find, Key)
    
    Self.Receive(erlang.Patten{
       result: func(args ...interface{}) {
           value = args[1]
           found = args[2].(bool)
       },
    })
    
    return
}

func (Pid safeMapProcess) Len() (len int) {
    var Self = erlang.Self()
    
    Self.Send(erlang.Process(Pid), length)
    
    Self.Receive(erlang.Patten{
       result: func(args ...interface{}) {
           len = args[1].(int)
       },
    })
    
    return
}

func (Pid safeMapProcess) Update(Key string, UpdateFunc UpdateFunc) {
    erlang.Send(erlang.Process(Pid), update, Key, UpdateFunc)
}

func (Pid safeMapProcess) Close() (Store map[string]interface{}) {
    var Self = erlang.Self()
    
    Self.Send(erlang.Process(Pid), end)
    
    Self.Receive(erlang.Patten{
       result: func(args ...interface{}) {
           Store = args[1].(map[string]interface{})
       },
    })
    
    return
}

// internal
func run(Self erlang.Process) {
    var Store = make(map[string]interface{})
    
    Self.LoopReceive(erlang.PattenLoop{
        insert: func(args ...interface{}) erlang.LoopSig {
            var Key = args[1].(string)
            var Value = args[2]
            Store[Key] = Value
            
            return erlang.LoopContinue
        },
        remove: func(args ...interface{}) erlang.LoopSig {
            var Key = args[1].(string)
            delete(Store, Key)
            
            return erlang.LoopContinue
        },
        find: func(args ...interface{}) erlang.LoopSig {
            var Key = args[1].(string)
            var Parent = args[2].(erlang.Process)
            Value, Found := Store[Key]
            
            erlang.Send(Parent, result, Value, Found)
            
            return erlang.LoopContinue
        },
        length: func(args ...interface{}) erlang.LoopSig {
            var Parent = args[1].(erlang.Process)
            
            erlang.Send(Parent, result, len(Store))
            
            return erlang.LoopContinue
        },
        update: func(args ...interface{}) erlang.LoopSig {
            var Key = args[1].(string)
            var Updater = args[2].(UpdateFunc)
            Value, Found := Store[Key]
            Store[Key] = Updater(Value, Found)
            
            return erlang.LoopContinue
        },
        end: func(args ...interface{}) erlang.LoopSig {
            close(Self)
            var Parent = args[1].(erlang.Process)
            
            erlang.Send(Parent, result, Store)
            
            return erlang.LoopEnd
        },
    })
}
package golang_safemap

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 safeMap chan commandData

type commandData struct {
    action commandAction
    key string
    value interface{}
    result chan<- interface{}
    data chan<- map[string]interface{}
    updater UpdateFunc
}

type commandAction int

const (
    remove commandAction = iota
    end
    find
    insert
    length
    update
)

type findResult struct {
    value interface{}
    found bool
}

// API
func New() SafeMap {
    sm := make(safeMap)
    go sm.run()
    
    return sm
}

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}
}

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}
    
    return (<-reply).(int)
}

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:
            store[command.key] = command.value
        case 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
            break
        }
    }
}

About

Write goroutine in erlang style

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages