2.33.

Daslang 中有几种可用的锁定机制。它们旨在确保代码的运行时安全。

2.33.1. Context 锁

可以通过 C++ 端的 ‘lock’ 和 ‘unlock’ 函数来锁定和解锁 Context。 锁定后,Context`无法重新启动。如果Context未锁定,则 `tryRestartAndLock 会重新启动Context,然后无论如何都会锁定它。 锁定Context的主要原因是从外部访问堆上的数据。堆收集可以在锁定的v中安全地进行。

2.33.2. 数组和表锁

ArrayTable 可以显式锁定和解锁。锁定后,无法修改它们。 在锁定的 Array 上调用 resize, reserve, push, emplace, erase 等会导致 panic。 通过 []作访问锁定的 ‘Table’ 元素会导致 ‘panic’。

迭代时 Arrays 被锁定。这样做是为了防止在迭代数组时修改数组。 keysvalues`迭代器也会锁定 `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’ 函数