doc updates; fixes 'inc' for 'char'

This commit is contained in:
Araq 2015-03-29 13:16:22 +02:00
commit edc4940c26
8 changed files with 97 additions and 191 deletions

View file

@ -14,7 +14,7 @@ deprecated pragma
The deprecated pragma is used to mark a symbol as deprecated:
.. code-block:: nimrod
.. code-block:: nim
proc p() {.deprecated.}
var x {.deprecated.}: char
@ -22,7 +22,7 @@ It can also be used as a statement. Then it takes a list of *renamings*. The
upcoming ``nimfix`` tool can automatically update the code and perform these
renamings:
.. code-block:: nimrod
.. code-block:: nim
type
File = object
Stream = ref object
@ -78,7 +78,7 @@ as helpers for macros.
noReturn pragma
---------------
The ``noreturn`` pragma is used to mark a proc that never returns.
The ``noreturn`` pragma is used to mark a proc that never returns.
acyclic pragma
@ -122,25 +122,25 @@ shallow pragma
--------------
The ``shallow`` pragma affects the semantics of a type: The compiler is
allowed to make a shallow copy. This can cause serious semantic issues and
break memory safety! However, it can speed up assignments considerably,
because the semantics of Nim require deep copying of sequences and strings.
break memory safety! However, it can speed up assignments considerably,
because the semantics of Nim require deep copying of sequences and strings.
This can be expensive, especially if sequences are used to build a tree
structure:
structure:
.. code-block:: nim
type
NodeKind = enum nkLeaf, nkInner
Node {.final, shallow.} = object
case kind: NodeKind
of nkLeaf:
of nkLeaf:
strVal: string
of nkInner:
of nkInner:
children: seq[Node]
pure pragma
-----------
An object type can be marked with the ``pure`` pragma so that its type
An object type can be marked with the ``pure`` pragma so that its type
field which is used for runtime type identification is omitted. This used to be
necessary for binary compatibility with other compiled languages.
@ -163,12 +163,12 @@ error pragma
------------
The ``error`` pragma is used to make the compiler output an error message
with the given content. Compilation does not necessarily abort after an error
though.
though.
The ``error`` pragma can also be used to
annotate a symbol (like an iterator or proc). The *usage* of the symbol then
triggers a compile-time error. This is especially useful to rule out that some
operation is valid due to overloading and type conversions:
operation is valid due to overloading and type conversions:
.. code-block:: nim
## check that underlying int values are compared and not the pointers:
@ -201,7 +201,7 @@ The ``line`` pragma can be used to affect line information of the annotated
statement as seen in stack backtraces:
.. code-block:: nim
template myassert*(cond: expr, msg = "") =
if not cond:
# change run-time line information of the 'raise' statement:
@ -215,26 +215,26 @@ If the ``line`` pragma is used with a parameter, the parameter needs be a
linearScanEnd pragma
--------------------
The ``linearScanEnd`` pragma can be used to tell the compiler how to
The ``linearScanEnd`` pragma can be used to tell the compiler how to
compile a Nim `case`:idx: statement. Syntactically it has to be used as a
statement:
.. code-block:: nim
case myInt
of 0:
of 0:
echo "most common case"
of 1:
of 1:
{.linearScanEnd.}
echo "second most common case"
of 2: echo "unlikely: use branch table"
else: echo "unlikely too: use branch table for ", myInt
In the example, the case branches ``0`` and ``1`` are much more common than
the other cases. Therefore the generated assembler code should test for these
values first, so that the CPU's branch predictor has a good chance to succeed
In the example, the case branches ``0`` and ``1`` are much more common than
the other cases. Therefore the generated assembler code should test for these
values first, so that the CPU's branch predictor has a good chance to succeed
(avoiding an expensive CPU pipeline stall). The other cases might be put into a
jump table for O(1) overhead, but at the cost of a (very likely) pipeline
stall.
stall.
The ``linearScanEnd`` pragma should be put into the last branch that should be
tested against via linear scanning. If put into the last branch of the
@ -243,8 +243,8 @@ whole ``case`` statement, the whole ``case`` statement uses linear scanning.
computedGoto pragma
-------------------
The ``computedGoto`` pragma can be used to tell the compiler how to
compile a Nim `case`:idx: in a ``while true`` statement.
The ``computedGoto`` pragma can be used to tell the compiler how to
compile a Nim `case`:idx: in a ``while true`` statement.
Syntactically it has to be used as a statement inside the loop:
.. code-block:: nim
@ -278,21 +278,21 @@ Syntactically it has to be used as a statement inside the loop:
of enumE:
break
inc(pc)
vm()
As the example shows ``computedGoto`` is mostly useful for interpreters. If
the underlying backend (C compiler) does not support the computed goto
the underlying backend (C compiler) does not support the computed goto
extension the pragma is simply ignored.
unroll pragma
-------------
The ``unroll`` pragma can be used to tell the compiler that it should unroll
a `for`:idx: or `while`:idx: loop for runtime efficiency:
a `for`:idx: or `while`:idx: loop for runtime efficiency:
.. code-block:: nim
proc searchChar(s: string, c: char): int =
proc searchChar(s: string, c: char): int =
for i in 0 .. s.high:
{.unroll: 4.}
if s[i] == c: return i
@ -440,7 +440,7 @@ Example:
Please note that if a callable symbol is never used in this scenario, its body
will never be compiled. This is the default behavior leading to best compilation
times, but if exhaustive compilation of all definitions is required, using
times, but if exhaustive compilation of all definitions is required, using
``nim check`` provides this option as well.
Example:
@ -461,9 +461,9 @@ Example:
pragma pragma
-------------
The ``pragma`` pragma can be used to declare user defined pragmas. This is
useful because Nim's templates and macros do not affect pragmas. User
defined pragmas are in a different module-wide scope than all other symbols.
The ``pragma`` pragma can be used to declare user defined pragmas. This is
useful because Nim's templates and macros do not affect pragmas. User
defined pragmas are in a different module-wide scope than all other symbols.
They cannot be imported from a module.
Example:
@ -473,8 +473,8 @@ Example:
{.pragma: rtl, exportc, dynlib, cdecl.}
else:
{.pragma: rtl, importc, dynlib: "client.dll", cdecl.}
proc p*(a, b: int): int {.rtl.} =
proc p*(a, b: int): int {.rtl.} =
result = a+b
In the example a new pragma named ``rtl`` is introduced that either imports

View file

@ -1,16 +1,16 @@
Threads
=======
To enable thread support the ``--threads:on`` command line switch needs to
be used. The ``system`` module then contains several threading primitives.
See the `threads <threads.html>`_ and `channels <channels.html>`_ modules
To enable thread support the ``--threads:on`` command line switch needs to
be used. The ``system`` module then contains several threading primitives.
See the `threads <threads.html>`_ and `channels <channels.html>`_ modules
for the low level thread API. There are also high level parallelism constructs
available. See `spawn`_ for further details.
Nim's memory model for threads is quite different than that of other common
programming languages (C, Pascal, Java): Each thread has its own (garbage
collected) heap and sharing of memory is restricted to global variables. This
helps to prevent race conditions. GC efficiency is improved quite a lot,
programming languages (C, Pascal, Java): Each thread has its own (garbage
collected) heap and sharing of memory is restricted to global variables. This
helps to prevent race conditions. GC efficiency is improved quite a lot,
because the GC never has to stop other threads and see what they reference.
Memory allocation requires no lock at all! This design easily scales to massive
multicore processors that are becoming the norm.
@ -22,10 +22,10 @@ Thread pragma
A proc that is executed as a new thread of execution should be marked by the
``thread`` pragma for reasons of readability. The compiler checks for
violations of the `no heap sharing restriction`:idx:\: This restriction implies
that it is invalid to construct a data structure that consists of memory
that it is invalid to construct a data structure that consists of memory
allocated from different (thread local) heaps.
A thread proc is passed to ``createThread`` or ``spawn`` and invoked
A thread proc is passed to ``createThread`` or ``spawn`` and invoked
indirectly; so the ``thread`` pragma implies ``procvar``.
@ -34,7 +34,7 @@ GC safety
We call a proc ``p`` `GC safe`:idx: when it doesn't access any global variable
that contains GC'ed memory (``string``, ``seq``, ``ref`` or a closure) either
directly or indirectly through a call to a GC unsafe proc.
directly or indirectly through a call to a GC unsafe proc.
The `gcsafe`:idx: annotation can be used to mark a proc to be gcsafe,
otherwise this property is inferred by the compiler. Note that ``noSideEfect``
@ -45,10 +45,9 @@ contain a ``ref`` or ``closure`` type. This enforces
the *no heap sharing restriction*.
Routines that are imported from C are always assumed to be ``gcsafe``.
To enable the GC-safety checking the ``--threadAnalysis:on`` command line
switch must be used. This is a temporary workaround to ease the porting effort
from old code to the new threading model. In the future the thread analysis
will always be performed.
To disable the GC-safety checking the ``--threadAnalysis:off`` command line
switch can be used. This is a temporary workaround to ease the porting effort
from old code to the new threading model.
Future directions:
@ -59,13 +58,13 @@ Future directions:
Threadvar pragma
----------------
A global variable can be marked with the ``threadvar`` pragma; it is
A global variable can be marked with the ``threadvar`` pragma; it is
a `thread-local`:idx: variable then:
.. code-block:: nim
var checkpoints* {.threadvar.}: seq[string]
Due to implementation restrictions thread local variables cannot be
Due to implementation restrictions thread local variables cannot be
initialized within the ``var`` section. (Every thread local variable needs to
be replicated at thread creation.)
@ -73,7 +72,7 @@ be replicated at thread creation.)
Threads and exceptions
----------------------
The interaction between threads and exceptions is simple: A *handled* exception
The interaction between threads and exceptions is simple: A *handled* exception
in one thread cannot affect any other thread. However, an *unhandled* exception
in one thread terminates the whole *process*!
@ -82,7 +81,7 @@ in one thread terminates the whole *process*!
Parallel & Spawn
================
Nim has two flavors of parallelism:
Nim has two flavors of parallelism:
1) `Structured`:idx: parallelism via the ``parallel`` statement.
2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement.
@ -115,7 +114,7 @@ Spawn statement
proc processLine(line: string) =
discard "do some heavy lifting here"
for x in lines("myinput.txt"):
spawn processLine(x)
sync()
@ -144,7 +143,7 @@ wait on multiple flow variables at the same time:
.. code-block:: nim
import threadpool, ...
# wait until 2 out of 3 servers received the update:
proc main =
var responses = newSeq[RawFlowVar](3)
@ -203,8 +202,7 @@ restrictions / changes:
the ``parallel`` section. This is called the *immutability check*. Currently
it is not specified what exactly "complex location" means. We need to make
this an optimization!
* Every array access has to be provably within bounds. This is called
* Every array access has to be provably within bounds. This is called
the *bounds check*.
* Slices are optimized so that no copy is performed. This optimization is not
yet performed for ordinary slices outside of a ``parallel`` section. Slices
are also special in that they currently do not support negative indexes!
yet performed for ordinary slices outside of a ``parallel`` section.