cgen: add support for shared arrays (#5721)
parent
38000f8622
commit
88248b1b66
|
@ -2376,10 +2376,17 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
||||||
if g.is_assign_lhs && !is_selector && node.is_setter {
|
if g.is_assign_lhs && !is_selector && node.is_setter {
|
||||||
g.is_array_set = true
|
g.is_array_set = true
|
||||||
g.write('array_set(')
|
g.write('array_set(')
|
||||||
if !left_is_ptr {
|
if !left_is_ptr || node.left_type.has_flag(.shared_f) {
|
||||||
g.write('&')
|
g.write('&')
|
||||||
}
|
}
|
||||||
g.expr(node.left)
|
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.write(', ')
|
||||||
g.expr(node.index)
|
g.expr(node.index)
|
||||||
mut need_wrapper := true
|
mut need_wrapper := true
|
||||||
|
@ -2404,10 +2411,17 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
||||||
info.elem_type != table.string_type {
|
info.elem_type != table.string_type {
|
||||||
// TODO move this
|
// TODO move this
|
||||||
g.write('*($elem_type_str*)array_get(')
|
g.write('*($elem_type_str*)array_get(')
|
||||||
if left_is_ptr {
|
if left_is_ptr && !node.left_type.has_flag(.shared_f) {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
g.expr(node.left)
|
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.write(', ')
|
||||||
g.expr(node.index)
|
g.expr(node.index)
|
||||||
g.write(') ')
|
g.write(') ')
|
||||||
|
@ -2428,10 +2442,17 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.write('(*($elem_type_str*)array_get(')
|
g.write('(*($elem_type_str*)array_get(')
|
||||||
if left_is_ptr {
|
if left_is_ptr && !node.left_type.has_flag(.shared_f) {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
g.expr(node.left)
|
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.write(', ')
|
||||||
g.expr(node.index)
|
g.expr(node.index)
|
||||||
g.write('))')
|
g.write('))')
|
||||||
|
@ -4497,6 +4518,24 @@ _Interface* I_${cctype}_to_Interface_${interface_name}_ptr($cctype* x) {
|
||||||
|
|
||||||
fn (mut g Gen) array_init(it ast.ArrayInit) {
|
fn (mut g Gen) array_init(it ast.ArrayInit) {
|
||||||
type_sym := g.table.get_type_symbol(it.typ)
|
type_sym := g.table.get_type_symbol(it.typ)
|
||||||
|
styp := g.typ(it.typ)
|
||||||
|
mut shared_styp := '' // only needed for shared &[]{...}
|
||||||
|
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 := it.typ.set_flag(.shared_f)
|
||||||
|
shared_styp = g.typ(shared_typ)
|
||||||
|
g.writeln('($shared_styp*)memdup(&($shared_styp){.val = ')
|
||||||
|
} else {
|
||||||
|
g.write('($styp*)memdup(&') // TODO: doesn't work with every compiler
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if g.is_shared {
|
||||||
|
g.writeln('{.val = ($styp*)')
|
||||||
|
}
|
||||||
|
}
|
||||||
if type_sym.kind == .array_fixed {
|
if type_sym.kind == .array_fixed {
|
||||||
g.write('{')
|
g.write('{')
|
||||||
for i, expr in it.exprs {
|
for i, expr in it.exprs {
|
||||||
|
@ -4568,6 +4607,14 @@ fn (mut g Gen) array_init(it ast.ArrayInit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.write('}))')
|
g.write('}))')
|
||||||
|
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))')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `ui.foo(button)` =>
|
// `ui.foo(button)` =>
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import sync
|
||||||
|
import time
|
||||||
|
|
||||||
|
fn incr(shared foo []int, index int) {
|
||||||
|
for _ in 0 .. 100000 {
|
||||||
|
lock foo {
|
||||||
|
foo[index] = foo[index] + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lock foo {
|
||||||
|
foo[2]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_shared_array() {
|
||||||
|
shared foo := &[10, 20, 0]
|
||||||
|
go incr(shared foo, 0)
|
||||||
|
go incr(shared foo, 1)
|
||||||
|
go incr(shared foo, 0)
|
||||||
|
go incr(shared foo, 1)
|
||||||
|
for _ in 0 .. 50000 {
|
||||||
|
lock foo {
|
||||||
|
foo[0] -= 2
|
||||||
|
foo[1] += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mut finished_threads := 0
|
||||||
|
for {
|
||||||
|
rlock foo {
|
||||||
|
finished_threads = foo[2]
|
||||||
|
}
|
||||||
|
if finished_threads == 4 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.sleep_ms(100)
|
||||||
|
}
|
||||||
|
rlock foo {
|
||||||
|
assert foo[0] == 100010
|
||||||
|
assert foo[1] == 350020
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,8 +38,8 @@ fn test_shared_receiver_lock() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// the following would be a good application for a channel
|
// the following would be a good application for a channel
|
||||||
for finished := false; ; {
|
for finished := false; true; {
|
||||||
lock z {
|
rlock z {
|
||||||
finished = z.a == 0
|
finished = z.a == 0
|
||||||
}
|
}
|
||||||
if finished {
|
if finished {
|
||||||
|
@ -47,7 +47,7 @@ fn test_shared_receiver_lock() {
|
||||||
}
|
}
|
||||||
time.sleep_ms(100)
|
time.sleep_ms(100)
|
||||||
}
|
}
|
||||||
lock x, y {
|
rlock x, y {
|
||||||
assert x.a == 7 && y.a == 5
|
assert x.a == 7 && y.a == 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,9 @@ fn test_shared_lock() {
|
||||||
time.sleep_ms(20)
|
time.sleep_ms(20)
|
||||||
}
|
}
|
||||||
// wait until all read threads are finished
|
// wait until all read threads are finished
|
||||||
for finished := false; ; {
|
for finished := false; true; {
|
||||||
mut rr := 0
|
mut rr := 0
|
||||||
lock z {
|
rlock z {
|
||||||
rr = z.a
|
rr = z.a
|
||||||
finished = z.a == 0
|
finished = z.a == 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,9 @@ fn test_shared_lock() {
|
||||||
time.sleep_ms(20)
|
time.sleep_ms(20)
|
||||||
}
|
}
|
||||||
// wait until all read threads are finished
|
// wait until all read threads are finished
|
||||||
for finished := false; ; {
|
for finished := false; true; {
|
||||||
mut rr := 0
|
mut rr := 0
|
||||||
lock z {
|
rlock z {
|
||||||
rr = z.a
|
rr = z.a
|
||||||
finished = z.a == 0
|
finished = z.a == 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,8 @@ fn test_shared_lock() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// the following would be a good application for a channel
|
// the following would be a good application for a channel
|
||||||
for finished := false; ; {
|
for finished := false; true; {
|
||||||
lock z {
|
rlock z {
|
||||||
finished = z.a == 0
|
finished = z.a == 0
|
||||||
}
|
}
|
||||||
if finished {
|
if finished {
|
||||||
|
@ -47,7 +47,7 @@ fn test_shared_lock() {
|
||||||
}
|
}
|
||||||
time.sleep_ms(100)
|
time.sleep_ms(100)
|
||||||
}
|
}
|
||||||
lock x, y {
|
rlock x, y {
|
||||||
assert x.a == 7 && y.a == 5
|
assert x.a == 7 && y.a == 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue