1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

all: remove rwshared keyword, make its semantics default for shared (#5710)

This commit is contained in:
Uwe Krüger 2020-07-07 01:57:31 +02:00 committed by GitHub
parent 013c0e6e16
commit ef02373061
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 70 additions and 96 deletions

View File

@ -35,13 +35,20 @@ atomic d := ...
- `c` can be passed to coroutines an accessed
*concurrently*.<sup>2</sup> In order to avoid data races it has to
be locked before access can occur and unlocked to allow access to
other coroutines. This is done by the following block structure:
other coroutines. This is done by one the following block structures:
```v
lock c {
// read, modify, write c
...
}
```
```v
rlock c {
// read c
...
}
```
Several variables may be specified: `lock x, y, z { ... }`.
They are unlocked in the opposite order.
- `d` can be passed to coroutines and accessed *concurrently*,

View File

@ -402,6 +402,7 @@ fn C.pthread_mutex_unlock(voidptr) int
fn C.pthread_rwlockattr_init(voidptr) int
fn C.pthread_rwlockattr_setkind_np(voidptr, int) int
fn C.pthread_rwlockattr_setpshared(voidptr, int) int
fn C.pthread_rwlock_init(voidptr, voidptr) int
fn C.pthread_rwlock_rdlock(voidptr) int
fn C.pthread_rwlock_wrlock(voidptr) int

View File

@ -33,6 +33,7 @@ pub fn new_rwmutex() &RwMutex {
C.pthread_rwlockattr_init(&a.attr)
// Give writer priority over readers
C.pthread_rwlockattr_setkind_np(&a.attr, C.PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
C.pthread_rwlockattr_setpshared(&a.attr, C.PTHREAD_PROCESS_PRIVATE)
C.pthread_rwlock_init(&m.mutex, &a.attr)
return m
}

View File

@ -450,7 +450,6 @@ pub:
pub mut:
lockeds []Ident // `x`, `y` in `lock x, y {`
is_expr bool
is_rw bool // `rwshared` needs special special handling even in `lock` case
typ table.Type
}

View File

@ -1158,9 +1158,6 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
if call_arg.share == .shared_t {
words = 'shared'
tok = 'shared'
} else if call_arg.share == .rwshared_t {
words = 'read/write shared'
tok = 'rwshared'
} else if call_arg.share == .atomic_t {
words = 'atomic'
tok = 'atomic'
@ -1176,9 +1173,6 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
if arg.typ.share() == .shared_t {
words = ' shared'
tok = 'shared'
} else if arg.typ.share() == .rwshared_t {
words = ' read/write shared'
tok = 'rwshared'
} else if arg.typ.share() == .atomic_t {
words = 'n atomic'
tok = 'atomic'
@ -1572,11 +1566,11 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
}
mut scope := c.file.scope.innermost(assign_stmt.pos.pos)
mut ident_var_info := left.var_info()
if ident_var_info.share in [.shared_t, .rwshared_t] {
if ident_var_info.share == .shared_t {
left_type = left_type.set_flag(.shared_f)
}
if ident_var_info.share in [.atomic_t, .rwshared_t] {
left_type = left_type.set_flag(.atomic_or_rw)
if ident_var_info.share == .atomic_t {
left_type = left_type.set_flag(.atomic_f)
}
assign_stmt.left_types[i] = left_type
ident_var_info.typ = left_type

View File

@ -59,10 +59,8 @@ mut:
is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&byte(0)` etc
is_sql bool // Inside `sql db{}` statement, generating sql instead of C (e.g. `and` instead of `&&` etc)
is_shared bool // for initialization of hidden mutex in `[rw]shared` literals
is_rwshared bool
optionals []string // to avoid duplicates TODO perf, use map
shareds []int // types with hidden mutex for which decl has been emitted
rwshareds []int // same with hidden rwmutex
inside_ternary int // ?: comma separated statements on a single line
inside_map_postfix bool // inside map++/-- postfix expr
inside_map_infix bool // inside map<</+=/-= infix expr
@ -408,22 +406,16 @@ fn (mut g Gen) register_optional(t table.Type) string {
}
fn (mut g Gen) find_or_register_shared(t table.Type, base string) string {
is_rw := t.has_flag(.atomic_or_rw)
prefix := if is_rw { 'rw' } else { '' }
sh_typ := '__${prefix}shared__$base'
sh_typ := '__shared__$base'
t_idx := t.idx()
if (is_rw && t_idx in g.rwshareds) || (!is_rw && t_idx in g.shareds) {
if t_idx in g.shareds {
return sh_typ
}
mtx_typ := if is_rw { 'sync__RwMutex' } else { 'sync__Mutex' }
mtx_typ := 'sync__RwMutex'
g.hotcode_definitions.writeln('struct $sh_typ { $base val; $mtx_typ* mtx; };')
g.typedefs2.writeln('typedef struct $sh_typ $sh_typ;')
// println('registered shared type $sh_typ')
if is_rw {
g.rwshareds << t_idx
} else {
g.shareds << t_idx
}
g.shareds << t_idx
return sh_typ
}
@ -1192,11 +1184,11 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
blank_assign = ident.kind == .blank_ident
if ident.info is ast.IdentVar {
share := (ident.info as ast.IdentVar).share
if share in [.shared_t, .rwshared_t] {
if share == .shared_t {
var_type = var_type.set_flag(.shared_f)
}
if share in [.atomic_t, .rwshared_t] {
var_type = var_type.set_flag(.atomic_or_rw)
if share == .atomic_t {
var_type = var_type.set_flag(.atomic_f)
}
}
}
@ -1327,7 +1319,6 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
g.write('*($styp*)')
}
g.is_shared = var_type.has_flag(.shared_f)
g.is_rwshared = var_type.has_flag(.atomic_or_rw)
if !cloned {
if is_decl {
if is_fixed_array_init && !has_val {
@ -1353,7 +1344,6 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
g.write(' })')
g.is_array_set = false
}
g.is_rwshared = false
g.is_shared = false
}
g.right_is_opt = false
@ -2073,17 +2063,10 @@ fn (mut g Gen) lock_expr(node ast.LockExpr) {
mut lock_prefixes := []byte{len: 0, cap: node.lockeds.len}
for id in node.lockeds {
name := id.name
// fields of `id` itself have no valid information, so look up type(flags) in scope
obj := g.file.scope.innermost(id.pos.pos).find(name) or {
verror('cgen: unable to get type for lock variable $name')
ast.ScopeObject{}
}
typ := if obj is ast.Var { (*(obj as ast.Var)).typ } else { table.Type(0) }
deref := if id.is_mut { '->' } else { '.' }
lock_prefix := if node.is_rlock { `r` } else { if typ.has_flag(.atomic_or_rw) { `w` } else { `m` } }
lock_prefix := if node.is_rlock { `r` } else { `w` }
lock_prefixes << lock_prefix // keep for unlock
mut_prefix := if lock_prefix == `m` { '' } else { 'Rw' }
g.writeln('sync__${mut_prefix}Mutex_${lock_prefix:c}_lock(${name}${deref}mtx);')
g.writeln('sync__RwMutex_${lock_prefix:c}_lock(${name}${deref}mtx);')
}
g.stmts(node.stmts)
// unlock in reverse order
@ -2092,9 +2075,7 @@ fn (mut g Gen) lock_expr(node ast.LockExpr) {
lock_prefix := lock_prefixes[i]
name := id.name
deref := if id.is_mut { '->' } else { '.' }
mut_prefix := if lock_prefix == `m` { '' } else { 'Rw' }
unlock_type := if lock_prefix == `m` { '' } else { '${lock_prefix:c}_' }
g.writeln('sync__${mut_prefix}Mutex_${unlock_type}unlock(${name}${deref}mtx);')
g.writeln('sync__RwMutex_${lock_prefix:c}_unlock(${name}${deref}mtx);')
}
}
@ -2237,7 +2218,7 @@ fn (mut g Gen) ident(node ast.Ident) {
g.write('(*($styp*)${name}.data)')
return
}
if !g.is_assign_lhs && (ident_var.share == .shared_t || ident_var.share == .rwshared_t) {
if !g.is_assign_lhs && ident_var.share == .shared_t {
g.write('${name}.val')
return
}
@ -2763,7 +2744,6 @@ const (
fn (mut g Gen) struct_init(struct_init ast.StructInit) {
styp := g.typ(struct_init.typ)
mut shared_styp := '' // only needed for shared &St{...
mut share_prefix := '' // 'rw' for `rwshared`
if styp in skip_struct_init {
g.go_back_out(3)
return
@ -2775,10 +2755,6 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
g.out.go_back(1) // delete the `&` already generated in `prefix_expr()
if g.is_shared {
mut shared_typ := struct_init.typ.set_flag(.shared_f)
if g.is_rwshared {
shared_typ = shared_typ.set_flag(.atomic_or_rw)
share_prefix = 'rw'
}
shared_styp = g.typ(shared_typ)
g.writeln('($shared_styp*)memdup(&($shared_styp){.val = ($styp){')
} else {
@ -2883,7 +2859,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
}
g.write('}')
if g.is_shared {
g.write(', .mtx = sync__new_${share_prefix}mutex()}')
g.write(', .mtx = sync__new_rwmutex()}')
if is_amp {
g.write(', sizeof($shared_styp))')
}

View File

@ -100,16 +100,16 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
pub fn (mut p Parser) call_args() []ast.CallArg {
mut args := []ast.CallArg{}
for p.tok.kind != .rpar {
is_shared := p.tok.kind in [.key_shared, .key_rwshared]
is_atomic_or_rw := p.tok.kind in [.key_rwshared, .key_atomic]
is_mut := p.tok.kind == .key_mut || is_shared || is_atomic_or_rw
is_shared := p.tok.kind == .key_shared
is_atomic := p.tok.kind == .key_atomic
is_mut := p.tok.kind == .key_mut || is_shared || is_atomic
if is_mut {
p.next()
}
e := p.expr(0)
args << ast.CallArg{
is_mut: is_mut
share: table.sharetype_from_flags(is_shared, is_atomic_or_rw)
share: table.sharetype_from_flags(is_shared, is_atomic)
expr: e
}
if p.tok.kind != .rpar {
@ -151,9 +151,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
if p.tok.kind == .lpar {
p.next() // (
is_method = true
is_shared := p.tok.kind in [.key_shared, .key_rwshared]
is_atomic_or_rw := p.tok.kind in [.key_rwshared, .key_atomic]
rec_mut = p.tok.kind == .key_mut || is_shared || is_atomic_or_rw
is_shared := p.tok.kind == .key_shared
is_atomic := p.tok.kind == .key_atomic
rec_mut = p.tok.kind == .key_mut || is_shared || is_atomic
if rec_mut {
p.next() // `mut`
}
@ -179,8 +179,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
if is_shared {
rec_type = rec_type.set_flag(.shared_f)
}
if is_atomic_or_rw {
rec_type = rec_type.set_flag(.atomic_or_rw)
if is_atomic {
rec_type = rec_type.set_flag(.atomic_f)
}
args << table.Arg{
name: rec_name
@ -400,9 +400,9 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool, bool) {
mut arg_no := 1
for p.tok.kind != .rpar {
arg_name := 'arg_$arg_no'
is_shared := p.tok.kind in [.key_shared, .key_rwshared]
is_atomic_or_rw := p.tok.kind in [.key_rwshared, .key_atomic]
is_mut := p.tok.kind == .key_mut || is_shared || is_atomic_or_rw
is_shared := p.tok.kind == .key_shared
is_atomic := p.tok.kind == .key_atomic
is_mut := p.tok.kind == .key_mut || is_shared || is_atomic
if is_mut {
p.next()
}
@ -416,13 +416,13 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool, bool) {
if !arg_type.has_flag(.generic) {
if is_shared {
p.check_fn_shared_arguments(arg_type, pos)
} else if is_atomic_or_rw {
} else if is_atomic {
p.check_fn_atomic_arguments(arg_type, pos)
} else {
p.check_fn_mutable_arguments(arg_type, pos)
}
} else if is_shared || is_atomic_or_rw {
p.error_with_pos('generic object cannot be `atomic`, `shared` or `rwshared`', pos)
} else if is_shared || is_atomic {
p.error_with_pos('generic object cannot be `atomic`or `shared`', pos)
}
// if arg_type.is_ptr() {
// p.error('cannot mut')
@ -432,8 +432,8 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool, bool) {
if is_shared {
arg_type = arg_type.set_flag(.shared_f)
}
if is_atomic_or_rw {
arg_type = arg_type.set_flag(.atomic_or_rw)
if is_atomic {
arg_type = arg_type.set_flag(.atomic_f)
}
}
if is_variadic {
@ -456,9 +456,9 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool, bool) {
}
} else {
for p.tok.kind != .rpar {
is_shared := p.tok.kind in [.key_shared, .key_rwshared]
is_atomic_or_rw := p.tok.kind in [.key_rwshared, .key_atomic]
mut is_mut := p.tok.kind == .key_mut || is_shared || is_atomic_or_rw
is_shared := p.tok.kind == .key_shared
is_atomic := p.tok.kind == .key_atomic
mut is_mut := p.tok.kind == .key_mut || is_shared || is_atomic
if is_mut {
p.next()
}
@ -485,20 +485,20 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool, bool) {
if !typ.has_flag(.generic) {
if is_shared {
p.check_fn_shared_arguments(typ, pos)
} else if is_atomic_or_rw {
} else if is_atomic {
p.check_fn_atomic_arguments(typ, pos)
} else {
p.check_fn_mutable_arguments(typ, pos)
}
} else if is_shared || is_atomic_or_rw {
p.error_with_pos('generic object cannot be `atomic`, `shared` or `rwshared`', pos)
} else if is_shared || is_atomic {
p.error_with_pos('generic object cannot be `atomic` or `shared`', pos)
}
typ = typ.set_nr_muls(1)
if is_shared {
typ = typ.set_flag(.shared_f)
}
if is_atomic_or_rw {
typ = typ.set_flag(.atomic_or_rw)
if is_atomic {
typ = typ.set_flag(.atomic_f)
}
}
if is_variadic {

View File

@ -133,11 +133,11 @@ pub fn (mut p Parser) parse_type() table.Type {
return typ
}
}
is_shared := p.tok.kind in [.key_shared, .key_rwshared]
is_atomic_or_rw := p.tok.kind in [.key_rwshared, .key_atomic]
is_shared := p.tok.kind == .key_shared
is_atomic := p.tok.kind == .key_atomic
mut nr_muls := 0
if p.tok.kind == .key_mut || is_shared || is_atomic_or_rw {
if p.tok.kind == .key_mut || is_shared || is_atomic {
nr_muls++
p.next()
}
@ -161,8 +161,8 @@ pub fn (mut p Parser) parse_type() table.Type {
if is_shared {
typ = typ.set_flag(.shared_f)
}
if is_atomic_or_rw {
typ = typ.set_flag(.atomic_or_rw)
if is_atomic {
typ = typ.set_flag(.atomic_f)
}
if nr_muls > 0 {
typ = typ.set_nr_muls(nr_muls)

View File

@ -514,7 +514,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
.key_for {
return p.for_stmt()
}
.name, .key_mut, .key_shared, .key_atomic, .key_rwshared, .key_static, .mul {
.name, .key_mut, .key_shared, .key_atomic, .key_static, .mul {
if p.tok.kind == .name {
if p.tok.lit == 'sql' {
return p.sql_stmt()
@ -783,9 +783,9 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
pub fn (mut p Parser) parse_ident(language table.Language) ast.Ident {
// p.warn('name ')
is_shared := p.tok.kind in [.key_shared, .key_rwshared]
is_atomic_or_rw := p.tok.kind in [.key_rwshared, .key_atomic]
is_mut := p.tok.kind == .key_mut || is_shared || is_atomic_or_rw
is_shared := p.tok.kind == .key_shared
is_atomic := p.tok.kind == .key_atomic
is_mut := p.tok.kind == .key_mut || is_shared || is_atomic
if is_mut {
p.next()
}
@ -823,7 +823,7 @@ pub fn (mut p Parser) parse_ident(language table.Language) ast.Ident {
info: ast.IdentVar{
is_mut: is_mut
is_static: is_static
share: table.sharetype_from_flags(is_shared, is_atomic_or_rw)
share: table.sharetype_from_flags(is_shared, is_atomic)
}
}
} else {

View File

@ -16,7 +16,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
p.eat_comments()
// Prefix
match p.tok.kind {
.key_mut, .key_shared, .key_rwshared, .key_atomic, .key_static {
.key_mut, .key_shared, .key_atomic, .key_static {
node = p.name_expr()
p.is_stmt_ident = is_stmt_ident
}

View File

@ -42,7 +42,7 @@ pub enum TypeFlag {
variadic
generic
shared_f
atomic_or_rw
atomic_f
}
/*
@ -54,7 +54,6 @@ pub enum ShareType {
mut_t
shared_t
atomic_t
rwshared_t
}
pub fn (t ShareType) str() string {
@ -62,7 +61,6 @@ pub fn (t ShareType) str() string {
.mut_t { return 'mut' }
.shared_t { return 'shared' }
.atomic_t { return 'atomic' }
.rwshared_t { return 'rwshared' }
}
}
@ -78,12 +76,12 @@ pub fn (t Type) atomic_typename() string {
}
}
pub fn sharetype_from_flags(is_shared, is_atomic_or_rw bool) ShareType {
return ShareType((int(is_atomic_or_rw) << 1) | int(is_shared))
pub fn sharetype_from_flags(is_shared, is_atomic bool) ShareType {
return ShareType((int(is_atomic) << 1) | int(is_shared))
}
pub fn (t Type) share() ShareType {
return sharetype_from_flags(t.has_flag(.shared_f), t.has_flag(.atomic_or_rw))
return sharetype_from_flags(t.has_flag(.shared_f), t.has_flag(.atomic_f))
}
pub fn (types []Type) contains(typ Type) bool {

View File

@ -6,7 +6,7 @@ mut:
a int
}
fn f(rwshared x St, shared z St) {
fn f(shared x St, shared z St) {
for _ in 0..reads_per_thread {
rlock x { // other instances may read at the same time
time.sleep_ms(1)
@ -26,14 +26,14 @@ const (
fn test_shared_lock() {
// object with separate read/write lock
rwshared x := &St{
shared x := &St{
a: 5
}
shared z := &St{
a: read_threads
}
for _ in 0..read_threads {
go f(rwshared x, shared z)
go f(shared x, shared z)
}
for i in 0..writes {
lock x { // wait for ongoing reads to finish, don't start new ones

View File

@ -6,7 +6,7 @@ mut:
a int
}
fn (rwshared x St) f(shared z St) {
fn (shared x St) f(shared z St) {
for _ in 0..reads_per_thread {
rlock x { // other instances may read at the same time
time.sleep_ms(1)
@ -26,7 +26,7 @@ const (
fn test_shared_lock() {
// object with separate read/write lock
rwshared x := &St{
shared x := &St{
a: 5
}
shared z := &St{

View File

@ -109,7 +109,6 @@ pub enum Kind {
key_module
key_mut
key_shared
key_rwshared
key_lock
key_rlock
key_none
@ -231,7 +230,6 @@ fn build_token_str() []string {
s[Kind.key_const] = 'const'
s[Kind.key_mut] = 'mut'
s[Kind.key_shared] = 'shared'
s[Kind.key_rwshared] = 'rwshared'
s[Kind.key_lock] = 'lock'
s[Kind.key_rlock] = 'rlock'
s[Kind.key_type] = 'type'