2.33. 锁
Daslang 中有几种可用的锁定机制。它们旨在确保代码的运行时安全。
2.33.1. Context 锁
可以通过 C++ 端的 ‘lock’ 和 ‘unlock’ 函数来锁定和解锁 Context。 锁定后,Context`无法重新启动。如果Context未锁定,则 `tryRestartAndLock 会重新启动Context,然后无论如何都会锁定它。 锁定Context的主要原因是从外部访问堆上的数据。堆收集可以在锁定的v中安全地进行。
2.33.2. 数组和表锁
Array 或 Table 可以显式锁定和解锁。锁定后,无法修改它们。 在锁定的 Array 上调用 resize, reserve, push, emplace, erase 等会导致 panic。 通过 []作访问锁定的 ‘Table’ 元素会导致 ‘panic’。
迭代时 Arrays 被锁定。这样做是为了防止在迭代数组时修改数组。 keys 和 values`迭代器也会锁定 `Table。在执行 find* 作期间, Tables 也会被锁定。
‘Array’ 和 ‘Table’ 锁检查发生在数据结构上,这些数据结构内部包含其他 ‘Arrays’ 或 ‘Tables’。
请考虑以下示例:
var a : array < array<int> >
...
for ( b in a[0] ) {
a |> resize(100500)
}
对 ‘a’ 数组的 ‘resize’作会导致 ‘panic’,因为 ‘a[0]’ 在迭代过程中被锁定。 但是,此测试只能在运行时进行。编译器生成自定义的 ‘resize’ 代码,用于验证锁:
def private builtin`resize ( var Arr:array<array<int> aka numT> explicit; newSize:int const ) {
_builtin_verify_locks(Arr)
__builtin_array_resize(Arr,newSize,24,__context__)
}
‘_builtin_verify_locks’ 迭代提供的数据,对于每个 ‘Array’ 或 ‘Table’ 确保它不会锁定。 如果它被锁定,则发生 ‘panic’。
仅当底层类型需要锁检查时,才会生成自定义作。
- 以下是对数据结构执行锁检查的作列表::
a <- b
return <- a
resize
reserve
push
push_clone
emplace
pop
erase
clear
insert
a[b] for the Table
- 可以显式禁用锁检查
使用 ‘set_verify_array_locks’ 和 ‘set_verify_table_locks’ 函数,为 ‘Array’ 或 ‘Table’。
对于具有 [skip_field_lock_check] 结构注释的结构类型
对于带有 [skip_lock_check] 函数注释的整个函数
对于整个context,使用 ‘options skip_lock_checks’
用于整个context,使用 ‘set_verify_context_locks’ 函数