mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-05 03:14:08 +00:00
deprecated regionized pointers
This commit is contained in:
@@ -173,6 +173,9 @@
|
||||
- The ``{.this.}`` pragma has been deprecated. It never worked within generics and
|
||||
we found the resulting code harder to read than the more explicit ``obj.field``
|
||||
syntax.
|
||||
- "Memory regions" for pointer types have been deprecated, they were hardly used
|
||||
anywhere. Note that this has **nothing** to do with the ``--gc:regions`` switch
|
||||
of managing memory.
|
||||
|
||||
|
||||
### Tool changes
|
||||
|
||||
@@ -193,6 +193,8 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
|
||||
if region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin {
|
||||
tyError, tyObject}:
|
||||
message c.config, n[i].info, errGenerated, "region needs to be an object type"
|
||||
else:
|
||||
message(c.config, n.info, warnDeprecated, "region for pointer types")
|
||||
addSonSkipIntLit(result, region)
|
||||
addSonSkipIntLit(result, t)
|
||||
if tfPartial in result.flags:
|
||||
|
||||
@@ -1507,68 +1507,6 @@ non nilable pointers. The details of this analysis are still to be specified
|
||||
here.
|
||||
|
||||
|
||||
Memory regions
|
||||
--------------
|
||||
|
||||
The types ``ref`` and ``ptr`` can get an optional ``region`` annotation.
|
||||
A region has to be an object type.
|
||||
|
||||
Regions are very useful to separate user space and kernel memory in the
|
||||
development of OS kernels:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
Kernel = object
|
||||
Userspace = object
|
||||
|
||||
var a: Kernel ptr Stat
|
||||
var b: Userspace ptr Stat
|
||||
|
||||
# the following does not compile as the pointer types are incompatible:
|
||||
a = b
|
||||
|
||||
As the example shows ``ptr`` can also be used as a binary
|
||||
operator, ``region ptr T`` is a shortcut for ``ptr[region, T]``.
|
||||
|
||||
In order to make generic code easier to write ``ptr T`` is a subtype
|
||||
of ``ptr[R, T]`` for any ``R``.
|
||||
|
||||
Furthermore the subtype relation of the region object types is lifted to
|
||||
the pointer types: If ``A <: B`` then ``ptr[A, T] <: ptr[B, T]``. This can be
|
||||
used to model subregions of memory. As a special typing rule ``ptr[R, T]`` is
|
||||
not compatible to ``pointer`` to prevent the following from compiling:
|
||||
|
||||
.. code-block:: nim
|
||||
# from system
|
||||
proc dealloc(p: pointer)
|
||||
|
||||
# wrap some scripting language
|
||||
type
|
||||
PythonsHeap = object
|
||||
PyObjectHeader = object
|
||||
rc: int
|
||||
typ: pointer
|
||||
PyObject = ptr[PythonsHeap, PyObjectHeader]
|
||||
|
||||
proc createPyObject(): PyObject {.importc: "...".}
|
||||
proc destroyPyObject(x: PyObject) {.importc: "...".}
|
||||
|
||||
var foo = createPyObject()
|
||||
# type error here, how convenient:
|
||||
dealloc(foo)
|
||||
|
||||
|
||||
Future directions:
|
||||
|
||||
* Memory regions might become available for ``string`` and ``seq`` too.
|
||||
* Builtin regions like ``private``, ``global`` and ``local`` might be
|
||||
useful for an OpenCL target.
|
||||
* Builtin "regions" can model ``lent`` and ``unique`` pointers.
|
||||
* An assignment operator can be attached to a region so that proper write
|
||||
barriers can be generated. This would imply that the GC can be implemented
|
||||
completely in user-space.
|
||||
|
||||
|
||||
Procedural type
|
||||
---------------
|
||||
A procedural type is internally a pointer to a procedure. ``nil`` is
|
||||
|
||||
@@ -89,8 +89,6 @@ proc closeBarrier(b: ptr Barrier) {.compilerProc.} =
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
type
|
||||
foreign* = object ## a region that indicates the pointer comes from a
|
||||
## foreign thread heap.
|
||||
AwaitInfo = object
|
||||
cv: Semaphore
|
||||
idx: int
|
||||
@@ -231,10 +229,10 @@ proc awaitAndThen*[T](fv: FlowVar[T]; action: proc (x: T) {.closure.}) =
|
||||
action(fv.blob)
|
||||
finished(fv)
|
||||
|
||||
proc unsafeRead*[T](fv: FlowVar[ref T]): foreign ptr T =
|
||||
proc unsafeRead*[T](fv: FlowVar[ref T]): ptr T =
|
||||
## blocks until the value is available and then returns this value.
|
||||
await(fv)
|
||||
result = cast[foreign ptr T](fv.data)
|
||||
result = cast[ptr T](fv.data)
|
||||
|
||||
proc `^`*[T](fv: FlowVar[ref T]): ref T =
|
||||
## blocks until the value is available and then returns this value.
|
||||
|
||||
@@ -11,7 +11,7 @@ type
|
||||
Killer* = object
|
||||
lock: Lock
|
||||
bailed {.guard: lock.}: bool
|
||||
processes {.guard: lock.}: array[0..MAX_WORKERS-1, foreign ptr Process]
|
||||
processes {.guard: lock.}: array[0..MAX_WORKERS-1, ptr Process]
|
||||
|
||||
# Hold a lock for a statement.
|
||||
template hold(lock: Lock, body: untyped) =
|
||||
@@ -32,7 +32,7 @@ proc initKiller*(): Killer =
|
||||
var killer = initKiller()
|
||||
|
||||
# remember that a process has been launched, killing it if we have bailed.
|
||||
proc launched*(process: foreign ptr Process): int {.gcsafe.} =
|
||||
proc launched*(process: ptr Process): int {.gcsafe.} =
|
||||
result = killer.processes.high + 1
|
||||
killer.lock.hold:
|
||||
if killer.bailed:
|
||||
|
||||
Reference in New Issue
Block a user