|
|
Table of |
§6. Object Teams API |
| §5. Team activation |
![]() |
|
| Binding activation | All callin bindings of a Team only have effect if the Team is active. Activation may be caused by explicit statements and also happens implicitly at certain points during program execution. |
![]() |
|
| Guard predicates |
Callin bindings can further be controlled using guard predicates,
which can be attached to roles and teams at different levels. If a guard
predicate evaluates to false, all affected callin bindings
are disabled.
|
![]() |
|
within (myTeam) { stmts }within (myTeam) stmtmyTeam must denote a Team instance. For the time of executing this block, this Team instance is activated for the current thread,
which has entered the within block.
The within block statement guarentees that it leaves
the team in exactly the same activation state as it was in when
entering this block. This includes the cases of exceptions, meaning
that deactivation will also occur if the execution of the block
terminates abnormally.
org.objectteams.Team (super class of all team classes) to control Team activation disregarding the block structure of the program.
The methods activate() and deactivate() are used to activate and deactivate a team instance for the current thread. activate(Thread aThread) and deactivate(Thread aThread).
In order to achieve global activation for all threads the predefined constant Team.ALL_THREADS is passed to these methods (e.g. activate(Team.ALL_THREADS)).activate() is invoked on a team instance
that has been explicitly activated before, this statement has
no effect at all (note the difference in §5.3(a) below).within
block, it will remain active after leaving the block.
within block
and if deactivate() is invoked on the same team
instance from within the within block,
leaving the block will re-activate the team.
activate().
Explicit activation is stronger than implicit activation and thus persists after the
team level method terminates. Ie., leaving a team level method will never reset
an explicit activation.
within is strongest, followed by (de)activate(), weakest is implicit activation. In this sense, explicit imperative (de)activation may override the block structure of implicit
activation (by explicit activation within a team level method), but not that of a within block (by deactivation from a within block).
base guards,
which affects the exact point in the control flow, where the guard will
be evaluated.
when followed by
a boolean expression in parentheses:when (predicateExpression)this, base.true enables
the callin binding(s) to which it applies.
Evaluation to false disables the callin binding(s).
void roleMethod(int ir) <- after void baseMethod(int ib)
when (ir > MyTeam.this.threshold);true.this.this with or without explicit qualifying this.
MyTeam.this.
after: The result (denoted by the special identifier result) of the role method, if it is not void.
void roleMethod(int ir)
when (ir > MyTeam.this.threshold) { body statements }protected class MyRole
when (value > MyTeam.this.threshold)
{
int value;
other class body declarations
}this (explicit or implicit, see above). Thus, in the example value will be interpreted as a field of the enclosing role.
MyTeam.thisthis) and its features.
Of course all guards can also access any visible static feature of a visible class.
Even if a guard has no direct effect, because, e.g., a role class has no callin bindings (maybe not even a role-base binding), predicates at such abstract levels are useful, because all predicates are inherited by all sub classes (explicit and implicit).
false and thus refuses to invoke the
callin bound role method. Using base guards it is easier to prevent any
side-effects caused by a callin binding, because lifting could cause side-effect
at two levels:
hasRole, e.g.
base as in:
protected class MyRole playedBy MyBase
base when (base.value > MyTeam.this.threshold)
{
class body declarations
}base guard:
base
can be used to denote the base object that is about to be lifted.
after callin bindings, the
identifier result may be used to refer to the
result of the base method (if any).base.
MyTeam.this).
base has the static type
java.lang.Object.
and.
|
Account objects only get ForeignAccount roles, if they belong to a different bank than the surrounding ATM team.base identifier.
debitWithFee to calls where the base method argument amount is lower than 1000.
Account.debit causes a replace callin to debitWithFee ONLY if BOTH predicates evaluate to true.
| General activation via config file: Instead of adding the team initialization and activation code to the main program, it is possible to add the respective teams via a config file. Every line of this text file contains the fully qualified name of a compiled team, which has to be available on the classpath. For the instantiation of these teams the default constuctor is used, which means adding a team to an application this way requires the team to provide a default constructor. The activation order (see §5.1) for these teams corresponds to the order in which they are listed in the config file. Lines starting with a '#' denote comment lines. Example config file:
'-Dot.teamconfig=<config_file_name>' has to be used when starting the application. |
||||||
| Activation adjustment example: Teams added via the config file mechanism are activated by default. Because no reference to them is stored anywhere, it is not possible do deactivate them later. If deactivation of unanticipated added teams is required, this can be archieved by adding a manager team via config file and encapsulate the actual functionality in another team managed by the manager team. This way a functional team can be activated and deactivated as needed. Example code: |
|
|
startMethod and stopMethod are methods which demand the activation and deactivation respectively.
|
|
Table of |
§6. Object Teams API |