Entities encapsulate state and present an event-oriented interface encoded as methods. However, methods also represent regular Java invocations on objects. The developer of an entity class must, therefore, remember that public methods are invoked in simulation time while non-public methods are regular invocations, that only non-public and non-static fields are allowed, etc. This can be confusing and it imposes restrictions on the developer and can lead to awkward coding practices within entity classes. In other words, there exists a clash of functionality between entity and object invocation semantics at the syntactic level.
To address this issue, we introduce proxy entities. As their name implies, proxy entities exist only to relay incoming events onto a target object. As with any entity method invocation, there are still two phases: event dispatch and event delivery. And, even though the internal mechanisms used for both event dispatch and delivery of proxied invocations may be totally different from regular entity invocations, there are no syntactic differences visible to the developer. Furthermore, the performance is equivalent.
Proxies are created via the proxy API call, which accepts two parameters. The first parameter is the proxy target and can be one of three types: an entity, a regular object or a proxiable object. The proxying of each of the three possible target types is illustrated in Figure 6 and described below. The second parameter to the system call is the proxy interface, indicating the methods that are to be exposed and relayed to the target. Clearly, the proxy target must implement the proxy interface and this is also verified by the system.
Note that this approach inserts the overhead of an additional method invocation into the event delivery process. Note also that if one invokes the proxy call twice on the same object, the result is two new entities that share that object in their state, as well as all those reachable from it. We can, however, eliminate this indirection through the use of proxiable objects.
Proxy entities simplify development. They allow an object the flexibility of combining both event-driven and regular method invocation, without loss of performance. They are interface-based, so they do not interfere with the object hierarchy. And, they allow for a capability-like isolation of functionality, which is useful in larger simulation programs. Finally, although the proxy separators are completely different in implementation, they behave in the same way as regular separators, both in terms of execution semantics and performance.
The code listing in Figure 7 shows how to use proxy entities with a basic example, similar to the earlier hello example. Note that myEntity is proxiable, because it implements the myInterface on line 10, which inherits JistAPI.Proxiable on line 5. The proxy separator is defined on line 13 using the JistAPI.proxy call with the target proxiable instance and appropriate interface class. The invocations on this proxy on lines 19 and 27 occur in simulation time.