A subcomponent-free data
component should contain a
ARAO::data_type
property in order to generate the corresponding
Ada type. ARAO predefined types are : integer
, float
,
null
, string
and boolean
. Normal data components are
mapped to the related Ada type, as seen in the following AADL example
:
data message properties ARAO::data_type => integer; end message;
is mapped to the following Ada95 code:
type message is new Integer;
AADL data
component implementations may contain others data
subcomponents. In this case, the data
component is mapped to an
Ada record type.
As an example, the following AADL component implementation:
data integer_type properties ARAO::data_type => integer; end integer_type; data structure end structure; data implementation structure.impl subcomponents d1 : data integer_type; d2 : data integer_type; end structure.impl;
is mapped to the following Ada code :
type Integer_Type is new Integer; type Structure_Impl is record D1 : Integer_Type; D2 : Integer_Type; end record;
AADL protected data
components must be declared in the same way
composed types are, i.e. by encapsulating them within another AADL type
declaration.
For each protected data
components, a new type is declared which
contains all data components (i.e. fields of the related composed type)
plus a mutex object within a Ada record. As for composed types, all
fields must be either a previously user-declared type or a ARAO base
type. Accessors and building features for the type will be declared
too, as for the data-owned procedures (“methods”) designated in the
features
part of the data
component.
The generated code enforces access protection, and declare type's
object-oriented procedures (“methods”, as defined by user), using
the middleware mutexes. A “method” of a type must always has as
features
a requires data access
on this data.
For example, the following AADL declaration :
data internal_message properties ARAO::data_type => integer; end internal_message; data message subcomponents Field : data internal_message; features method : subprogram update; properties ARAO::Access_Control_Protocol => Protected_Access; end message;
would generate a code like this :
package Partition is type Message is private; procedure Build (This : out Message); procedure Get_Data (This : in Message; Value : out Internal_Message); procedure Set_Data (This : in out Message; Value : in Internal_Message); private type Message is record Data : Partition.Internal_Message; Mutex : PolyORB.Tasking.Mutexes.Mutex_Access; end record; end Partition;
and the update
method which will be call by generated code is like this :
procedure Update (This : in out Message; Value : in Partition.Internal_Message) is begin PolyORB.Tasking.Mutexes.Enter (This.Mutex); Repository.Update (This, Value); PolyORB.Tasking.Mutexes.Leave (This.Mutex); end Update;
Where the procedures Enter
and Leave
are middleware mutexes'
take
and release
procedures.
We define protected data type internal type as the components
(usually only one) , excluding the mutex, which are embedded in a
protected type as a subcomponent
. The protected data type
internal type could be either a protected type or a “normal”
(non-protected) type. Eventually, all protected types can be
decomposed in a set of basic types.
Data accessors can be used by the user exactly as data-owned procedure are. In the current version, they are the only ones actually called by the PolyORB AADL runtime, contrary to the generated interfaces which are not called at all.
Protected type accessors include Set_X
and Get_X
Ada
procedures, where X
is the name of the Field which contains the
real (internal) data type. Those procedures are access-protected,
using the protected object's middleware mutex to ensure mutual
exclusion. The Build
procedure will ensure mutex
initialization.
An example of safe usage of accessors is :
----------------------- -- Concurrent_Update -- ----------------------- procedure Concurrent_Update (arg : in out Partition.Counter_Type) is Sum : Partition.Integer_Type; begin -- data initialization Partition.Set_Field (Data, 0); for I in 0 .. 100 loop Partition.Increment (Data); Partition.Get_Field (Data, Sum); if Integer (Sum) = 100 then exit; end if; end loop; end Concurrent_Update;
relying on the following AADL declarations :
data Integer_Type properties ARAO::data_type => integer; end Integer_Type; data Counter_Type features Increment : subprogram Increment; subcomponents field : data Integer_Type; properties Concurency_Control_Protocol => Protected_Access; end Counter_Type; subprogram Increment features this : requires data access Counter_Type; properties source_language => Ada95; source_name => "Repository"; end Increment; subprogram Concurrent_Update features arg : requires data access Counter_Type; properties source_language => Ada95; source_name => "Repository"; end Concurrent_Update; thread Task features sh_data : requires data access Counter_Type; properties Dispatch_Protocol => Periodic; Period => 1000 Ms; end Task; thread implementation Task.impl calls { sp1 : subprogram Concurrent_Update; }; connections Cnx_Th_dat : data access sh_data -> sp1.arg; end Task.impl; process implementation global.impl subcomponents th1 : thread Task.impl; th2 : thread Task.impl; dat : data Counter_Type; connections Cnx_1 : data access dat -> th1.sh_data; Cnx_2 : data access dat -> th2.sh_data; end global.impl;
with the following package specification and body generated :
package Partition is type Integer_Type is new Integer; type Counter_Type is private; procedure Build (This : out Partition.Integer_Type); procedure Get_Field (This : in Message; Value : out Partition.Integer_Type); procedure Set_Field (This : in out Message; Value : in Partition.Integer_Type); procedure Increment (This : in out Counter_Type); private type Counter_Type is record Field : Partition.Integer_Type; Mutex : PolyORB.Tasking.Mutexes.Mutex_Access; end record; end Partition;
with Repository; package body Counter_Type_PKG is ----------- -- Build -- ----------- procedure Build (This : out Message) is begin -- Initialize the middleware's mutex PolyORB.Tasking.Mutexes.Create (T.Mutex); end Build; --------------- -- Get_Field -- --------------- procedure Get_Field (This : in Counter_Type; Value : out Partition.Integer_Type) is begin PolyORB.Tasking.Mutexes.Enter (T.Mutex); Value := This.Field; PolyORB.Tasking.Mutexes.Leave (T.Mutex); end Get_Field; --------------- -- Set_Field -- --------------- procedure Set_Field (This : in out Counter_Type; Value : in Partition.Integer_Type) is begin PolyORB.Tasking.Mutexes.Enter (T.Mutex); This.Field := Value; PolyORB.Tasking.Mutexes.Leave (T.Mutex); end Set_Field; --------------- -- Increment -- --------------- procedure Increment (This : in out Counter_Type) is begin PolyORB.Tasking.Mutexes.Enter (This.Mutex); Repository.Increment (This.Field); PolyORB.Tasking.Mutexes.Leave (This.Mutex); end Increment; end Counter_Type_PKG;
Note that the Set
usage could had been replaced by an
Initialization
method of Counter_Type, and that the Get
could
had been replaced by a Test_Value
method.
We have seen that in the translation phase, the AADL data components
are mapped to Ada95 types. Since the communication between nodes is
performed using the PolyORB tools, all data sent in a request must
have the neutral type PolyORB.Any.Any
. So, conversion functions
from and to this neutral type must be generated. For a process named
proc
these conversion functions will be generated in the
proc_Helpers
package. Example:
data message properties ARAO::data_type => integer; end message;
is a definition for an integer type, the conversion routines generated
in proc_Helpers
are:
with Partition; with PolyORB.Any; package proc_helpers is -- TypeCode variable used to characterize an Any variable TC_message : PolyORB.Any.TypeCode.Object := PolyORB.Any.TypeCode.TC_Alias; function From_Any (Item : in PolyORB.Any.Any) return Partition.message; function To_Any (Item : in Partition.message) return PolyORB.Any.Any; end proc_helpers;
Note that we use the Namespaces
package created in the translation
phase.
Available properties for data components can be found in SAE AS5506, in 5.1 page 50 and in Appendix A, pages 197-218.
Concurency_control_protocol | Supported : None, Access_Protected
|
Not_Collocated | Not Supported
|
Provided_Access | Not Supported
|
Required_Access | Not Supported
|
Source_Code_Size | Not Supported
|
Source_Language | Not Supported
|
Source_Name | Not Supported
|
Source_Text | Not Supported
|
Type_Source_Name | Not Supported
|