This page was originally written by Arturo,
it is a very initial draft.
Last updated: [98/05/18 Arturo - First checked in]
We've spent a fair amount of time discussing E and its benefits:
This document is an attempt at separating all of the different components
of E and examining their cost/benefit tradeoffs.
- Asynchronous messaging and deadlock avoidance.
- Optimistic object references.
- Capability security.
- Network object messaging.
- E Language Specification
- ELib JavaDoc
- Dan's 'New E' Specification
2. Deconstructing E
2.1. Within process asynchronous messaging
This is basically an event queue with capability security in the send/delivery
Threads are difficult to program in, there are synchronization issues
that depending on a number of circumstances can lead to deadlock.
- The single Run Queue has many synchronization and consistency benefits.
Basically objects that are strictly invoked from the RunQ (or indirectly
so) don't need to worry about synchronizing over methods or data.
- Asynchronous programming is less prone to deadlocks. (i.e. you
need to deadlock by design, rather than by consequence of a number
- When used for network messages it compensates for latency, avoiding
the need to wait for a result or acknowledgment from the other side.
- Ideal for multicasting where the notions of result don't scale.
- It is a significant change from the well understood synchronous
invocation programming and design requires very thorough understanding
of cause and effect of events (what we like to call causality programming).
- Operations that need to return information require a separate return
message (unless you have object futures, which have their own tradeoffs).
- You need to be careful about keeping said part of the application
away from side-affecting threads.
- Error handling and value returning becomes much more difficult
since the error happens at a later point in time when the state of
the invocating object could have changed.
2.1.4. Notes on asynchronous error handling
There are three kinds of errors that can occur on an async invocation:
- Unexpected invocation error usually reflected by RuntimeExceptions.
- Expected invocation error, noted by a 'throws' statement on the
- Errors that happen as a result of this object asynchronously invoking
on other objects.
2.1.5. Required components
- Run Queue
- CRAPI based invocation mechanism
2.2. Generic invocation interface (call, send)
The first versions of E (please correct me here if I'm wrong) generated
classes for all the different kinds of stubs, since at that time we did
not have CRAPI there was no way to do a generic invocation interface.
Now we have an interface is used to describe every single kind of invocation:
void sendOnly(target, "methodName", args);
This allows us to write intermediaries that extend object invocation
Intermediary objects that extend behavior with minimal class bloat. Examples
- Revocable forwarders.
In applying this you loose all the typing information, this makes programming,
debugging and maintenance more difficult. The only way to get the type
information back is by having some form of stubs that
2.3. Stubs or lack of thereof
One of the issues with a generic invocation interface is the difficulty
with typing issues, stubs allow you to have strong typing, but they always
come at a cost. In the first generations of E we had a compiler generate
a number of stub classes where each class would have a different internal
invocation for every method, thanks to CRAPI and Danfuzz this evolved into
Stubs that turn a strongly typed call into a generic asyncrhonous invocation.
See Robj's digression on proxy typing.
Stubs can serve two different purposes:
- Provide objects of the right type that you invoke synchronously that
generate the generic invocation.
- Strongly typed variables that are only used as references in invocations
2.3.1. No Stubs
This is when you decide to use the generic invocation interface for every
async message send.
- Benefit: No bloat of any kind whatsoever.
- Cost: Lose all of the typing information, and hence lose the compiler
support and code clarity that comes with it.
2.3.2. Compiler generated stubs.
- Benefit: Strongly typed stubs that can be used to invoke through
and even have exception handling information.
- Cost: Class bloat.
2.3.3. Runtime generated stubs.
2.3.4. El Cheapo
2.4. Object futures
Otherwise known as optimistic object references, channels, promises, unresolved
object references, etc. Well, not quite since all of these are not the same,
although they are based on the same principal.
2.4.1. As object message queues.
2.4.2. As object value futures.
2.4.3. The network, security and optimistic object references.
2.5. Promises as return values of 'send'
Object instances per asynchronous invocation.
2.6. Picking the right tool for the right job:
3. Comm system
The comm system is the part of our system responsible for:
Exception handling, alternatives and multicast group management are issues
that need to be evaluated and understood at every level of the system.
- Setup, tear down and maintenance of connections.
- Object pass by copy transport/serialization.
- Support for (fragile) objects that get exported by proxy.
- Support for (sturdy) unique network object references, these references
are used to get a fragile object proxy.
- Provides the core support for multipoint messaging and multicast
- Proper layering of system all the way down.
- Firewall support.
- Background loading of large objects.
- Versioning identification a part of the connection handshake.
- Tools for allowing the programmer to define which things are exportable,
- Figure out best implementation path for the different features.
- Proper multipoint support at every level.
- Minimize what gets sent over the wire.
- How much of the existing code to leverage?
This is a description of a possible layering of the comm system:
3.2. Data Comm System (Socket+)
This layer is responsible for connection set up, tear down, bit transport,
authentication, encryption, compression.
3.2.1. Connection management
3.2.2. Wire protocol
3.2.4. Reliability and ordering
3.2.5. Exception handling
3.2.6. Multicast support
3.3. Object transport System (Java Serialization + Data Comm
This layer is responsable for the per message encoding and decoding of an
3.3.1. Pass by copy
Object to byte array serialization support.
3.3.2. Pass by special copy, special encoding behaviours (writeObject
3.3.3. Other encoding behaviours
3.3.4. Per message/object graph encoding/decoding
3.3.5. Wire protocol
3.3.6. Usage of Data Comm level excepions.
3.4. Exportable object references (Proxies + Messages)
With this we provide an abstraction for object to object inter-process messaging.
3.4.1. Objects passed by proxy i.e. Exportable
There is a certain number of classes/interfaces defined to be Exportable.
(Actually based on El Cheapo they would extend BaseExportable)
3.4.2. Object Swiss Numbers
3.4.3. Import/Export tables
They need weak pointers to enable acyclic network garbage collection.
3.4.4. Process Identity
Center for managing multiple connections.
Which holds the private public key pair used to
A SturdyRef is the combination of:
[Information to contact the machine + Object's Swiss number]
There are issues relating to the lifetime of SturdyRefs and dealing with
live references upon revocation.
3.4.7. Object to object reliability and ordering
3.4.8. Async object garbage collection for proxies (wire protocol)
Needs a clean up protocol to deal with race conditions by using a wire
counting protocol. The race condition is that the proxy might get garbage
3.5. Alternatives to be evaluated
3.5.2. T.120 Stack
To do list:
- Bill research SSLava
- Design data comm API s. t.. SSL could go underneath.
- Decide whether to use off the shelf SSL today, otherwise user our
- Firewall story.
- Arturo writes up E page and supports Bob.
- Bob does toy object comm system guts.
- Robj writes up issues page and object comm API with MarkM's help.
- Scott helps define multipoint abstraction and its application to
the different layers.
- Research object comm alternatives