19.11.2014 Views

The Fortress Language Specification - CiteSeerX

The Fortress Language Specification - CiteSeerX

The Fortress Language Specification - CiteSeerX

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

An atomic expression consists of the special reserved word atomic followed by a body expression. Evaluating<br />

an atomic expression is simply evaluating the body expression. All reads and all writes which occur as part of this<br />

evaluation will appear to occur simultaneously in a single atomic step with respect to any action performed by any<br />

thread which is dynamically outside. This is specified in detail in Chapter 21. <strong>The</strong> value and type of an atomic<br />

expression are the value and type of its body expression.<br />

A tryatomic expression consists of the special reserved word tryatomic followed by an expression. See Section<br />

32.3 for a discussion of tryatomic expressions.<br />

A function or method with the modifier atomic acts as if its entire body were surrounded in an atomic expression.<br />

However, it is a static error if an API declares a functional f with the modifier atomic but a component implementing<br />

the API defines f whose body is an atomic expression without the modifier. Input and output (including functionals<br />

with the modifier io ) cannot be performed within an atomic expression. Thus, a functional must not have both<br />

atomic and io modifiers.<br />

When the body of an atomic expression completes abruptly, the atomic expression completes abruptly in the same<br />

way. If it completes abruptly by exiting to an enclosing label expression, writes within the block are retained<br />

and become visible to other threads. If it completes abruptly by throwing an uncaught exception, all writes to objects<br />

allocated before the atomic expression began evaluation are discarded. Writes to newly allocated objects are retained.<br />

Any variable reverts to the value it held before evaluation of the atomic expression began. Thus, the only values<br />

retained from the abruptly completed atomic expression will be reachable from the exception object through a chain<br />

of newly allocated objects.<br />

Atomic expressions may be nested arbitrarily; the above semantics imply that an inner atomic expression is atomic<br />

with respect to evaluations which occur dynamically outside the inner atomic expression but dynamically inside an<br />

enclosing atomic .<br />

Implicit threads may be created dynamically within an atomic expression. <strong>The</strong>se implicit threads will complete<br />

before the atomic expression itself does so. <strong>The</strong> implicit threads may run in parallel, and will see one another’s<br />

writes; they may synchronize with one another using nested atomic expressions.<br />

A spawned thread created in an atomic expression conceptually begins execution after the atomic expression, so<br />

long as an exception is not thrown by the atomic expression. Thus the body of the spawned thread is dynamically<br />

outside the atomic expression in which it was created. It is legal to either spawn a thread (discussed in Section 13.24)<br />

or to synchronize with it using the val or wait methods during the course of an atomic expression, but it is illegal<br />

to do both to the same thread. Doing so will cause the method call to throw the AtomicSpawnSynchronization<br />

exception.<br />

Note that atomic expressions may be evaluated in parallel with other expressions. An atomic expression experiences<br />

conflict when another thread attempts to read or write a memory location which is accessed by the atomic<br />

expression. <strong>The</strong> evaluation of such an expression must be partially serialized with the conflicting memory operation<br />

(which might be another atomic expression). <strong>The</strong> exact mechanism by which this occurs will vary; the necessary<br />

serialization is provided by the implementation. In general, the evaluation of a conflicting atomic expression may<br />

be abandoned, forcing the effects of execution to be discarded and execution to be retried. <strong>The</strong> longer an atomic<br />

expression evaluates and the more memory it touches the greater the chance of conflict and the larger the bottleneck a<br />

conflict may impose.<br />

For example, the following code uses a shared counter atomically:<br />

arraySumN extends Additive,nat x(a :N[x]) : N = do<br />

sum : N := 0<br />

for i ← a.indices do<br />

atomic sum += a i<br />

end<br />

sum<br />

end<br />

107

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!