Provides real-time {@link javolution.context.Context} to facilitate
separation of concerns and achieve higher level of performance and
code predictability.
Separation of concerns is an important design principle greatly misenderstood.
Most developers think it is limited to modularity and encapsulation or it
requires special programming tools (e.g. Aspect programming).
Separation of concerns is very powerful and easier than it looks.
Basically, it could be summarized as the "pass the buck principle".
If you don't know what to do with some information, just give it to someone
else who might know.
A frequent example is the catching of exceptions too early (with some logging processing)
instead of throwing a checked exception. Unfortunately, they are still plenty of cases
where the separation of concerns is not as good as it could be. For example logging!
Using the standard logging, the code has to know which logger to log to? Why?
Separation of concerns can be adressed through "Aspect Programming",
but there is a rather simpler solution "Context Programming"!
It does not require any particular tool, it basically says that every threads
has a context which can be customized by someone else (the one who knows what to do).
Then, your code looks a lot cleaner and is way more flexible as you don't have
to worry about logging, security, performance etc. in your low level methods.
For example:[code]
void myMethod() {
...
LogContext.info("Don't know where this is going to be logged to");
...
}[/code]
Used properly Javolution's {@link javolution.context.Context contexts}
greatly facilitate the separation of concerns. Contexts are
complemented by others classes such as for example the
{@link javolution.lang.Configurable Configurable} class to reduce
dependency between configuration and application code.
This package provides few predefined contexts:
- {@link javolution.context.LocalContext LocalContext} - To define locally
scoped environment settings.
- {@link javolution.context.ConcurrentContext ConcurrentContext} - To take advantage of concurrent
algorithms on multi-processors systems.
- {@link javolution.context.AllocatorContext AllocatorContext} - To control
object allocation, e.g. {@link javolution.context.StackContext StackContext}
to allocate on the stack (or RTSJ ScopedMemory).
- {@link javolution.context.LogContext LogContext} - For thread-based or object-based logging
capability, e.g. {@link javolution.util.StandardLog StandardLog} to leverage standard
logging capabilities.
Note:
java.util.logging provides class-based
logging (based upon class hierarchy).
- {@link javolution.context.PersistentContext PersistentContext} - To achieve persistency across
multiple program execution.
- {@link javolution.context.SecurityContext SecurityContext} - To address application-level security
concerns.
- {@link javolution.testing.TestContext TestContext} - To address varied aspect of testing such as performance and regression.
- I am writing an application using third party libraries.
I cannot avoid GC unless I get the source and patch it to Javolution.
Can I still make my application real-time using {@link javolution.context.StackContext StackContext}?
You cannot get determinism using "any" library (including Java standard library)
regardless of the garbage collector issue. Array resizing, lazy initialization, map rehashing (...)
would all introduce unexpected delays (this is why Javolution comes with its own
{@link javolution.lang.Realtime real-time} collections implementation).
Still, you may use incremental/real-time collectors (if few milliseconds delays are acceptable).
These collectors work even faster if you limit the amount of garbage produced onto the heap
through {@link javolution.context.StackContext stack allocations}.
- Can you explain a little how objects can be "stack" allocated?
It all depends upon the StackContext {@link javolution.context.StackContext#DEFAULT default} implementation.
The default implementation use thread-local queues (no synchronization required);
but if you run on a RTSJ virtual machine
entering a {@link javolution.context.StackContext StackContext} could mean using ScopedMemory .
- As a rule, I am skeptical of classes that pool small objects.
At one time (5 years ago) it was a big win. Over time, the advantage has
diminished as garbage collectors improve. Object pools can make it much more
difficult for the garbage collector to do its job efficiently, and can have
adverse effects on footprint. (Joshua Bloch)
Stack allocation is different from object pooling, it is a simple and transparent
way to make your methods "clean" (no garbage generated), it has also the side effect
of making your methods faster and more time-predictable.
If all your methods are "clean" then your whole
application is "clean", faster and more time-predictable (aka real-time).
In practice very few methods need to enter a {@link javolution.context.StackContext StackContext},
only the one generating a significant number of temporary objects (these methods are made "cleaner"
and faster through stack allocation). For example:[code]
public final class DenseVector> extends Vector {
...
public F times(Vector that) {
final int n = this.getDimension();
if (that.getDimension() != n) throw new DimensionException();
StackContext.enter();
try { // Reduces memory allocation / garbage collection.
F sum = this.get(0).times(that.get(0));
for (int i = 1; i < n; i++) {
sum = sum.plus(this.get(i).times(that.get(i)));
}
return StackContext.outerCopy(sum); // Stack object exported through copy.
} finally {
StackContext.exit(); // Resets stack.
}
}
...
}[/code]
|
Allocator.java | Class | This class represents an object allocator; instances of this class
are generated by
AllocatorContext .
If an allocator has recycled objects available, those are returned
first, before allocating new ones.
Allocator instances are thread-safe without synchronization,
they are the "production lines" of the
ObjectFactory factories ,
their implementation is derived from the
AllocatorContext to which they belong (e.g. |
ConcurrentContext.java | Class | This class represents a context to take advantage of concurrent
algorithms on multi-processors systems.
When a thread enters a concurrent context, it may performs concurrent
executions by calling the
ConcurrentContext.execute(Runnable) static method.
The logic is then executed by a concurrent thread or by the current
thread itself if there is no concurrent thread immediately available
(the number of concurrent threads is limited, see
Javolution Configuration for details).
Only after all concurrent executions are completed, is the current
thread allowed to exit the scope of the concurrent context
(internal synchronization).
Concurrent logics always execute within the same
Context as
the calling thread. |
Context.java | Class | This class represents an execution context; they can be associated to
particular threads or objects.
Context-aware applications may extend the context base class or any
predefined contexts in order to facilitate
separation of concerns.
The scope of a
Context should be surrounded by a try,
finally block statement to ensure correct behavior in case
of exceptions being raised. |
ImmortalContext.java | Class | This class represents an allocator from immortal memory (RTSJ).
It is typically used to allocate (and recycle) from immortal memory
allowing dynamically created static instances to be accessible by
NoHeapRealtimeThread :[code]
public synchronized Text intern() {
if (!INTERN_INSTANCES.containsKey(this)) {
ImmortalContext.enter();
try { // Forces interned instance to be in immortal memory.
Text txt = this.copy(); // In ImmortalMemory.
INTERN_INSTANCES.put(txt, txt);
} finally {
ImmortalContext.exit();
}
}
return (Text) INTERN_INSTANCES.get(str);
}[/code]
Because class initialization may occur while running in a non-heap
context (e.g. |
LogContext.java | Class | This class represents a context for object-based/thread-based logging
capabilities.
The
LogContext.DEFAULT default logging context is
StandardLog StandardLog to leverage java.util.logging
capabilities.
Logging can be temporarily modified on a thread or object basis.
For example:[code]
public static main(String[] args) {
LogContext.enter(LogContext.NULL); // Temporarily disables logging.
try {
ClassInitializer.initializeAll(); // Initializes bootstrap, extensions and classpath classes.
} finally {
LogContext.exit(LogContext.NULL); // Goes back to default logging.
}
...
}[/code]
Applications may extend this base class to address specific logging
requirements. |