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
|
||||
|
||||
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_ms(int n);
|
||||
|
||||
|
@ -11,7 +11,7 @@ import time
|
||||
#include "photonwrapper.h"
|
||||
|
||||
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_ms(n int)
|
||||
|
||||
@ -19,3 +19,8 @@ fn C.photon_sleep_ms(n int)
|
||||
pub fn sleep(duration time.Duration) {
|
||||
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)
|
||||
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
|
||||
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
|
||||
}
|
||||
if fsym.info !is ast.Enum {
|
||||
|
@ -3161,10 +3161,16 @@ fn (mut g Gen) expr(node_ ast.Expr) {
|
||||
}
|
||||
}
|
||||
ast.SpawnExpr {
|
||||
g.spawn_expr(node)
|
||||
g.spawn_and_go_expr(node, .spawn_)
|
||||
}
|
||||
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 {
|
||||
g.ident(node)
|
||||
|
@ -6,8 +6,19 @@ module c
|
||||
import v.ast
|
||||
import v.util
|
||||
|
||||
fn (mut g Gen) spawn_expr(node ast.SpawnExpr) {
|
||||
g.writeln('/*spawn (thread) */')
|
||||
enum SpawnGoMode {
|
||||
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)
|
||||
mut handle := ''
|
||||
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_fn_name := name + '_thread_wrapper'
|
||||
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 {
|
||||
tmp_fn
|
||||
} else if expr.is_fn_var {
|
||||
@ -76,15 +92,15 @@ fn (mut g Gen) spawn_expr(node ast.SpawnExpr) {
|
||||
name
|
||||
}
|
||||
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 {
|
||||
g.write('${arg_tmp_var}->arg0 = ')
|
||||
g.write('${arg_tmp_var}${dot}arg0 = ')
|
||||
g.expr(expr.left)
|
||||
g.writeln(';')
|
||||
}
|
||||
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.writeln(';')
|
||||
}
|
||||
@ -108,39 +124,43 @@ fn (mut g Gen) spawn_expr(node ast.SpawnExpr) {
|
||||
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}'
|
||||
}
|
||||
if g.pref.os == .windows {
|
||||
simple_handle := if node.is_expr && node.call_expr.return_type != ast.void_type {
|
||||
'thread_handle_${tmp}'
|
||||
if is_spawn {
|
||||
if g.pref.os == .windows {
|
||||
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 {
|
||||
'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 {
|
||||
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});')
|
||||
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')
|
||||
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)
|
||||
g.gowrappers.write_string('${c_name(receiver_type_name)}_name_table[')
|
||||
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)
|
||||
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('${dot}_object')
|
||||
g.gowrappers.write_string('${idot}_object')
|
||||
} else {
|
||||
g.gowrappers.write_string('arg->fn(')
|
||||
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) {
|
||||
g.writeln('/*go (coroutine) */')
|
||||
}
|
||||
// fn (mut g Gen) go_expr(node ast.GoExpr) {
|
||||
//}
|
||||
|
||||
// get current thread size, if fn hasn't defined return default
|
||||
[inline]
|
||||
|
@ -8,6 +8,7 @@ import os.cmdline
|
||||
import os
|
||||
import v.vcache
|
||||
import rand
|
||||
// import net.http // TODO can't use net.http on arm maccs: bignum.c arm asm error
|
||||
|
||||
pub enum BuildMode {
|
||||
// `v program.v'
|
||||
@ -801,6 +802,20 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
||||
}
|
||||
'-use-coroutines' {
|
||||
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 {
|
||||
if command == 'build' && is_source_file(arg) {
|
||||
|
Loading…
Reference in New Issue
Block a user