The class Host
manages the entire image
processing in the ML including paging, caching, parallelization and
calling any Module::calculate*
functionality. It
also provides functions such as checking and updating module graphs as
well as calculating (sub)images with getTile()
commands.
The Host
processes a set of ML modules
that are derived from the class Module
and
connected as a directed acyclic graph.
Note | |
---|---|
Do not try to use the |
For memory-optimized calculation of an image or subimage, each
ML module (derived from Module
) supports
so-called page-based image processing, i.e., each
image is divided into blocks (called pages) which
are then processed sequentially or in parallel and are finally
combined to the requested (sub)image.
Consequently, the memory usually does not hold the complete image, but only the currently used fragments.
The page extent is defined as an image property of each ML module output. Page-based image processing can degenerate to global image processing when the page extent is set to the extent of the actual image. This, however, is the worst case and should be avoided.
During image processing, the ML stores as many pages as possible
in the cache of the MLMemoryManager
(Section 1.3.2.2, “The MLMemoryManager
and Memory Handling”) to reach maximum performance. Repeated
(sub)image requests can often be processed more efficiently by simply
reusing existing pages. The extent of pages can be controlled by the
application or by the user.
Overview of image requests performed by the
Host
:
1. Viewer
shows image properties and data
from Filter
.
2. Filter
calculates results from image
properties and data from Load
.
The Host
remains invisible to the module
but processes all Viewer
requests. Functions
(e.g., getTile()) are wrapped in the class
Module
:
When a tile is requested, the tile request is broken down into page request:
Host
calculates a tile with
getTile()
as follows:Allocate memory for the tile.
Calculate the pages that are intersected by the tile.
For all pages:
Already in cache? Yes => Done.
Not in cache? => Allocate page in cache.
Request to Filter
with
calculateInputSubImageBox()
: Determine input area
needed to calculate the page.
Allocate and calculate the input tiles by recursively
calling getTile().
Call calculateOutputSubImage()
in
Filter.
Copy pages to tile.
The ML class Memory
provides functions
for memory allocation, reallocation, freeing, etc. Currently, only
basic functionality is available; however, future versions will use
automatic strategies to (re)organize and/or clean up memory (and the
ML cache) to reduce or avoid out-of-memory errors.
Important | |
---|---|
If possible, always try to use the memory handling functionality of this class when you need to allocate your own memory. This class can automatically handle memory errors and will support correct and safe memory handling in the future. |
Note | |
---|---|
You can use the |
Note | |
---|---|
See Section 5.5, “Tracing, Exception Handling and Checked Object Construction/Destruction” for alternative memory management concepts. |
The following class functionality is currently available:
static void* allocateMemory(MLuint size, MLMemoryErrorHandling handleFailure);
Allocates a memory block of size
bytes.
static void* reallocateMemory(void* ptr, MLuint size, MLMemoryErrorHandling handleFailure);
The memory block pointed to by ptr
is
resized and copied so that it has at least
size
bytes.
static void freeMemory(void* ptr);
Frees memory that has been allocated with any
Memory
function. NULL pointers may be
passed safely; they are simply ignored.
static void* duplicateMemory(const void *ptr, MLuint size, MLMemoryErrorHandling handleFailure);
Copies the memory pointed to by src
of size size
in a newly allocated buffer
which must be freed by the caller with
freeMemory()
. If ptr
is passed as NULL
, NULL
is returned without any error handling.
static char* duplicateString(const char *ptr, MLMemoryErrorHandling handleFailure);
Copies the passed null-terminated string
str
in a newly allocated buffer which must
be freed by the caller with
freeMemory()
.
Note | |
---|---|
Always use functions of the class
|
The parameter handleFailure
determines
the function behavior in error cases:
If memory allocation fails, NULL
is
returned without error handling. The programmer must take care of
the error.
If memory allocation fails,
ML_PRINT_FATAL_ERROR()
with error code
ML_NO_MEMORY
is called;
NULL
is returned if
ML_PRINT_FATAL_ERROR()
has been returned. The
programmer does not need to take care of the error case, because
the ML handles it.
If memory allocation fails,
throw(ML_NO_MEMORY)
is executed. The
programmer could implement something like
Example 2.4. Using Exceptions when Allocating Memory with MLThrowNoMemory
ML_START_NAMESPACE try { // Try to allocate... Memory::allocateMemory(1000, ML_THROW_NO_MEMORY); } catch(MLErrorCode) { // Handle error if memory could not be allocated. } ML_END_NAMESPACE
Note that these error handling cases will only occur if the
Memory
class functionality has no chance to
allocate the required memory. In future versions, the following might
happen: The first internal allocation fails, but the
Memory
class clears the ML cache and
successfully retries memory allocation. In those cases, none of the
above error cases will be used.
The
ml::Base
class is a base class of many ML classes and is designed for all
objects passed between different ML modules via the so-called
Base
fields. Thus it is possible to establish
transfer of arbitrary data types between modules.
The ML provides a so-called Runtime Type System for managing all important classes available in the module database and in the ML.
This class contains the global runtime type system of the
ML. It manages a dictionary of runtime types and can create and
remove runtime types. This class only contains static components
and must be initialized with
and destroyed
with init()
destroy().
This class contains runtime-generated type and inheritance
information of associated classes. To track this information, the
macros defined in
mlRuntimeSubClass.h
have to
be inserted in the declaration and implementation of the
associated classes.
This class manages a set of instances of the class
RuntimeType
. The class
Runtime
uses one global instance of this
class for the runtime type system of the ML.
The file
mlRuntimeSubClass.h
also includes
important and frequently used macros.
ML_BASE_IS_A(base,type)
This macro is used to check whether the given
Base
pointer is of the expected type:
ML_BASE_IS_A(base, MarkerExample).
Note | |
---|---|
The macro |
Base
must be used.Each of these macros implements the interface to the runtime type system of the derived class.
ML_CLASS_HEADER(className)
This macro must be included in the header of a non-abstract class to declare some additional methods described below.
ML_MODULE_CLASS_HEADER(ModuleClassName)
This macro must be included in the header of a class
derived from the class
Module
to declare some
additional methods described below.
ML_ABSTRACT_CLASS_HEADER(className)
This macro must be included in the header of an abstract class to declare some additional methods described below.
One of the following macros in the source file implementation of
a class derived from Base
must be used.
Each of these macros implements the interface to the runtime type system of the derived class.
ML_CLASS_SOURCE(className, parentName)
This macro must be included in the source file of a
non-abstract class to implement the methods declared with
ML_CLASS_HEADER
.
ML_MODULE_CLASS_SOURCE(className, parentModule)
This macro must be included in the source file of classes
derived from the class Module
to implement
the methods declared with
ML_MODULE_CLASS_HEADER
.
Module
implements protected constructors
and assignment operators to avoid the assignment of
Module
modules to themselves. The normal
ML_CLASS_SOURCE
macros cannot be used.
ML_ABSTRACT_CLASS_SOURCE(className,parentName)
This macro must be included in the source file of an
abstract class to implement the methods declared with
ML_ABSTRACT_CLASS_HEADER
.
ML_MODULE_CLASS_SOURCE_EXT(className, parentModule, superClassConstructs)
This macro is an alternative to
ML_MODULE_CLASS_SOURCE
if the constructor of
the parentModule
does not have two
parameters or if other members need to be initialized (e.g.
constants). The third parameter
superClassConstructs
permits the
specification of the correct constructor call of the superclass,
e.g., ML_MODULE_CLASS_SOURCE_EXT(MyFilter, MyParentModule, :MyParentModule())
does not pass
parameters for the superclass constructor that is used in the
normal Module
.
If you need to pass more complex expressions as third parameters, such as superclass or member initializers (as a comma-separated list, for example), use the following trick:
Example 2.5. How to Use the Macro ML_MODULE_CLASS_SOURCE_EXT
// Stuff to do for base classes when copy constructor is implemented // (which is done in a macro to have a private and not an executable // copy constructor). #define _INIT_STUFF : Module(0,0), _initMember1(initValue1), \ _initMember2(initValue2) // This macro declares some automatically generated functions and methods // for the runtime system and for the initialization of this class. It // implements more elaborated superclass and member initializers given // by _INIT_STUFF. ML_MODULE_CLASS_SOURCE_EXT(MyNewModule, Module, _INIT_STUFF) #undef _INIT_STUFF
See also the file
mlLibraryInitMacros.h
which does not directly belong to the runtime type system but which
contains macros for the initialization after runtime linking to the
library. It permits the implementation of a function in a library
where module classes and runtime types can be initialized directly
after linking to the library.
See Chapter 5, Debugging and Error Handling for detailed information on concept, classes and macros for error handling and debugging.
© 2024 MeVis Medical Solutions AG