deprecated regionized pointers
This commit is contained in:
parent
b4e5c9d075
commit
265003df1a
5 changed files with 9 additions and 68 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue