版本:release
- 任意gs写的代码,必然在某个对象上
- 命令行输入,每行命令都会编译1个对象
- 不论被
component
多少次,一个对象中永远只有1份
- 总是先构造被
component
的代码,析构反之
- 避免相互
component
,若有,由最外层代码书写顺序决定构造析构顺序
- 只有两种类型:成员变量,局部变量。
- 没有静态变量、全局变量。
- 共享变量:
share_value
,存取的时候都会拷贝,但能并发读写
readonly
只读 parallel
并行 语义几乎相同
- 对象声明为
parallel
- 所有变量都必须是只读的,声明时候必须写上
readonly
- 所有方法都必须是并行的,无需显示声明为
parallel
- 变量声明为
readonly
- 并非不能写,只是不能改变局部
- 只能用
:=
整体赋值,自行保证覆盖安全
- 传递时不会拷贝,传递的内容无法修改
- 区别于
const
成员变量
- 变量声明为
parallel
- 可以并发修改容器内已存在的元素
- 不可以新增/删除一有元素
- 可以用
:=
整体赋值,自行保证覆盖安全
- 传递时不会拷贝,传递的内容无法修改
- 可以看成预创建了一组
readonly
的变量放在一个不可改变大小的容器中
- 方法声明为
readonly
- 只能访问只读变量
- 被调用时候不切换域
- 因而可以并行执行
- 初学可以理解为线程,但更为轻量
- GS任意代码要执行,必然在某个协程中
- 非抢占式,阻塞时挂起
- 多对多模型
- 就是区域范围的意思,亦可视作一把大锁,用于在并发场景下,保护所辖范围内的数据
- 等价于其他语言中,用mutex管理一堆变量,只是做成了语言机制,方便编码,这是GS的特色
- GS的任意变量(对象句柄也是变量)都必然隶属于某个域,局部变量亦不能例外
- GS的任意变量,不能在其所属域外使用,跨域必然产生拷贝。只读变量例外,因为不能修改,拷贝和引用无差别。
- 管道传输,函数变量参数,导致的数据传递,必须明确是否转移到了其他域
function.append_dup_arg
, append_dup_arg_arr
queue.send_dup
- 协程可以锁定域
- 协程要执行代码,必然在某个域中
- 当协程执行非并行方法时(跨域调用),会进入(自动锁定)该方法所在的域,并离开(自动释放)协程此前所在的域
- 执行并行方法,不会产生跨域操作,但可以显式指定在哪个域内执行(仍旧不会产生跨域行为)
- 协程将域锁定后,辖区内所有变量方法都只允许当前协程访问(并行方法例外)
- 协程被阻塞时,会离开当前域,恢复时重新锁定
- 跨域调用
- 需使用
=>
,或者function.call_in_domain
方法指定域
- 所有参数会拷贝,返回值会拷贝,见上
- 即使实际没有切域,拷贝仍然会发生
- 除了拷贝开销,还有锁冲突开销
- 显式锁定对象句柄,实际锁定了其所在的域
- 实际声明了1个
function
变量,指向所定义的匿名函数
- 可以捕获上下文变量,作为该匿名函数的隐含参数
- 值变量捕获为拷贝,引用变量捕获为引用
- 成员变量不捕获,因为该匿名函数就是所在对象上的成员方法
defer
- 实际声明了1个闭包,但默认捕获为引用
- 该闭包在离开作用域时调用,注意是闭包变量的作用域
- 即使下文发生报错也会调用,这是主要利用的点
- 防止该匿名函数再报错
- 如有多个,调用顺序为声明顺序,不应依赖于此
#include 和 import
- 所有符号都必须
import
后才对当前代码可见
- 有时会使用
include
简化import
的工作
include
与C语言同样采用传统的宏处理机
include
特性尽量少用,以后可能会废弃
- 可以使用
#pragma export_imports
来导出这个文件下所有import
的符号代替include
- 参考M71的preimport.gs
#define
- 支持通过
#define
声明宏定义
- 可以使用
#pragma export_macros
来导出这个文件下所有#define
的符号
热更新
monkey.patch
可以理解为重新编译并把函数指针替换
- update可以理解为销毁对象 -> 重新编译 -> 创建对象