mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: coroutines (part 2)
This commit is contained in:
parent
2162230086
commit
9db10c8f61
2
thirdparty/photon/photonwrapper.h
vendored
2
thirdparty/photon/photonwrapper.h
vendored
@ -21,7 +21,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int photon_init_default();
|
int photon_init_default();
|
||||||
void photon_thread_create11(void* (* f)(void*));
|
void photon_thread_create(void* (* f)(void*), void* arg);
|
||||||
void photon_sleep_s(int n);
|
void photon_sleep_s(int n);
|
||||||
void photon_sleep_ms(int n);
|
void photon_sleep_ms(int n);
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import time
|
|||||||
#include "photonwrapper.h"
|
#include "photonwrapper.h"
|
||||||
|
|
||||||
fn C.photon_init_default() int
|
fn C.photon_init_default() int
|
||||||
fn C.photon_thread_create11(f voidptr)
|
fn C.photon_thread_create(f voidptr)
|
||||||
fn C.photon_sleep_s(n int)
|
fn C.photon_sleep_s(n int)
|
||||||
fn C.photon_sleep_ms(n int)
|
fn C.photon_sleep_ms(n int)
|
||||||
|
|
||||||
@ -19,3 +19,8 @@ fn C.photon_sleep_ms(n int)
|
|||||||
pub fn sleep(duration time.Duration) {
|
pub fn sleep(duration time.Duration) {
|
||||||
C.photon_sleep_ms(duration.milliseconds())
|
C.photon_sleep_ms(duration.milliseconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init needs to be run
|
||||||
|
pub fn initialize() int {
|
||||||
|
return C.photon_init_default()
|
||||||
|
}
|
||||||
|
@ -4199,7 +4199,13 @@ fn (mut c Checker) enum_val(mut node ast.EnumVal) ast.Type {
|
|||||||
fsym := c.table.final_sym(typ)
|
fsym := c.table.final_sym(typ)
|
||||||
if fsym.kind != .enum_ && !c.pref.translated && !c.file.is_translated {
|
if fsym.kind != .enum_ && !c.pref.translated && !c.file.is_translated {
|
||||||
// TODO in C int fields can be compared to enums, need to handle that in C2V
|
// TODO in C int fields can be compared to enums, need to handle that in C2V
|
||||||
c.error('expected type is not an enum (`${typ_sym.name}`)', node.pos)
|
if typ_sym.kind == .placeholder {
|
||||||
|
// If it's a placeholder, the type doesn't exist, print
|
||||||
|
// an error that makes sense here.
|
||||||
|
c.error('unknown type `${typ_sym.name}`', node.pos)
|
||||||
|
} else {
|
||||||
|
c.error('expected type is not an enum (`${typ_sym.name}`)', node.pos)
|
||||||
|
}
|
||||||
return ast.void_type
|
return ast.void_type
|
||||||
}
|
}
|
||||||
if fsym.info !is ast.Enum {
|
if fsym.info !is ast.Enum {
|
||||||
|
@ -3161,10 +3161,16 @@ fn (mut g Gen) expr(node_ ast.Expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.SpawnExpr {
|
ast.SpawnExpr {
|
||||||
g.spawn_expr(node)
|
g.spawn_and_go_expr(node, .spawn_)
|
||||||
}
|
}
|
||||||
ast.GoExpr {
|
ast.GoExpr {
|
||||||
g.go_expr(node)
|
// XTODO this results in a cgen bug, order of fields is broken
|
||||||
|
// g.spawn_and_go_expr(ast.SpawnExpr{node.pos, node.call_expr, node.is_expr},
|
||||||
|
g.spawn_and_go_expr(ast.SpawnExpr{
|
||||||
|
pos: node.pos
|
||||||
|
call_expr: node.call_expr
|
||||||
|
is_expr: node.is_expr
|
||||||
|
}, .go_)
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
g.ident(node)
|
g.ident(node)
|
||||||
|
@ -6,8 +6,19 @@ module c
|
|||||||
import v.ast
|
import v.ast
|
||||||
import v.util
|
import v.util
|
||||||
|
|
||||||
fn (mut g Gen) spawn_expr(node ast.SpawnExpr) {
|
enum SpawnGoMode {
|
||||||
g.writeln('/*spawn (thread) */')
|
spawn_
|
||||||
|
go_
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
|
||||||
|
is_spawn := mode == .spawn_
|
||||||
|
is_go := mode == .go_
|
||||||
|
if is_spawn {
|
||||||
|
g.writeln('/*spawn (thread) */')
|
||||||
|
} else {
|
||||||
|
g.writeln('/*go (coroutine) */')
|
||||||
|
}
|
||||||
line := g.go_before_stmt(0)
|
line := g.go_before_stmt(0)
|
||||||
mut handle := ''
|
mut handle := ''
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
@ -67,7 +78,12 @@ fn (mut g Gen) spawn_expr(node ast.SpawnExpr) {
|
|||||||
wrapper_struct_name := 'thread_arg_' + name
|
wrapper_struct_name := 'thread_arg_' + name
|
||||||
wrapper_fn_name := name + '_thread_wrapper'
|
wrapper_fn_name := name + '_thread_wrapper'
|
||||||
arg_tmp_var := 'arg_' + tmp
|
arg_tmp_var := 'arg_' + tmp
|
||||||
g.writeln('${wrapper_struct_name} *${arg_tmp_var} = malloc(sizeof(thread_arg_${name}));')
|
if is_spawn {
|
||||||
|
g.writeln('${wrapper_struct_name} *${arg_tmp_var} = malloc(sizeof(thread_arg_${name}));')
|
||||||
|
} else if is_go {
|
||||||
|
g.writeln('${wrapper_struct_name} ${arg_tmp_var};')
|
||||||
|
}
|
||||||
|
dot := if is_spawn { '->' } else { '.' }
|
||||||
fn_name := if use_tmp_fn_var {
|
fn_name := if use_tmp_fn_var {
|
||||||
tmp_fn
|
tmp_fn
|
||||||
} else if expr.is_fn_var {
|
} else if expr.is_fn_var {
|
||||||
@ -76,15 +92,15 @@ fn (mut g Gen) spawn_expr(node ast.SpawnExpr) {
|
|||||||
name
|
name
|
||||||
}
|
}
|
||||||
if !(expr.is_method && g.table.sym(expr.receiver_type).kind == .interface_) {
|
if !(expr.is_method && g.table.sym(expr.receiver_type).kind == .interface_) {
|
||||||
g.writeln('${arg_tmp_var}->fn = ${fn_name};')
|
g.writeln('${arg_tmp_var}${dot}fn = ${fn_name};')
|
||||||
}
|
}
|
||||||
if expr.is_method {
|
if expr.is_method {
|
||||||
g.write('${arg_tmp_var}->arg0 = ')
|
g.write('${arg_tmp_var}${dot}arg0 = ')
|
||||||
g.expr(expr.left)
|
g.expr(expr.left)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
for i, arg in expr.args {
|
for i, arg in expr.args {
|
||||||
g.write('${arg_tmp_var}->arg${i + 1} = ')
|
g.write('${arg_tmp_var}${dot}arg${i + 1} = ')
|
||||||
g.expr(arg.expr)
|
g.expr(arg.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
@ -108,39 +124,43 @@ fn (mut g Gen) spawn_expr(node ast.SpawnExpr) {
|
|||||||
res := if is_res { '${result_name}_' } else { '' }
|
res := if is_res { '${result_name}_' } else { '' }
|
||||||
gohandle_name = '__v_thread_${opt}${res}${g.table.sym(g.unwrap_generic(node.call_expr.return_type)).cname}'
|
gohandle_name = '__v_thread_${opt}${res}${g.table.sym(g.unwrap_generic(node.call_expr.return_type)).cname}'
|
||||||
}
|
}
|
||||||
if g.pref.os == .windows {
|
if is_spawn {
|
||||||
simple_handle := if node.is_expr && node.call_expr.return_type != ast.void_type {
|
if g.pref.os == .windows {
|
||||||
'thread_handle_${tmp}'
|
simple_handle := if node.is_expr && node.call_expr.return_type != ast.void_type {
|
||||||
|
'thread_handle_${tmp}'
|
||||||
|
} else {
|
||||||
|
'thread_${tmp}'
|
||||||
|
}
|
||||||
|
stack_size := g.get_cur_thread_stack_size(expr.name)
|
||||||
|
g.writeln('HANDLE ${simple_handle} = CreateThread(0, ${stack_size}, (LPTHREAD_START_ROUTINE)${wrapper_fn_name}, ${arg_tmp_var}, 0, 0); // fn: ${expr.name}')
|
||||||
|
g.writeln('if (!${simple_handle}) panic_lasterr(tos3("`go ${name}()`: "));')
|
||||||
|
if node.is_expr && node.call_expr.return_type != ast.void_type {
|
||||||
|
g.writeln('${gohandle_name} thread_${tmp} = {')
|
||||||
|
g.writeln('\t.ret_ptr = ${arg_tmp_var}->ret_ptr,')
|
||||||
|
g.writeln('\t.handle = thread_handle_${tmp}')
|
||||||
|
g.writeln('};')
|
||||||
|
}
|
||||||
|
if !node.is_expr {
|
||||||
|
g.writeln('CloseHandle(thread_${tmp});')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
'thread_${tmp}'
|
g.writeln('pthread_t thread_${tmp};')
|
||||||
}
|
mut sthread_attributes := 'NULL'
|
||||||
stack_size := g.get_cur_thread_stack_size(expr.name)
|
if g.pref.os != .vinix {
|
||||||
g.writeln('HANDLE ${simple_handle} = CreateThread(0, ${stack_size}, (LPTHREAD_START_ROUTINE)${wrapper_fn_name}, ${arg_tmp_var}, 0, 0); // fn: ${expr.name}')
|
g.writeln('pthread_attr_t thread_${tmp}_attributes;')
|
||||||
g.writeln('if (!${simple_handle}) panic_lasterr(tos3("`go ${name}()`: "));')
|
g.writeln('pthread_attr_init(&thread_${tmp}_attributes);')
|
||||||
if node.is_expr && node.call_expr.return_type != ast.void_type {
|
size := g.get_cur_thread_stack_size(expr.name)
|
||||||
g.writeln('${gohandle_name} thread_${tmp} = {')
|
g.writeln('pthread_attr_setstacksize(&thread_${tmp}_attributes, ${size}); // fn: ${expr.name}')
|
||||||
g.writeln('\t.ret_ptr = ${arg_tmp_var}->ret_ptr,')
|
sthread_attributes = '&thread_${tmp}_attributes'
|
||||||
g.writeln('\t.handle = thread_handle_${tmp}')
|
}
|
||||||
g.writeln('};')
|
g.writeln('int ${tmp}_thr_res = pthread_create(&thread_${tmp}, ${sthread_attributes}, (void*)${wrapper_fn_name}, ${arg_tmp_var});')
|
||||||
}
|
g.writeln('if (${tmp}_thr_res) panic_error_number(tos3("`go ${name}()`: "), ${tmp}_thr_res);')
|
||||||
if !node.is_expr {
|
if !node.is_expr {
|
||||||
g.writeln('CloseHandle(thread_${tmp});')
|
g.writeln('pthread_detach(thread_${tmp});')
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
g.writeln('pthread_t thread_${tmp};')
|
|
||||||
mut sthread_attributes := 'NULL'
|
|
||||||
if g.pref.os != .vinix {
|
|
||||||
g.writeln('pthread_attr_t thread_${tmp}_attributes;')
|
|
||||||
g.writeln('pthread_attr_init(&thread_${tmp}_attributes);')
|
|
||||||
size := g.get_cur_thread_stack_size(expr.name)
|
|
||||||
g.writeln('pthread_attr_setstacksize(&thread_${tmp}_attributes, ${size}); // fn: ${expr.name}')
|
|
||||||
sthread_attributes = '&thread_${tmp}_attributes'
|
|
||||||
}
|
|
||||||
g.writeln('int ${tmp}_thr_res = pthread_create(&thread_${tmp}, ${sthread_attributes}, (void*)${wrapper_fn_name}, ${arg_tmp_var});')
|
|
||||||
g.writeln('if (${tmp}_thr_res) panic_error_number(tos3("`go ${name}()`: "), ${tmp}_thr_res);')
|
|
||||||
if !node.is_expr {
|
|
||||||
g.writeln('pthread_detach(thread_${tmp});')
|
|
||||||
}
|
}
|
||||||
|
} else if is_go {
|
||||||
|
g.writeln('photon_thread_create((void*)${wrapper_fn_name}, &${arg_tmp_var});')
|
||||||
}
|
}
|
||||||
g.writeln('// end go')
|
g.writeln('// end go')
|
||||||
if node.is_expr {
|
if node.is_expr {
|
||||||
@ -273,11 +293,11 @@ fn (mut g Gen) spawn_expr(node ast.SpawnExpr) {
|
|||||||
receiver_type_name := util.no_dots(rec_cc_type)
|
receiver_type_name := util.no_dots(rec_cc_type)
|
||||||
g.gowrappers.write_string('${c_name(receiver_type_name)}_name_table[')
|
g.gowrappers.write_string('${c_name(receiver_type_name)}_name_table[')
|
||||||
g.gowrappers.write_string('arg->arg0')
|
g.gowrappers.write_string('arg->arg0')
|
||||||
dot := if expr.left_type.is_ptr() { '->' } else { '.' }
|
idot := if expr.left_type.is_ptr() { '->' } else { '.' }
|
||||||
mname := c_name(expr.name)
|
mname := c_name(expr.name)
|
||||||
g.gowrappers.write_string('${dot}_typ]._method_${mname}(')
|
g.gowrappers.write_string('${idot}_typ]._method_${mname}(')
|
||||||
g.gowrappers.write_string('arg->arg0')
|
g.gowrappers.write_string('arg->arg0')
|
||||||
g.gowrappers.write_string('${dot}_object')
|
g.gowrappers.write_string('${idot}_object')
|
||||||
} else {
|
} else {
|
||||||
g.gowrappers.write_string('arg->fn(')
|
g.gowrappers.write_string('arg->fn(')
|
||||||
g.gowrappers.write_string('arg->arg0')
|
g.gowrappers.write_string('arg->arg0')
|
||||||
@ -354,9 +374,8 @@ fn (mut g Gen) spawn_expr(node ast.SpawnExpr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) go_expr(node ast.GoExpr) {
|
// fn (mut g Gen) go_expr(node ast.GoExpr) {
|
||||||
g.writeln('/*go (coroutine) */')
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
// get current thread size, if fn hasn't defined return default
|
// get current thread size, if fn hasn't defined return default
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -8,6 +8,7 @@ import os.cmdline
|
|||||||
import os
|
import os
|
||||||
import v.vcache
|
import v.vcache
|
||||||
import rand
|
import rand
|
||||||
|
// import net.http // TODO can't use net.http on arm maccs: bignum.c arm asm error
|
||||||
|
|
||||||
pub enum BuildMode {
|
pub enum BuildMode {
|
||||||
// `v program.v'
|
// `v program.v'
|
||||||
@ -801,6 +802,20 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
|||||||
}
|
}
|
||||||
'-use-coroutines' {
|
'-use-coroutines' {
|
||||||
res.use_coroutines = true
|
res.use_coroutines = true
|
||||||
|
$if macos && arm64 {
|
||||||
|
vexe := vexe_path()
|
||||||
|
vroot := os.dir(vexe)
|
||||||
|
so_path := os.join_path(vroot, 'thirdparty', 'photon', 'photonwrapper.so')
|
||||||
|
so_url := 'https://github.com/vlang/photonbin/raw/master/photonwrapper_macos_arm64.so'
|
||||||
|
if !os.exists(so_path) {
|
||||||
|
println('coroutines .so not found, downloading...')
|
||||||
|
// http.download_file(so_url, so_path) or { panic(err) }
|
||||||
|
os.system('wget -O "${so_path}" "${so_url}"')
|
||||||
|
println('done!')
|
||||||
|
}
|
||||||
|
} $else {
|
||||||
|
println('coroutines only work on arm64 macos for now')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if command == 'build' && is_source_file(arg) {
|
if command == 'build' && is_source_file(arg) {
|
||||||
|
Loading…
Reference in New Issue
Block a user