05.08.2014 Views

here - Stefan-Marr.de

here - Stefan-Marr.de

here - Stefan-Marr.de

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

5.3. The OMOP By Example<br />

The process that has been spawned during the initialization of the agent object<br />

tries in<strong>de</strong>finitely to process these update blocks in #processUpdateBlock.<br />

It waits for the next update block, evaluates it with the current state as argument,<br />

and sets the result value as new state.<br />

This implementation is simplified but represents the essence of Clojure<br />

agents. The differences with the Clojure implementation sketched in Sec. 2.4.3<br />

originate from language differences between SOM and Clojure. For instance,<br />

SOM does not have the notion of private methods, which leaves the implementation<br />

methods #initialize and #processUpdateBlock exposed to arbitrary<br />

use. Thus, these methods could be called from another thread and violate<br />

the assumption that only one update function is executed at a time. The remaining<br />

differences originate from the use of the OMOP. Note that the #read,<br />

#initialize, and #send: method are annotated with unenforced. They are<br />

by themselves not subject to the OMOP’s enforcement, guaranteeing that it<br />

does not come to meta recursion during their execution.<br />

Providing exten<strong>de</strong>d Guarantees based on the OMOP While Clojure gui<strong>de</strong>s<br />

<strong>de</strong>velopers to use agents in conjunction with immutable data structures, at the<br />

same time it makes the pragmatic <strong>de</strong>cision not to enforce any such guarantees<br />

on top of the JVM. One reason for this is the anticipated performance impact.<br />

Another issue is the integration with Java itself, which makes it impossible<br />

to provi<strong>de</strong> such guarantees consistently. This section uses this example to<br />

<strong>de</strong>monstrate how the OMOP can be used to express and in return enforce<br />

such guarantees concisely.<br />

To this end, Lst. 5.3 <strong>de</strong>fines the AgentDomain. The domain implements the<br />

intercession handler #requestExecOf:on:with: to ensure that only a single<br />

thread of execution modifies the agent and that the agent is not reinitialized.<br />

In this simple example, this is done by using a list of selectors that are allowed<br />

to be executed. In case any other selector is sent to an agent, an error is raised<br />

to report the violation. 5<br />

As the ImmutableDomain in Sec. 5.3.1 shows, adding the guarantee of immutability<br />

is also possible in a concise manner. Using the ImmutableDomain<br />

of Lst. 5.1 in this example, the agent ensures in #processUpdateBlock that the<br />

state is an immutable object. This is done by requiring the immutable domain<br />

to #adopt: the return value of an update block. 6<br />

5 Our actual implementation of agents goes beyond what is presented <strong>here</strong>. For brevity, the<br />

example leaves out operations such as #await and #send:with:.<br />

6 In the current implementation #adopt: performs a shallow adopt only and thus, only the<br />

root object of the object graph is ma<strong>de</strong> immutable.<br />

123

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

Saved successfully!

Ooh no, something went wrong!