deprecated regionized pointers

This commit is contained in:
Araq 2018-08-10 01:20:14 +02:00
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 - 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`` we found the resulting code harder to read than the more explicit ``obj.field``
syntax. 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 ### 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 { if region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin {
tyError, tyObject}: tyError, tyObject}:
message c.config, n[i].info, errGenerated, "region needs to be an object type" 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, region)
addSonSkipIntLit(result, t) addSonSkipIntLit(result, t)
if tfPartial in result.flags: 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. 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 Procedural type
--------------- ---------------
A procedural type is internally a pointer to a procedure. ``nil`` is 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 type
foreign* = object ## a region that indicates the pointer comes from a
## foreign thread heap.
AwaitInfo = object AwaitInfo = object
cv: Semaphore cv: Semaphore
idx: int idx: int
@ -231,10 +229,10 @@ proc awaitAndThen*[T](fv: FlowVar[T]; action: proc (x: T) {.closure.}) =
action(fv.blob) action(fv.blob)
finished(fv) 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. ## blocks until the value is available and then returns this value.
await(fv) await(fv)
result = cast[foreign ptr T](fv.data) result = cast[ptr T](fv.data)
proc `^`*[T](fv: FlowVar[ref T]): ref T = proc `^`*[T](fv: FlowVar[ref T]): ref T =
## blocks until the value is available and then returns this value. ## blocks until the value is available and then returns this value.

View file

@ -11,7 +11,7 @@ type
Killer* = object Killer* = object
lock: Lock lock: Lock
bailed {.guard: lock.}: bool 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. # Hold a lock for a statement.
template hold(lock: Lock, body: untyped) = template hold(lock: Lock, body: untyped) =
@ -32,7 +32,7 @@ proc initKiller*(): Killer =
var killer = initKiller() var killer = initKiller()
# remember that a process has been launched, killing it if we have bailed. # 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 result = killer.processes.high + 1
killer.lock.hold: killer.lock.hold:
if killer.bailed: if killer.bailed: