main 9.0
Loading...
Searching...
No Matches
HOWTO Micro-Kernel - the Internals

What is a MANAGED OBJECT ?

INTERNALS

The micro-kernel links the "C" library libmkkernel with a target-language. The basics of the micro-kernel are implemented as MANAGED OBJECT.

MANAGED OBJECT

The aim of managed-object technology is that a class defined in "C" is automatically available as a class in the target-language.

This requires three technologies:

  1. A technology that supports the life-cycle of a class in every target-language.
  2. A technology that translates the class definition from "C" into code that can be used as a native class in the target-language.
  3. A technology to combine the two classes, the "C" class and the target-language class.

Example: The managed-object class MkBufferStreamC in "C" is available as MkBufferStreamC (C, C++, C#, VB.Net, Java, Go, Python, Ruby, Tcl, Perl, PHP) in all target-languages.

‍Each class in the target-language that supports managed-objects uses a base-class that supports managed-objects and has a shadow-class in the micro-kernel.

DATA STRUCTURE

A managed-object class has two or three sections:

superclassThis is the section that defines the class hierarchy
instance attributesThis is the section used by the programmer to define the attributes
ILS storageThis is an optional section that is used as a predefined memory for dynamic instance attributes

One design-goal of the micro-kernel was type-safty, this mean that never a HARD cast should be required:

MK_OBJ myobj = (MK_OBJ) mypointer; // bad, this is a HARD cast from VOID (MK_MNG) pointer
MK_OBJ myobj = MkObj(my_unknown_pointer); // good, this is a SOFT run-time-cast (not as fast) from a UNKNOWN (MK_MNG) managed-object-pointer
MK_OBJ myobj = MkOBJ(my_known_pointer); // good, this is a SOFT compile-time-cast (fast) from a KNOWN managed-object-pointer
MK_OBJ MkObj(MK_MNG mng)
#define MkOBJ(x)
Note
read more at: MkObjectC_Obj_C_API

Example from kernel_mk.h The abstract class MkBufferStreamS managed-object struct

// BEGIN-MkBufferStreamS-super - created by 'cls_MqS.tcl -i NHI1_HOME/theKernel/libmkkernel/.libmkkernel.meta' - DO NOT change
union {
struct MkObjectS obj; // base CLASS \MkObjectS
struct MkBufferS buf; // base CLASS \MkBufferS
} super;
// END-MkBufferStreamS-super - created by 'cls_MqS.tcl -i NHI1_HOME/theKernel/libmkkernel/.libmkkernel.meta' - DO NOT change
// instance attributes
struct {
MK_NUM numItems; // the number of items in the package
MK_INT undo; // \e undo last operation: read=+1 < no=0 < write=-1)
// \note The \e endian_is_wrong attribute is required if a \RMkBufferStreamC is send to
// an other host. The \e sender-endian is part of the \e package-header and the \e reader is using
// the information from the \e package-header to setup the \e endian_is_wrong attribute.
// \li \b false (0) if the endian is the \b same as the local endian.
// \li \b true (1) if the endian is \b not the same as the local endian.
// If \e endian_is_wrong is \b true the package header transform the native-binary-package-data
// to the local endian as part of the \RDocMqA{ReadTT} and \RDocNsA{BufferStreamReadTT} methods.
// The transformation of native data is \b only done if required, just \e routing of a package
// does \b not require a transformation.
bool endian_is_wrong; // the value: \e TRUE if endian of storage != \c MK_ENDIAN_MY
} var; // variable part of the \e instance-data
struct {
union MkBufferU cur;
} storage; // storage part of the \e instance-data
// BUG FIX don't put busRef into "var" -> the pMkBusReadL_END will "overwrite" the data including the
// "self" pointer
struct MkBuffer64S busRef; // pBusReadNextWord will fill this
struct MkCacheS saveCache; // cache to support recursion in LST sub-package
struct MkBufferStreamSaveS * busWriteSave; // if \b not NULL than an active LST-WRITE is ongoing
struct MkBufferStreamSaveS * busReadSave; // if \b not NULL than an active LST-READ is ongoing
#define MkBufferStreamS_ils_size 0 // \e ILS size
};
int32_t MK_NUM
unsigned char MK_BINB
signed int MK_INT
#define MkBufferStreamS_ils_size
struct MkBuffer64S busRef
union MkBufferU cur
union MkBufferStreamS::@8 super
struct MkBufferStreamS::@9 var
struct MkBufferStreamSaveS * busReadSave
struct MkBufferStreamS::@10 storage
struct MkObjectS obj
MK_BINB ils_data[MkBufferStreamS_ils_size]
struct MkBufferS buf
struct MkBufferStreamSaveS * busWriteSave
struct MkCacheS saveCache

The class MkBufferStreamS is an abstract class, since the instant-local-storage MkBufferStreamS_ils_size is "0".
The abstract class implements all of the methods, but have to be superordinated to the final-class.

MkObjectSMkBufferSMkBufferStreamS

In the case of MkBufferStreamS the final-classes are:

MkBufferStream16384S, MkBufferStream256S and MkBufferStream64S

SUPERCLASS

MkObjectC_Obj_C_API

Example from kernel_mk.h The superclass definition is a union over all base-classes up to MkObjectC

// BEGIN-MkBufferStreamS-super - created by 'cls_MqS.tcl -i NHI1_HOME/theKernel/libmkkernel/.libmkkernel.meta' - DO NOT change
union {
struct MkObjectS obj; // base CLASS \MkObjectS
struct MkBufferS buf; // base CLASS \MkBufferS
} super;
// END-MkBufferStreamS-super - created by 'cls_MqS.tcl -i NHI1_HOME/theKernel/libmkkernel/.libmkkernel.meta' - DO NOT change

Two compile-time-casts from the abstract class MkBufferStreamS are valid:

  1. The cast to MkObjectS (MK_OBJ): &BufferStreamPtr->super.obj == MkOBJ(BufferStreamPtr)
  2. The cast to MkBufferS (MK_BUF): &BufferStreamPtr->super.buf == MkBUF(BufferStreamPtr)

There is also a redundant cast:

  • &BufferStreamPtr->super.obj == &BufferStreamPtr->super.buf.super.obj

The reason is that MkBufferS is also an managed-object and has the attribute super.obj.

‍For every managed-object the cast &pointer->super.obj always exists.

The both names obj and buf are no concidence, the MANAGED OBJECT uses for class-lookup the short-name from the defined-namespace.

C-struct class class-prefix C-short runtime-cast compile-time-cast short-name long-name
void* MK_MNG mng
struct MkObjectS MkObjectC Object MK_OBJ MkObj MkOBJ obj object
struct MkBufferS MkBufferC Buffer MK_BUF MkBuf MkBUF buf buffer
struct MkBufferStreamS MkBufferStreamC BufferStream MK_BUS MkBus MkBUS bus stream
struct MkBufferListS MkBufferListC BufferList MK_BFL MkBfl MkBFL bfl buffer-list
struct MkLogFileS MkLogFileC LogFile MK_LFL MkLfl MkLFL lfl log-file
struct MkErrorS MkErrorC Error MK_ERR MkErr MkERR err error
struct MkRuntimeS MkRuntimeC Runtime MK_RT MkRt MkRT rt runtime

The MK_MNG is a special pointer, and is used to store a managed-object pointer to a location outside the kernel with its garanteed validity.

‍The goal is to always soft-cast an MK_MNG pointer to a valid managed-object pointer.