cgen: add support for shared maps (#7042)

pull/7050/head
Uwe Krüger 2020-11-30 13:25:14 +01:00 committed by GitHub
parent e3fab7e076
commit a128ab4313
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 2 deletions

View File

@ -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 {

View File

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