deprecated regionized pointers

This commit is contained in:
Araq
2018-08-10 01:20:14 +02:00
parent b4e5c9d075
commit 265003df1a
5 changed files with 9 additions and 68 deletions

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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.

View File

@@ -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: