Skip to content

Commit

Permalink
[docs] Add explanation on the multiple declaration of "on Initialize".
Browse files Browse the repository at this point in the history
see #1014

Signed-off-by: Stéphane Galland <galland@arakhne.org>
  • Loading branch information
gallandarakhneorg committed Jun 20, 2020
1 parent 65d5ea8 commit 3eca574
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 9 deletions.
139 changes: 137 additions & 2 deletions docs/io.sarl.docs.markdown/src/main/documentation/reference/Agent.md
Expand Up @@ -387,6 +387,8 @@ variable as the keywords `this` and `it`.

### Initialization Handler

#### General Description

When an agent is ready to be executed by the runtime environment, it receives the [:initializeevent:] event.
This event is defined as:

Expand Down Expand Up @@ -420,7 +422,7 @@ It contains the list of the parameters given to the spawning function (as specif
[:End:]


### Guarded Initialization Handler
#### Guarded Initialization Handler

Because [:initializeevent:] is an event, the handler in the agent could use a guard. This feature enables
the developer to write different initialization blocks depending on the guards of the handlers.
Expand All @@ -446,8 +448,141 @@ no parameter. The second event handler is executed when the event has at least o
[:End:]


#### Execution of the Initialization Handler

The `on Initialize` event handler in agents is a bit special, as it is the code run when an agent is born.
As such, its execution is more "synchronous" than other on-behavior rules. In particular:

1. Any event emitted within an `on Initialize`, will not be processed until that
`on Initialize` code finishes. So, your agent initialization should not depend
(and wait) on any fired event being processed, as they won't!
2. When spawning an agent in `on Initialize`, the spawn instructions will return only
after the agent has been created. However, creation of the agent (i.e., of the
corresponding object) does not include initialization of the agent via its
`on Initialize` handler. Said so, the Java thread manager may process those
initialization processes of the new agent before continuing with the execution
of the spawning agent (and this seems to be the case in many Linux boxes
where the executor service of Java tends to have the same behavior during
all the runs). If you change computer, it may be different. In the following
example, the thread executor service of Java seems to give the priority to
the `on Initialize` of [:agenttwoname:] instead of continuing the run of the
spawn function.

[:Success:]
package io.sarl.docs.faq.general
import io.sarl.core.Initialize
import io.sarl.core.Logging
import io.sarl.core.Lifecycle
[:On]
agent Agent1 {
uses Logging, Lifecycle
var agent_name = "agent1"
on Initialize {
info(agent_name + " spawned")
info(agent_name + " spawning Agent2")
spawn(Agent2)
info(agent_name + " end")
}
}

agent [:agenttwoname](Agent2) {
uses Logging
var agent_name = "agent2"
on Initialize {
info(agent_name + " spawned")
info(agent_name + " sleeping")
Thread::sleep(5000)
info(agent_name + " woke up")
info(agent_name + " end")
}
on Initialize {
info(agent_name + " init2")
info(agent_name + " init2 end")
}
}
[:End:]

The output has been:

```
Launching the agent: Agent1
agent1 spawned
agent1 spawning Agent2
agent2 spawned
agent2 init2
agent2 sleeping
agent2 init2 end
agent2 woke up
agent2 end
agent1 end
```

Here it appears as the `on Initialize` behaviors have been run all before
the execution resumes after the `spawn()` statement, but this is just one way
and one should not rely on that behavior being guaranteed: once the spawned
agent is created, the `spawn()` commands returns.


#### Multiple Initialization Handlers

It is allowed to declare multiple initialization handlers into a single agent type, as illustrated by:

[:Success:]
package io.sarl.docs.faq.general
import io.sarl.core.Initialize
import io.sarl.core.Logging
[:On]
agent Agent3 {
uses Logging
on Initialize {
info("1")
}
on Initialize {
info("2")
}
on Initialize {
info("3")
}
}
[:End:]

According to the SARL operational semantic, the three event handlers for `Initialize` are run in parallel.
The initialization event handlers are not constructors (as defined in object-oriented programming paradigm),
they are reacting to the receiving of an `Initialize` occurrence.
Consequently, we could say that there is a single `Initialize` occurrence during the whole life of an agent;
But, it may have multiple handlers to react to the receiving of this event.


#### Initialization Handler within the Inheritance Hierarchy

The example in the previous section could be extended in order to illustrate how the initialization handlers
are run when the type of the agent (here [:agent4name:]) is declared within a inheritance hierarchy.

[:Success:]
package io.sarl.docs.faq.general
import io.sarl.core.Initialize
import io.sarl.core.Logging
[:On]
agent [:agent4name](Agent4) extends [:agent3name](Agent3) {
uses Logging
on Initialize {
info("4")
}
on Initialize {
info("5")
}
}
[:End:]

According to the SARL operational semantic, all the initialization handlers are run in parallel.
In the previous example, five event handlers will be run: three are defined into [:agent3name:], and
two are defined into [:agent4name:]. This mechanism is generalized to all the events within an agent.


### Destruction Handler

#### General Description

The counterpart of [:initializeevent:] is the event [:destroyevent:]. This event is defined as:

[:ShowType:](io.sarl.core.Destroy)
Expand All @@ -469,7 +604,7 @@ Example:
[:End:]


### Guarded Destruction Handler
#### Guarded Destruction Handler

As for [:initializeevent:], the handlers of the [:destroyevent:] event could be guarded.

Expand Down
Expand Up @@ -283,6 +283,9 @@ variable as the keywords `this` and `it`.

### Initialization Handler


#### General Description

When a behavior is ready to be executed by the runtime environment, usually when it
is registered in its owning agent, it receives the [:initializeevent:] event.
This event is defined as:
Expand All @@ -306,7 +309,7 @@ It contains the list of the parameters given that are never set for behaviors.
[:End:]


### Guarded Initialization Handler
#### Guarded Initialization Handler

Because [:initializeevent:] is an event, the handler in the behavior could use a guard. This feature enables
the developer to write different initialization blocks depending on the guards of the handlers.
Expand All @@ -331,8 +334,82 @@ no parameter. The second event handler is executed when the event has at least o
[:End:]


#### Execution of the Initialization Handler

The `on Initialize` event handler in behaviors is a bit special, as it is the code run when a behavior is attached to its agent.
As such, its execution is more "synchronous" than other on-behavior rules. In particular:

1. Any event emitted within an `on Initialize`, will not be processed until that
`on Initialize` code finishes. So, your behavior initialization should not depend
(and wait) on any fired event being processed, as they won't!
2. When spawning an agent in `on Initialize`, the spawn instructions will return only
after the agent has been created. However, creation of the agent (i.e., of the
corresponding object) does not include initialization of the agent via its
`on Initialize` handler. Said so, the Java thread manager may process those
initialization processes of the new agent before continuing with the execution
of the spawning agent (and this seems to be the case in many Linux boxes
where the executor service of Java tends to have the same behavior during
all the runs). If you change computer, it may be different.


#### Multiple Initialization Handlers

It is allowed to declare multiple initialization handlers into a single behavior type, as illustrated by:

[:Success:]
package io.sarl.docs.faq.general
import io.sarl.core.Initialize
import io.sarl.core.Logging
[:On]
behavior Beh1 {
uses Logging
on Initialize {
info("1")
}
on Initialize {
info("2")
}
on Initialize {
info("3")
}
}
[:End:]

According to the SARL operational semantic, the three event handlers for `Initialize` are run in parallel.
The initialization event handlers are not constructors (as defined in object-oriented programming paradigm),
they are reacting to the receiving of an `Initialize` occurrence.


#### Initialization Handler within the Inheritance Hierarchy

The example in the previous section could be extended in order to illustrate how the initialization handlers
are run when the type of the behavior (here [:beh2name:]) is declared within a inheritance hierarchy.

[:Success:]
package io.sarl.docs.faq.general
import io.sarl.core.Initialize
import io.sarl.core.Logging
[:On]
agent [:beh2name](Beh2) extends [:beh1name](Beh1) {
uses Logging
on Initialize {
info("4")
}
on Initialize {
info("5")
}
}
[:End:]

According to the SARL operational semantic, all the initialization handlers are run in parallel.
In the previous example, five event handlers will be run: three are defined into [:beh1name:], and
two are defined into [:beh2name:]. This mechanism is generalized to all the events within a behavior.


### Destruction Handler

#### General Description

The counterpart of [:initializeevent:] is the event [:destroyevent:]. This event is defined as:

[:ShowType:](io.sarl.core.Destroy)
Expand All @@ -354,7 +431,7 @@ Example:
[:End:]


### Guarded Destruction Handler
#### Guarded Destruction Handler

As for [:initializeevent:], the handlers of the [:destroyevent:] event could be guarded.

Expand Down
Expand Up @@ -14,19 +14,19 @@ It may be:
* "error": the issue makes the compiler failing and stopping. This type of issue can be ignored neither programmatically (see below) nor with the SARL compiler configuration.
* "warning": the issue is an important message that may have implication on the quality of your program. But, it does not stop the compiler. This type of issue can be ignored neither programmatically (see below) nor with the SARL compiler configuration.
* "info": the issue is a simple information message from the compiler. The impact on the quality of your program is low. The compiler is not stopped when an information message is output. This type of issue can be ignored neither programmatically (see below) nor with the SARL compiler configuration.
* "configurable": the issue has a level (inside "error", "warning", "info", "ignore") that may be configured by the SARL developers himself. A default level is assumed for the case the SARL developers did not specify his preferred level for the issue. It could be ignore both programmatically (see below) and with the SARL compiler configuration.
* "configurable": the issue has a level (inside "error", "warning", "info", "ignore") that may be configured by the SARL developers themselves. A default level is assumed for the case the SARL developers did not specify their preferred level for the issue. It could be ignore both programmatically (see below) and with the SARL compiler configuration.
* "delegated": it is similar to "configurable", except that the configuration management is delegated to the Eclipse Java Development Toolkit (JDT), and its preference pages. In the case of delegated error, the associated JDT issue code is also provided for information.


In the case of an issue with a "configurable" level, you could select yourself the level that should be used by the SARL compiler for the issue.
In the case of an issue with a "configurable" or "delegated" level, you could select yourself the level that should be used by the SARL compiler for the issue.
This configuration may be done into the preferences of the Eclipse SARL IDE or in the configuration of the `sarlc` command-line compiler.
Additionally, you could force the SARL compiler to ignore an issue by attaching the annotation `@SuppressWarnings("code")` to the element that is marked with the issue.
In this annotation, the code corresponds to the content of the "Code" column below.
This code may have a short format (e.g., the one shown in the column), or a long format (e.g., if you move your mouse pointer on the code, you should see the long format of the code into a pop-up window).
The long code is provided by the SARL compiler at the end of the issue messages.
It is preferable to use the short code as argument of `@SuppressWarnings`. Nevertheless, it may be ambiguous with other issue codes
The long code is provided by the SARL compiler at the end of each of the issue messages.
It is preferable to use the short code as argument to `@SuppressWarnings`. Nevertheless, it may be ambiguous with other issue codes
that could be defined outside the SARL compiler itself (e.g. Eclipse, Checkstyle, etc.). In the case of ambiguity, you could use
the long code as argument of `@SuppressWarnings`.
the long code as argument to `@SuppressWarnings` too.



Expand Down

0 comments on commit 3eca574

Please sign in to comment.