Difference between revisions of "Uno/Article/Working with Environments, Mappings & Objects"

From Apache OpenOffice Wiki
< Uno
Jump to: navigation, search
m (Practice)
m (Minor wording fixes.)
Line 14: Line 14:
 
* [[Uno/Spec/Mapping|mappings]], basically connecting environments, to bring objects from one world to another, and certainly  
 
* [[Uno/Spec/Mapping|mappings]], basically connecting environments, to bring objects from one world to another, and certainly  
 
* objects, for doing implementations.
 
* objects, for doing implementations.
All of these three entities (environments, mappings, objects) are dynamically extendable.
+
The sets of available implementations of all of these three entities (environments, mappings, objects) are dynamically extendable.
  
 
===Environments===
 
===Environments===
Line 20: Line 20:
 
* manage a set of objects, sharing some characteristics as the [[Uno/Term/Object Binary Interface|Binary Interface (OBI)]] or the "purpose", and
 
* manage a set of objects, sharing some characteristics as the [[Uno/Term/Object Binary Interface|Binary Interface (OBI)]] or the "purpose", and
 
* control the life cycle of any particular object belonging to an environment.
 
* control the life cycle of any particular object belonging to an environment.
Environments are addressed by environments descriptors,
+
Environments are addressed by environment descriptors, e.g.
 
<pre>
 
<pre>
 
"<OBI>[:purpose]*"
 
"<OBI>[:purpose]*"
 
</pre>
 
</pre>
composed of the [[Uno/Term/Object Binary Interface|OBI]] and zero or multiple purposes.
+
An environment descriptor is basically composed of the [[Uno/Term/Object Binary Interface|OBI]] and zero or multiple purposes.
  
 
Examples for environments are:
 
Examples for environments are:
Line 47: Line 47:
  
 
====Life Cycle====
 
====Life Cycle====
Every environment is Uno runtime wide unique and global. Re-requesting a particular environment (e.g. <code>"uno:unsafe"</code>) multiple times, always returns the '''same''' instance. An environments identity is uniquely derived from its description. An environment exists as long as an object or proxy is registered or an explicit reference is kept.
+
Every environment is Uno runtime wide unique and global. Re-requesting a particular environment (e.g. <code>"uno:unsafe"</code>) multiple times, always returns the '''same''' instance. An environments identity is the same as its description. An environment exists as long as an object or proxy is registered or an explicit reference is kept.
  
 
====Activation====
 
====Activation====
Environments may be activated either directly by being '''entered''', or indirectly by being '''invoked'''. Depending on the particular environment, semantics might differ slightly. Environments may control some global state, which they may alter in response to activation.
+
Environments may be activated either directly by being '''entered''', or indirectly by being '''invoked'''. Depending on the particular purposes, semantics might differ slightly. Environments may control some global state, which may be altered in response to activation.
  
 
As only [[Uno/Spec/Purpose Environment|purpose environments]] control any state, their is actually no difference between activating two environments with different object [[Uno/Term/Object Binary Interface|OBI]]s but with the same purpose:
 
As only [[Uno/Spec/Purpose Environment|purpose environments]] control any state, their is actually no difference between activating two environments with different object [[Uno/Term/Object Binary Interface|OBI]]s but with the same purpose:
Line 60: Line 60:
  
 
====Integrity====
 
====Integrity====
Direct manipulation (e.g. casting and calling) of an object of a particular environment '''must''' only be done, while the managing environment has been activated. In contrast, indirect manipulation, e.g. through the managing environment, is guaranteed to always be safe.
+
Direct manipulation (e.g. casting and calling) of an object of a particular environment '''must''' only be done, while the managing environment has been activated. In contrast, indirect manipulation, e.g. through the managing environment or a proxy, is guaranteed to always be safe.
 +
 
 +
Every object belongs to exactly one environment only.
  
 
Objects of different environments, even having the same [[Uno/Term/Object Binary Interface|OBI]], must '''never''' be mixed, otherwise [[Uno/Term/Environment Integrity|environment integrity]] may break (e.g. leading to a [[Uno/Term/Thread Safe|thread-safe]] object providing the same [[Uno/Term/Thread Unsafe|thread-unsafe]] object to multiple threads).
 
Objects of different environments, even having the same [[Uno/Term/Object Binary Interface|OBI]], must '''never''' be mixed, otherwise [[Uno/Term/Environment Integrity|environment integrity]] may break (e.g. leading to a [[Uno/Term/Thread Safe|thread-safe]] object providing the same [[Uno/Term/Thread Unsafe|thread-unsafe]] object to multiple threads).
Line 72: Line 74:
 
====Naming====
 
====Naming====
 
Environment naming has not been implemented for any Uno runtime yet. Naming is going to allow to have multiple environments of the same type, e.g.
 
Environment naming has not been implemented for any Uno runtime yet. Naming is going to allow to have multiple environments of the same type, e.g.
  <code>"gcc3:unsafe;impl_one"</code>
+
  <code>"gcc3:unsafe;first_instance"</code>
 
or
 
or
  <code>"gcc3:unsafe;impl_two"</code>
+
  <code>"gcc3:unsafe;second_instance"</code>
This is going to enable the instantiation of different components implemented in the same [[Uno/Term/Object Binary Interface|OBI]] and requiring the same purposes into independent environments. E.g. two [[Uno/Term/Thread Unsafe|thread-unsafe]] C++ components may be invoked in parallel, despite both being implemented as <code>"C++:unsafe"</code>. It is also going to enable logging e.g. of inter-component calls of any two components.
+
This is going to enable the instantiation of different components implemented in the same [[Uno/Term/Object Binary Interface|OBI]] and requiring the same purposes into independent environments. E.g. two [[Uno/Term/Thread Unsafe|thread-unsafe]] C++ components may be instantiated into two independent <code>"gcc3:unsafe"</code> environments, allowing to be invoked in parallel, despite both being implemented as <code>"C++:unsafe"</code>. This is also going to enable logging e.g. of inter-component calls of any two components.
  
 
====Parameters====
 
====Parameters====
Line 92: Line 94:
  
 
====Implementations====
 
====Implementations====
Mappings are backed by mapping implementations, actually mapping implementations are purpose independent, and only map from one [[Uno/Term/Object Binary Interface|OBI]] to another. As in most cases it is needed to map back and forth, mappings are mostly implemented as bridges.
+
Mappings are backed by mapping implementations, actually mapping implementations are purpose independent, and only map from one [[Uno/Term/Object Binary Interface|OBI]] to another. As in most cases it is needed to map back and forth, mappings are mostly implemented as bridges ("bi-directional mappings").
  
 
====Cascading====
 
====Cascading====
Line 104: Line 106:
  
 
====Life Cycle====
 
====Life Cycle====
Mappings live as long as objects are mapped. Releasing the last mapped object also releases the mapping. Re-requesting a particular mapping (e.g. <code>"uno:unsafe"</code> -> <code>"uno"</code>) multiple times, always returns the '''same''' instance.
+
Mappings live as long as objects are mapped or an explicit reference is hold. Releasing the last mapped object and the last explicit reference also releases the mapping. Re-requesting a particular mapping (e.g. <code>"uno:unsafe"</code> -> <code>"uno"</code>) multiple times, always returns the '''same''' instance.
  
 
===Objects===
 
===Objects===
Objects are the third stand in the Uno architecture. Where environments deal with the management of objects, while mappings know how to forward a particular object from one [[Uno/Term/Object Binary Interface|OBI]] to another, objects are the functional parts.
+
Objects are the third stand in the [[Uno]] architecture. Where environments deal with the management of objects, while mappings know how to forward a particular object from one [[Uno/Term/Object Binary Interface|OBI]] respectively purpose to another, objects are the functional parts.
  
 
====Implementations====
 
====Implementations====
 
Basically, (Uno) objects may be implemented anywhere, in components, in libraries, in applications or in the network. Accessing and creating Uno objects solely through other Uno objects guarantees [[Uno/Term/Environment Integrity|environment integrity]]. Unfortunately, only Uno components ensure the by-object-only access, while applications, libraries and network sockets may very well by-pass this. Therefor precautions need to be taken, to still ensure that [[Uno/Term/Environment Integrity|environmental integrity]] can not break.
 
Basically, (Uno) objects may be implemented anywhere, in components, in libraries, in applications or in the network. Accessing and creating Uno objects solely through other Uno objects guarantees [[Uno/Term/Environment Integrity|environment integrity]]. Unfortunately, only Uno components ensure the by-object-only access, while applications, libraries and network sockets may very well by-pass this. Therefor precautions need to be taken, to still ensure that [[Uno/Term/Environment Integrity|environmental integrity]] can not break.
  
'''Specialization:''' Libraries as well as applications, may be implemented from '''environment-specialized''' to '''environment-any''', partly specialization being possible, e.g.
+
'''Specialization:''' Libraries as well as applications, may be implemented as '''environment-specialized''', as '''environment-any''', or something in between, e.g.
* a function taking and returning <code>"uno"</code> objects only is specialized on the <code>"uno"</code> environment,
+
* a function accepting and returning <code>"uno"</code> objects only is specialized on the <code>"uno"</code> environment,
* a function taking and returning <code>"gcc3:unsafe"</code> objects only is specialized on the <code>"gcc3:unsafe"</code> environment,
+
* a function acceptiong and returning <code>"gcc3:unsafe"</code> objects only is specialized on the <code>"gcc3:unsafe"</code> environment,
* a function taking and returning <code>"gcc3[:<purpose>]*"</code> objects only is partly specialized, namely on the GCC3 C++ [[Uno/Term/Object Binary Interface|OBI]], only,
+
* a function accepting and returning <code>"gcc3[:<purpose>]*"</code> objects only is partly specialized, namely on the GCC3 C++ [[Uno/Term/Object Binary Interface|OBI]], only,
* a function taking and returning <code>"<OBI>[:<purpose>]*"</code> objects is basically able to deal with any kind of objects, it is therefor environment-any.
+
* a function accepting and returning <code>"<OBI>[:<purpose>]*"</code> objects is basically able to deal with any kind of objects, it is not specialized at all and is therefor environment-any.
  
 
'''Mapping:''' Actually, any environment-specialized library (or function) can easily be wrapped into any other kind of environment-specialization, as long as the necessary mapping is available. Hence, exactly this is what the Uno runtime does automatically, in case Uno objects are used.
 
'''Mapping:''' Actually, any environment-specialized library (or function) can easily be wrapped into any other kind of environment-specialization, as long as the necessary mapping is available. Hence, exactly this is what the Uno runtime does automatically, in case Uno objects are used.
Line 122: Line 124:
 
'''Type Safety:''' Depending on the capabilities of the particular programming language and language binding, correct dealing with environment-specialization may be enforced at compilation time, e.g. by dedicated reference types. Actually, it is recommended to use the most specific type as possible, or, the other way around, to be as specialized as the API only, unfortunately this is not always possible because of missing language-feature support.
 
'''Type Safety:''' Depending on the capabilities of the particular programming language and language binding, correct dealing with environment-specialization may be enforced at compilation time, e.g. by dedicated reference types. Actually, it is recommended to use the most specific type as possible, or, the other way around, to be as specialized as the API only, unfortunately this is not always possible because of missing language-feature support.
  
An environment-any or partly -specialized library (or function) needs to request the missing information from the [[Uno/Spec/Runtime|runtime]], this may be done by invoking the [[Uno/Spec/Environment_Stack|getCurrentEnvironment]] [[Uno/Spec/Runtime|runtime]] function.
+
An environment-any or partly -specialized library (or function) needs to request the lacking information at runtime, from the Uno [[Uno/Spec/Runtime|runtime]], this may be done by invoking the [[Uno/Spec/Environment_Stack|getCurrentEnvironment]] [[Uno/Spec/Runtime|runtime]] function.
  
'''Note:''' Unfortunately, no type safe [[Uno/Term/Purpose Reference|purpose aware references]] are yet available for any [[Uno]] language binding. So, this is planned.
+
{{Uno/Note}} Unfortunately, no type safe [[Uno/Term/Purpose Reference|purpose aware references]] are yet available for any [[Uno]] language binding. So, this is planned.
  
'''Note:''' It is planned, to support the selection of an [[Uno/Spec/Implementation Environment|implementation environment]], determining an implementations [[Uno/Term/Object Binary Interface|OBI]] and purpose environment at compile time, e.g. for 'C' like languages by a macro or an include. Some experiments have been done, so no final decisions have been made yet.
+
{{Uno/Note}} It is planned, to support the selection of an [[Uno/Spec/Implementation Environment|implementation environment]], determining an implementations [[Uno/Term/Object Binary Interface|OBI]] and purpose environment at compile time, e.g. for 'C' like languages by a macro or an include. Some experiments have been done, so no final decisions have been made yet.
  
 
====Life Cycle====
 
====Life Cycle====

Revision as of 13:13, 27 September 2006

Environments, mappings and objects are at the heart of Uno. Understanding their relationship and how to use them is fundamental for understanding how Uno

  • transparently integrates different programming languages,
  • achieves remote transparency,
  • allows to trace one or multiple components objects,
  • provides well defined back-doors for optimization purposes,
  • can implicitly handle contexts (such as the "ComponentContext"),
  • protects thread-unsafe objects,
  • isolates thread-affine objects,

and more.

Theory

The three entities are

  • environments for managing objects,
  • mappings, basically connecting environments, to bring objects from one world to another, and certainly
  • objects, for doing implementations.

The sets of available implementations of all of these three entities (environments, mappings, objects) are dynamically extendable.

Environments

Environments are fundamental to Uno. Environments

  • manage a set of objects, sharing some characteristics as the Binary Interface (OBI) or the "purpose", and
  • control the life cycle of any particular object belonging to an environment.

Environments are addressed by environment descriptors, e.g.

"<OBI>[:purpose]*"

An environment descriptor is basically composed of the OBI and zero or multiple purposes.

Examples for environments are:

  • "uno" - the environment managing Binary Uno standard OBI objects,
  • "gcc3" - the environment managing GCC3 C++ OBI objects,
  • "uno:unsafe" - the environment managing Binary Uno standard OBI thread-unsafe objects,
  • "jni:affine" - the environment managing JNI (Java Native Interface) OBI thread-affine objects.
  • "jni:affine:debug" - the environment managing JNI (Java Native Interface) OBI thread-affine debug objects.

Two Types

Environments requested from the Uno runtime are actually linear combined from exactly one OBI and zero or multiple purpose environments. E.g.

"gcc3:unsafe"

is backed by the GCC3 OBI environment implementation and the "unsafe" purpose environment implementation.

Environments having a purpose in their descriptors are actually called purpose environments, other environments may be called pure or pure OBI.

OBI Environment Implementations

OBI environment implementations do not control any state and are solely managing objects of a particular OBI.

Purpose Environment Implementations

Purpose environment implementations typically only manage objects of a standard (in Binary Uno the "UNO") OBI, but do control state. Purpose environments alter their state when being activated respectively deactivated.

Life Cycle

Every environment is Uno runtime wide unique and global. Re-requesting a particular environment (e.g. "uno:unsafe") multiple times, always returns the same instance. An environments identity is the same as its description. An environment exists as long as an object or proxy is registered or an explicit reference is kept.

Activation

Environments may be activated either directly by being entered, or indirectly by being invoked. Depending on the particular purposes, semantics might differ slightly. Environments may control some global state, which may be altered in response to activation.

As only purpose environments control any state, their is actually no difference between activating two environments with different object OBIs but with the same purpose:

"gcc3:unsafe"
"uno:unsafe"

Consequently, entering a "pure" OBI environment, such as "gcc3", has no effect at all.

Integrity

Direct manipulation (e.g. casting and calling) of an object of a particular environment must only be done, while the managing environment has been activated. In contrast, indirect manipulation, e.g. through the managing environment or a proxy, is guaranteed to always be safe.

Every object belongs to exactly one environment only.

Objects of different environments, even having the same OBI, must never be mixed, otherwise environment integrity may break (e.g. leading to a thread-safe object providing the same thread-unsafe object to multiple threads).

Substitution

Environments may be substituted with compatible environments. Environments are compatible if the to be substituted environments descriptor is a prefix of the substitutes descriptor, e.g.

"uno:unsafe" 

may be substituted with

"uno:unsafe:debug"

Naming

Environment naming has not been implemented for any Uno runtime yet. Naming is going to allow to have multiple environments of the same type, e.g.

"gcc3:unsafe;first_instance"

or

"gcc3:unsafe;second_instance"

This is going to enable the instantiation of different components implemented in the same OBI and requiring the same purposes into independent environments. E.g. two thread-unsafe C++ components may be instantiated into two independent "gcc3:unsafe" environments, allowing to be invoked in parallel, despite both being implemented as "C++:unsafe". This is also going to enable logging e.g. of inter-component calls of any two components.

Parameters

Environment parameters have not been implemented yet. Environment parameters are essential for things as simplifying remote access (see Uno/Todo#Features). Environment parameters may look like this:

"remote[socket,host=0,port=12345;urp]"

which would pass the string

"socket,host=0,port=12345;urp"

to the remote environment implementation.

Environment parameters could be passed to any OBI or purpose named in the environment descriptor, e.g.

"remote[socket,host=0,port=12345;urp]:debug[logfile=<filename>.log]"

would log all calls to the remote objects to the named log file.

Mappings

Mappings connect any two particular environments in a way, that an object of the source environment may be "mapped" to the destination environment, actually providing a representation of the source object in terms of the destination environment.

Implementations

Mappings are backed by mapping implementations, actually mapping implementations are purpose independent, and only map from one OBI to another. As in most cases it is needed to map back and forth, mappings are mostly implemented as bridges ("bi-directional mappings").

Cascading

A mapping may not only be direct, but may very well be composed of multiple "smaller" mappings. E.g. if the Binary Uno runtime can not find any direct mapping, it tries to concatenate multiple mappings. See the cascaded mapping specification for details.

The following mapping

"gcc3" -> "gcc3:unsafe" 

gets actually composed as

"gcc3" -> "uno" -> "uno:unsafe" -> "gcc3:unsafe"

Life Cycle

Mappings live as long as objects are mapped or an explicit reference is hold. Releasing the last mapped object and the last explicit reference also releases the mapping. Re-requesting a particular mapping (e.g. "uno:unsafe" -> "uno") multiple times, always returns the same instance.

Objects

Objects are the third stand in the Uno architecture. Where environments deal with the management of objects, while mappings know how to forward a particular object from one OBI respectively purpose to another, objects are the functional parts.

Implementations

Basically, (Uno) objects may be implemented anywhere, in components, in libraries, in applications or in the network. Accessing and creating Uno objects solely through other Uno objects guarantees environment integrity. Unfortunately, only Uno components ensure the by-object-only access, while applications, libraries and network sockets may very well by-pass this. Therefor precautions need to be taken, to still ensure that environmental integrity can not break.

Specialization: Libraries as well as applications, may be implemented as environment-specialized, as environment-any, or something in between, e.g.

  • a function accepting and returning "uno" objects only is specialized on the "uno" environment,
  • a function acceptiong and returning "gcc3:unsafe" objects only is specialized on the "gcc3:unsafe" environment,
  • a function accepting and returning "gcc3[:<purpose>]*" objects only is partly specialized, namely on the GCC3 C++ OBI, only,
  • a function accepting and returning "<OBI>[:<purpose>]*" objects is basically able to deal with any kind of objects, it is not specialized at all and is therefor environment-any.

Mapping: Actually, any environment-specialized library (or function) can easily be wrapped into any other kind of environment-specialization, as long as the necessary mapping is available. Hence, exactly this is what the Uno runtime does automatically, in case Uno objects are used.

Type Safety: Depending on the capabilities of the particular programming language and language binding, correct dealing with environment-specialization may be enforced at compilation time, e.g. by dedicated reference types. Actually, it is recommended to use the most specific type as possible, or, the other way around, to be as specialized as the API only, unfortunately this is not always possible because of missing language-feature support.

An environment-any or partly -specialized library (or function) needs to request the lacking information at runtime, from the Uno runtime, this may be done by invoking the getCurrentEnvironment runtime function.

Note: Unfortunately, no type safe purpose aware references are yet available for any Uno language binding. So, this is planned.

Note: It is planned, to support the selection of an implementation environment, determining an implementations OBI and purpose environment at compile time, e.g. for 'C' like languages by a macro or an include. Some experiments have been done, so no final decisions have been made yet.

Life Cycle

An objects life cycle may depend on the base system, systems without garbage collection typically use reference counting, while systems with garbage collection keep objects alive as long as they are referenced only.

Invocation

An object may only be invoked, if the managing environment has been activated. Typically, a cast precedes the concrete invokation of an object.

Practice

So, you may ask yourself, having read the above, what exactly can you do with this stuff?! Actually, the combination of environments, mappings and objects is very powerful.

Environments

Helpers

  • Environment Guards
  • Environment AntiGuards
  • Environment Aware Reference
  • Purpose Environment Implementation Helper

C++ Example - Requesting an Environment

[Cpp] uno::Environment env(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("c++:unsafe"))); ====C++ Exmaple

Mappings

Helpers

  • Mappers

Objects

C++ Example - Function always returning an appropriate object

The following example shows a function always returning an appropriate (correct OBI and purpose) object of type XInterface. For this function to work properly, the client must have activated the appropriate environment, as the uno::Reference is only partly (namely OBI) specialized.

Callee: [cpp] // This function is environment specialized on "c++<purpose>*". uno::Reference<uno::XInterface> create_appropriateObject(void) {

 uno:Reference<uno::XInterface> result_Obj;
 // We may want to open a new scope, to ensure that "result_Obj" does
 // not get destructed while "c++:unsafe" is active.
 {
   // We need to remember the callers environment, to "map-out/in"
   // the parameters and return values properly.
   uno::Environment outerEnv(uno::getCurrent());
   // We activate (enter) the "c++:unsafe" environment.
   // Note: Any other environment suiteable for "MyUnsafeObject" would work as well.
   cppu::EnvGuard unsafeGuard(uno::Environment(rtl::OUString(RTL_CONSTASCII_UPARAM("c++:unsafe"))));
   // This reference points to a "thread-unsafe" object.
   Reference<uno::XInterface> unsafeEnv_Obj(new MyUnsafeObject());
   // We may do some activations on "unsafeEnv_Obj".
   unsafeEnv_Obj->doThis();
   unsafeEnv_Obj->doThat();
   // We "mapOut" the object and assign it to "result_Obj".
   result_Obj.set(cppu::mapOut(unsafeEnv_Obj, outerEnv), SAL_NO_ACQUIRE);
   // We may _not_ activate result_obj, as we are still in the "c++:unsafe" environment.
   // The unsafeEnv_Obj reference gets destructed here, actually calling the "release" method in the right environment.
   // The unsafeGuard gets destructed here, deactivating the "c++:unsafe" environment.
 }
 // Using "result_obj" is "safe" here.
 return result_Obj;

}

Caller: [cpp] ... {

 // Whatever "c++<purpose>*" we enter, the result of "create_appropriateObject" will 
 // always match.
 cppu::EnvGuard cppDebug_Guard(rtl::OUString(RTL_CONSTASCII_PARAM("c++:debug")));
 uno::Reference obj(create_appropriateObject());

} ...

C++ Example - Function accepting any kind parameters

In the following example, the called function gets a parameter, which needs to be mapped appropriately to the "c++:unsafe" environment, to be able to pass a thread-unsafe object to the set method of the parameter. For the function to work properly, the client must have activated the appropriate environment, as the uno::Reference is only partly (namely OBI) specialized.

Callee: [cpp] // This function is environment specialized on "c++<purpose>*". void takeAnyObject(uno::Reference<...> const & rObj) {

 // We need to remember the callers environment, to "map-out/in"
 // the parameters and return values properly.
 uno::Environment outerEnv(uno::getCurrent());
 // We now activate (enter) the "c++:unsafe" environment.
 // Note: Any other environment suiteable for "MyUnsafeObject" would work as well.
 cppu::EnvGuard unsafeGuard(uno::Environment(rtl::OUString(RTL_CONSTASCII_PARAM("c++:unsafe"))));
 // We "mapIn" the parameter.
 uno::Reference<...> unsafeEnv_Obj.set(cppu::mapIn(rObj, outerEnv), SAL_NO_ACQUIRE);
 // MyUnsafeObj has a C++ OBI and is thread-unsafe
 unsafeEnv_Obj->set(new MyUnsafeObject());

}

Caller: [cpp] ... {

 // Whatever "c++<purpose>*" we enter, the parameter passed to "takeAnyObject" will
 // always match.
 cppu::EnvGuard cppDebug_Guard(rtl::OUString(RTL_CONSTASCII_PARAM("c++:debug")));
 uno::Reference<...> obj(...);
 takeAnyObject(obj);

} ...

Personal tools