mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
Enabled explicitly unknown lock levels (#5409)
* enabled explicitly unknown lock levels * allowing "unknown" as locks pragma * added test case for locks pragma * updated docs on locks pragma
This commit is contained in:
committed by
Andreas Rumpf
parent
363b1c0a41
commit
ce4587d7b7
@@ -582,7 +582,13 @@ proc pragmaLocks(c: PContext, it: PNode): TLockLevel =
|
||||
if it.kind != nkExprColonExpr:
|
||||
invalidPragma(it)
|
||||
else:
|
||||
if it[1].kind != nkNilLit:
|
||||
case it[1].kind
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||
if it[1].strVal == "unknown":
|
||||
result = UnknownLockLevel
|
||||
else:
|
||||
localError(it[1].info, "invalid string literal for locks pragma (only allowed string is \"unknown\")")
|
||||
else:
|
||||
let x = expectIntLit(c, it)
|
||||
if x < 0 or x > MaxLockLevel:
|
||||
localError(it[1].info, "integer must be within 0.." & $MaxLockLevel)
|
||||
|
||||
@@ -198,3 +198,22 @@ This is essential so that procs can be called within a ``locks`` section:
|
||||
As usual ``locks`` is an inferred effect and there is a subtype
|
||||
relation: ``proc () {.locks: N.}`` is a subtype of ``proc () {.locks: M.}``
|
||||
iff (M <= N).
|
||||
|
||||
The ``locks`` pragma can also take the special value ``"unknown"``. This
|
||||
is useful in the context of dynamic method dispatching. In the following
|
||||
example, the compiler can infer a lock level of 0 for the ``base`` case.
|
||||
However, one of the overloaded methods calls a procvar which is
|
||||
potentially locking. Thus, the lock level of calling ``g.testMethod``
|
||||
cannot be inferred statically, leading to compiler warnings. By using
|
||||
``{.locks: "unknown".}``, the base method can be marked explicitly as
|
||||
having unknown lock level as well:
|
||||
|
||||
.. code-block:: nim
|
||||
type SomeBase* = ref object of RootObj
|
||||
type SomeDerived* = ref object of SomeBase
|
||||
memberProc*: proc ()
|
||||
|
||||
method testMethod(g: SomeBase) {.base, locks: "unknown".} = discard
|
||||
method testMethod(g: SomeDerived) =
|
||||
if g.memberProc != nil:
|
||||
g.memberProc()
|
||||
|
||||
13
tests/pragmas/tlocks.nim
Normal file
13
tests/pragmas/tlocks.nim
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
type SomeBase* = ref object of RootObj
|
||||
type SomeDerived* = ref object of SomeBase
|
||||
memberProc*: proc ()
|
||||
|
||||
method testMethod(g: SomeBase) {.base, locks: "unknown".} = discard
|
||||
method testMethod(g: SomeDerived) =
|
||||
if g.memberProc != nil:
|
||||
g.memberProc()
|
||||
|
||||
# ensure int literals still work
|
||||
proc plain*() {.locks: 0.} =
|
||||
discard
|
||||
Reference in New Issue
Block a user