The Managers
The managers provide global functionality within the engine and are
implemented as singletons; that is, only one instantiation is made
available for each type of manager. Managers are singletons because
duplication of their resources can cause redundancy, leading to
potential processing performance implications. Singletons provide
common functionality that is usable across all the systems.
Task Manager
The task manager handles the scheduling of a system's task within its
thread pool. The thread pool creates one thread per processor to get
the best possible n-way scaling to processors. The task manager also
prevents over-subscription, which avoid unnecessary task switching
within the OS.
The task manager receives from the scheduler its list of tasks to
execute, as well as which tasks to wait for execution to complete.
The scheduler gets its list of tasks to execute from the different
systems themselves. Each system has only one primary task; this is
called functional decomposition. Each primary task can issue as
many sub-tasks as it wants for operating on its data; this is called
data decomposition.
Figure 6 shows how the task manager could issue tasks onto
threads for execution on a quad-core (four-thread) system:
Figure 6. An example of the task manager's four-thread pool.
Aside from access by the scheduler for issuing primary tasks, the
task manager also has an initialization mode in which it calls systems
serially from each thread so that the systems can initialize any local
storage they require for execution.
For help getting started on implementing a task manager, refer to
Appendix D.
State Manager
State management is part of the messaging mechanism that tracks
and distributes change notifications made by a system to other
interested systems. To reduce unnecessary change notification
broadcasts, systems must register with the state manager for
the changes they want to receive. This mechanism is based on
the observer design pattern, which is described in more detail in
Appendix C. The basic premise of the observer design pattern is
an observer observing a subject for any changes, with a change
controller acting as a mediator between the two.
Here's how the mechanism works:
1. The observer registers the subject it wants to observe with the
change controller (or state manager).
2. When the subject has changed one of its properties, it sends a
change notification to the change controller.
3. The change controller, when requested by the framework,
distributes the subject's change notification to the observer.
4. The observer queries the subject for the actual changed data.
The free step mode of operation introduces extra complexities into
this mechanism: (1) The data must be included with the change
notification because a system that has modified shared data may
still be executing and therefore cannot be queried for its value. (2)
If a system is not yet ready to receive the changes at the end of a
clock tick, the state manager will need to hold onto that data until all
systems registered for it are finally ready to receive it.
The framework implements two state managers-one for handling
changes on the scene level and another for handling changes on
the object level. Because the scenes and objects, for the most part,
have different messages that are relevant to them, separating them
removes the need to process unnecessary messages. However, any
object changes that are relevant to the scene will be registered with
the scene so that it will receive those change notifications.
To remove any synchronization overhead, the state manager has a
change queue for each thread created by the task manager. No
synchronization is required when accessing the queue. The queues
can then be merged after execution using the method described in
the Data Synchronization section.
Although it seems that change notifications would have to be
distributed serially, this action can be parallelized. When systems
are executing their tasks they operate across all their objects. For
example, the physics system is moving around objects, checking for
collisions, and setting new forces as physics objects interact with
each other. During change notification, a system's object is no
longer interacting with other objects from its own system, but is
now interacting with other extensions in the universal object it is
associated with. This means that universal objects are now independent
of each other, so each universal object can be updated in parallel.
Take note, though, that there may be some corner cases that need
to be accounted for with synchronization. Still, something that once
looked hopelessly serial can now get at least some parallelization.
Figure 7. An internal UObject change notification.
Service Manager
The service manager provides access to functionality to systems
that are external to their implementations. The service manager
does not provide this directly but has the interfaces defined for it, and
any systems that implement the exposed interface functionality will
register themselves with the service manager.
Only a small set of services is available because the design of the
engine is to keep the systems running as discretely as possible. Also,
the systems are not free to provide any service they so choose, but
only the ones that the service manager provides.
The service manager also gives the different systems access to each
other's properties. Properties are values of each system that are
specific to a system and are therefore not passed in the messaging
system. Examples: the screen resolution of the graphics system or the
gravity value of the physics system. The service manager gives the
systems access to these properties without giving the systems direct
control over them. The property changes are queued and are issued
only during serial execution. Accessing another system's properties
is a rare occurrence and should not be used as common practice. This
is made available for properties or functionality that does not change
from frame to frame. Examples: the console window turning on and
off the wireframe mode in the graphics system or the user interface
system changing the screen resolution as requested by the user.
Figure 8. An example of the service manager.
Environment Manager
The environment manager provides the functionality for the
engine's running environment. The function groups provided by
the environment manager are:
Platform Manager
The platform manager handles all OS call abstraction and also provides
added functionality beyond just a simple abstraction. This gives the
benefit of encapsulating several common functional steps within one
call, instead of all the callers having to implement them or know about
the nuances of the OS calls.
An example is the call in the platform manager to load a system's
dynamic library. In addition to loading a system in, the platform
manager also gets the function entry points and then calls the
library's initialization function. It also keeps around a handle to the
library, unloading it upon exiting the engine.
The platform manager provides information about the processor,
such as which instructions sets are supported, frequency, and cache
sizes. The platform manager also initializes some of the behavior
for the executing process, such as the operation of floating-point
denormals (or subnormal numbers).
|
Reminds me of Erlang.
Can you post some test results ?
Corei7 performance scaling will probably be decent (around 4x I bet) :p
But did you have the opportunity to tests on a xeon 7400 (6 cores) or on a dualxeon (12 cores) ?
Vincent