cgen: add support for shared maps (#7042)
parent
e3fab7e076
commit
a128ab4313
|
@ -2355,6 +2355,25 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
value_typ_str := g.typ(node.value_type)
|
||||
value_typ := g.table.get_type_symbol(node.value_type)
|
||||
size := node.vals.len
|
||||
mut shared_styp := '' // only needed for shared &[]{...}
|
||||
mut styp := ''
|
||||
is_amp := g.is_amp
|
||||
g.is_amp = false
|
||||
if is_amp {
|
||||
g.out.go_back(1) // delete the `&` already generated in `prefix_expr()
|
||||
if g.is_shared {
|
||||
mut shared_typ := node.typ.set_flag(.shared_f)
|
||||
shared_styp = g.typ(shared_typ)
|
||||
g.writeln('($shared_styp*)memdup(&($shared_styp){.val = ')
|
||||
} else {
|
||||
styp = g.typ(node.typ)
|
||||
g.write('($styp*)memdup(&') // TODO: doesn't work with every compiler
|
||||
}
|
||||
} else {
|
||||
if g.is_shared {
|
||||
g.writeln('{.val = ($styp*)')
|
||||
}
|
||||
}
|
||||
if size > 0 {
|
||||
if value_typ.kind == .function {
|
||||
g.write('new_map_init($size, sizeof(voidptr), _MOV(($key_typ_str[$size]){')
|
||||
|
@ -2378,6 +2397,14 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
} else {
|
||||
g.write('new_map_1(sizeof($value_typ_str))')
|
||||
}
|
||||
if g.is_shared {
|
||||
g.write(', .mtx = sync__new_rwmutex()}')
|
||||
if is_amp {
|
||||
g.write(', sizeof($shared_styp))')
|
||||
}
|
||||
} else if is_amp {
|
||||
g.write(', sizeof($styp))')
|
||||
}
|
||||
}
|
||||
ast.None {
|
||||
g.write('opt_none()')
|
||||
|
@ -3715,10 +3742,17 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
|||
if g.is_assign_lhs && !g.is_array_set && !get_and_set_types {
|
||||
g.is_array_set = true
|
||||
g.write('map_set(')
|
||||
if !left_is_ptr {
|
||||
if !left_is_ptr || node.left_type.has_flag(.shared_f) {
|
||||
g.write('&')
|
||||
}
|
||||
g.expr(node.left)
|
||||
if node.left_type.has_flag(.shared_f) {
|
||||
if left_is_ptr {
|
||||
g.write('->val')
|
||||
} else {
|
||||
g.write('.val')
|
||||
}
|
||||
}
|
||||
g.write(', ')
|
||||
g.expr(node.index)
|
||||
if elem_typ.kind == .function {
|
||||
|
@ -3744,10 +3778,17 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
|||
} else {
|
||||
g.write('(*($elem_type_str*)map_get(')
|
||||
}
|
||||
if node.left_type.is_ptr() {
|
||||
if node.left_type.is_ptr() && !node.left_type.has_flag(.shared_f) {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(node.left)
|
||||
if node.left_type.has_flag(.shared_f) {
|
||||
if left_is_ptr {
|
||||
g.write('->val')
|
||||
} else {
|
||||
g.write('.val')
|
||||
}
|
||||
}
|
||||
g.write(', ')
|
||||
g.expr(node.index)
|
||||
if elem_typ.kind == .function {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import sync
|
||||
|
||||
fn incr(shared foo map[string]int, key string, sem sync.Semaphore) {
|
||||
for _ in 0 .. 100000 {
|
||||
lock foo {
|
||||
foo[key] = foo[key] + 1
|
||||
}
|
||||
}
|
||||
sem.post()
|
||||
}
|
||||
|
||||
fn test_shared_array() {
|
||||
shared foo := &{'p': 10, 'q': 20}
|
||||
sem := sync.new_semaphore()
|
||||
go incr(shared foo, 'p', sem)
|
||||
go incr(shared foo, 'q', sem)
|
||||
go incr(shared foo, 'p', sem)
|
||||
go incr(shared foo, 'q', sem)
|
||||
for _ in 0 .. 50000 {
|
||||
lock foo {
|
||||
unsafe {
|
||||
foo['p'] = foo['p'] - 2
|
||||
foo['q'] = foo['q'] + 3
|
||||
}
|
||||
}
|
||||
}
|
||||
for _ in 0..4 {
|
||||
sem.wait()
|
||||
}
|
||||
rlock foo {
|
||||
fp := unsafe { foo['p'] }
|
||||
fq := unsafe { foo['q'] }
|
||||
assert fp == 100010
|
||||
assert fq == 350020
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue