This is something I've been looking at for the last day or so. I was
really looking for a concurrency solution that solves issues of
concurrency from a language standpoint and it seems like SCOOP is
currently at a standstill research-wise.
I'm not an Eiffel compiler writer so I don't know exactly how every
piece can be implemented but it seems doable. The proposal relies on
transactional memory, probably implemented as software transactional
memory right now.
If this proposal is feasible and desirable, it would need to be
formalized by someone (not me) in to some language rules.
I'm crossing my fingers for a language solution to concurrency!
--------------------------------------------------
A proposal for transaction based concurrency in Eiffel by Colin LeMahieu,
Rationale:
The un-computability of determining if a program based on locks will
deadlock in general necessitates using alternative forms of concurrency.
Abstract:
The Eiffel language already supports the basic idea of transactions in
features. A feature either completes in its entirety or an exception
is raised. The only shortfall of the current implementation is that
any side effects made before the feature completes are not aborted in
the transactional sense. If we adapt the semantics of a feature to
include the idea of a transactional feature, we will be able to
implement concurrency through transactions in the Eiffel language cleanly.
Behavior:
-A feature can be a transaction
-All feature calls are asynchronous
-Transactional features guarantee atomicity and isolation across the
execution of the feature
-When a transactional feature calls another transactional feature, the
transactions are composed.
-The compiler and runtime determine the scheduling either through
compiler analysis, runtime statistics, or runtime transactions.
-When a transactional feature is aborted it is automatically retried
until it is not aborted.
-External features without abort and commit semantics are executed
when all transactions have been committed or aborted and executed
serially with respect to the system, this is ensured by the runtime.
Syntax:
Use the 'transaction' keyword to define a feature as a transaction
feature
obligatory_transfer_example(account, amount) is
transaction
withdraw(account, amount)
deposit(account, amount)
end
withdraw(account, amount: INTEGER) is
transaction
account.balance.withdraw(amount)
end
deposit(account, amount: INTEGER) is
transaction
account.balance.deposit(amount)
end
Use the 'external', 'abort', and 'commit' keywords to define a
transactional external feature. 'External' defines the external
transaction functionality. 'Abort' defines functionality to roll back
any state changed in 'external'. 'commit' defines functionality to
commit the transaction of 'external'.
feature external_feat is
external
""
abort
""
commit
""
end
Design by contract:
-Preconditions and postconditions retain ECMA semantics.
-Features with preconditions and postconditions can only be called
from a feature that is a transaction as a validation constraint.
-If a transactional feature 'f' wants to call feature 'g' with a
precondition 'a', 'f' can check 'a' before calling 'g' and is assured
that 'a' will be the same once 'g' is being executed by the
transactional nature of 'f'; 'a' will either remain valid or 'f' will
be aborted and retried.
-Postcondition wait semantics as introduced with SCOOP do not need to
be used as the compiler or runtime will determine the execution
schedule of a program.
-Class invariants determine the consistency of transactions and are
checked every time a transaction is committed and after it is aborted
Deferred features:
Deferred features can be redefined to be either a transaction or not.
If the feature must be transactional, the designer should encapsulate
the call to the deferred feature within a transaction feature.
Agents:
Agent semantics will not change.
Exceptions:
The feature .last_exception is obsolete
The ANY class contains a new feature last_exceptions and is a
collection of exception objects that have been thrown within the
context of the current feature.
All features within a feature must be executed and either succeed or
generate an exception before the enclosing feature can move to the
retry clause propagate an exception.
If a feature doesn't handle all exceptions, its transaction is
failed(aborted and not retried) with an exception of type ROUTINE_FAILURE
When a lower priority feature has a transactional dependency on a
higher priority feature that fails, it will fail with an exception of
type TRANSACTION_FAILURE which is a subtype of ROUTINE_FAILURE
Priority:
If two calls, 'g' and 'h' within a feature 'f' are in conflict,
priority is assigned by order of program text and the feature
appearing later in the program text will be aborted and retried.
If a looping construct is in conflict with earlier iterations of its
loop, priority is assigned to earlier iterations of the loop and later
iterations will be aborted.
If a recursive call is in conflict with itself, priority is assigned
to the top level nesting and the deeper nesting calls will be aborted.
Thread library:
The thread library is obsolete. All classes should be marked obsolete.
Threads:
Explicitly creating threads is redundant. Legacy external features
that create threads must block until the threads are complete. Code
inheriting from THREAD in the EiffelBase threading library and
effecting execute will continue to work simply by using new feature
call semantics; the library will need to be changed to allow the new
runtime to schedule the feature's execution.
Mutexes:
Code using mutexes will continue to work, however they should be
replaced with transactional code as soon as possible to avoid deadlocks.
Legacy:
This language change is fully backward compatible with serial code,
however, performance benefits would only be seen when using code that
does not reference external features that don't have transaction
semantics. Building transactions over code that references legacy
externals can cause runtime routine failures; the overlying solution
would be to eliminate legacy external features.
External clauses without abort and commit clauses are called 'legacy
externals' and are marked as obsolete by compilers supporting legacy
externals.
Systems that allow legacy external features, without abort and commit
clauses, cannot be executed within transactions. The compiler could
detect many of these through system analysis however the runtime will