2.32. Context
Daslang 环境被组织到上下文中。编译 Daslang 程序会生成 ‘Program’ 对象,然后可以将其模拟到 ‘Context’ 中。
- Context 包括
名称和标志
函数代码
全局变量数据
共享全局变量数据
堆栈
动态内存堆
动态字符串堆
常量字符串堆
运行时调试信息
锁
其他查找基础设施
从某种意义上说, `Context`可以被视为 Daslang 虚拟机。它是负责执行代码并保持状态的对象。 它也可以被视为类的实例,当标记为 [export] 时可以访问这些方法。
函数代码、常量字符串堆、运行时调试信息和共享的全局变量在克隆的上下文之间共享。 这允许为 context 实例保留相对较小的配置文件。
可以选择在不同类型的多个上下文之间共享堆栈,以保持内存配置文件更小。
2.32.1. 初始化和关闭
在其生命周期中, Context 会经历初始化和关闭。 上下文初始化在 Context::runInitScript 中实现,关闭在 Context::runShutdownScript 中实现。 这些函数在创建、克隆和销毁 Context 时自动调用。 根据用户应用程序和 CodeOfPolicies,它们也可能在调用 Context::restart 或 Context::restartHeaps 时被调用。
- 它按以下顺序初始化。
所有全局变量都按照每个模块的声明顺序进行初始化。
所有标记为 [init] 的函数都按照每个模块声明的顺序调用,特别排序的函数除外。
所有标记为 [init] 的特别排序的函数都按照它们在拓扑排序之后出现的顺序被调用。
- init 函数的拓扑排序顺序在 init 注释中指定。
tag 属性指定函数将在指定传递期间出现
before 属性指定函数将出现在指定通道之前
after 属性指定函数将出现在指定通道之后
请考虑以下示例:
[init(before="middle")]
def a {
order |> push("a")
}
[init(tag="middle")]
def b {
order |> push("b")
}
[init(tag="middle")]
def c {
order |> push("c")
}
[init(after="middle")]
def d {
order |> push("d")
}
- 函数将按
d
b 或 c, 任意顺序
a
Context关闭时按照每个模块声明的顺序运行所有标记为 [finalize] 的函数。
2.32.2. 宏Context
对于每个包含宏的模块,将创建并初始化单独的Context。 除了常规函数之外,在初始化期间还会调用标记为 [macro] 或 [_macro] 的函数。
标记为 [macro_function] 的函数将从常规Context中排除,并且仅显示在宏Context中。
除非宏模块被标记为共享,否则编译完成后会关闭。 共享宏模块在第一次编译期间初始化,并在环境关闭期间关闭。
2.32.3. 锁
Context 包含 recursive_mutex,并且可以使用 lock_context 或 lock_this_context RAII 块进行专门锁定和解锁。 跨上下文调用 invoke_in_context 会自动锁定目标Context。
2.32.4. 查找
全局变量和函数可以在 Daslang 和 C++ 端按名称或损坏的名称哈希进行查找。
2.32.5. 内存分配和垃圾回收
字符串堆和常规堆的内存分配策略都在 CodeOfPolicies 中指定,以及选项。
要允许从上下文内部进行垃圾回收,以下选项是必需的:
options persistent_heap // 此 API 支持垃圾回收堆
options gc // 此 API 为堆栈上的变量启用垃圾回收
要从上下文内部收集垃圾:
var collect_string_heap = true
var validate_after_collect = false
heap_collect(collect_string_heap, validate_after_collect)
从 C++ 端执行相同的作:
context->collectHeap(dummy_line_info_ptr, collect_string_heap, validate_after_collect);