1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/docs/wiki/Clients Sun Apr 26 18:25:12 2020 +0200
1.3 @@ -0,0 +1,122 @@
1.4 += Clients =
1.5 +
1.6 +Client code is code that accesses the facilities of components as described by
1.7 +those components' interfaces, potentially via interprocess communications
1.8 +mechanisms. Given an interface description featuring component operations,
1.9 +code may be written to invoke these operations and to treat the component as
1.10 +if it resides in the same program.
1.11 +
1.12 +<<TableOfContents(2)>>
1.13 +
1.14 +== Introduction ==
1.15 +
1.16 +The following example interface, resident in a file called `calc.idl`, will be
1.17 +used to illustrate the mechanisms described in this document:
1.18 +
1.19 +{{{
1.20 +interface Calc
1.21 +{
1.22 + void add(in int left, in int right, out int result);
1.23 + void subtract(in int left, in int right, out int result);
1.24 + void multiply(in int left, in int right, out int result);
1.25 + void divide(in int numerator, in int denominator, out int result);
1.26 +};
1.27 +}}}
1.28 +
1.29 +To use this interface, a client program would do the following:
1.30 +
1.31 + * Obtain appropriate program types to reference the interface
1.32 +
1.33 + * Initialise values or objects that reference the component providing the
1.34 + interface
1.35 +
1.36 + * Invoke operations provided by the interface, thus interacting with the
1.37 + component
1.38 +
1.39 +The sections below describe how this is done in the different supported
1.40 +programming languages.
1.41 +
1.42 +Note that the mechanism by which interface descriptions are processed for use
1.43 +in programs is described in the [[L4Re Support]] document. The `idl` manual
1.44 +page provides details for developers wishing to use the tool directly.
1.45 +
1.46 +== Client Header Files ==
1.47 +
1.48 +Given the existence of generated files for the interface, a program would
1.49 +include the client header file:
1.50 +
1.51 +{{{
1.52 +#include "calc_client.h"
1.53 +}}}
1.54 +
1.55 +== C Language Clients ==
1.56 +
1.57 +An object representing the component will have the `Calc` type. This
1.58 +encapsulates a reference to the object state and a reference to the interface
1.59 +details.
1.60 +
1.61 +The object state can be populated using a capability in L4Re:
1.62 +
1.63 +{{{
1.64 +ref_Calc ref = {.cap=server};
1.65 +}}}
1.66 +
1.67 +However, the state of a local object would be populated using a pointer:
1.68 +
1.69 +{{{
1.70 +ref_Calc ref = {.ptr=local_state};
1.71 +}}}
1.72 +
1.73 +The `Calc` object is initialised using the chosen reference value and a
1.74 +predefined interface reference:
1.75 +
1.76 +{{{
1.77 +Calc obj = {.ref=ref, .iface=&client_iface_Calc};
1.78 +}}}
1.79 +
1.80 +This predefined interface reference is obtained via the header file.
1.81 +
1.82 +To call interface operations, the functions providing access to them can be
1.83 +called directly:
1.84 +
1.85 +{{{
1.86 +Calc_add(ref, 123, 456, &result);
1.87 +}}}
1.88 +
1.89 +However, this ignores the object type and just employs the reference to the
1.90 +object state. A more object-oriented approach involves using the interface:
1.91 +
1.92 +{{{
1.93 +obj.iface->add(obj.ref, 123, 456, &result);
1.94 +}}}
1.95 +
1.96 +By employing object type values (instances), it becomes possible to treat
1.97 +local and remote components interchangeably.
1.98 +
1.99 +== C++ Language Clients ==
1.100 +
1.101 +An object representing the component will have the `Calc` type. A client
1.102 +object employing a capability in L4Re is a subtype of `Calc` called
1.103 +`client_Calc` and would be initialised as follows:
1.104 +
1.105 +{{{
1.106 +client_Calc obj(server);
1.107 +}}}
1.108 +
1.109 +Meanwhile, an object implemented locally might have a type called `local_Calc`
1.110 +and be initialised as follows:
1.111 +
1.112 +{{{
1.113 +local_Calc obj;
1.114 +}}}
1.115 +
1.116 +Such a local object would also need to be defined as a subtype of `Calc`.
1.117 +
1.118 +These objects can then be used to call interface operations:
1.119 +
1.120 +{{{
1.121 +obj.add(123, 456, &result);
1.122 +}}}
1.123 +
1.124 +Since a common base class is used to declare the interface, local and remote
1.125 +components are interchangeable.
2.1 --- a/docs/wiki/Development Sun Apr 26 18:24:46 2020 +0200
2.2 +++ b/docs/wiki/Development Sun Apr 26 18:25:12 2020 +0200
2.3 @@ -271,6 +271,27 @@
2.4 * `begin_compound_output`
2.5 * `write_files`
2.6
2.7 +These functions are described in more detail with regard to the topics of
2.8 +compound and individual interfaces.
2.9 +
2.10 +Meanwhile, a selection of writer functions are employed to generate code for
2.11 +the different structures employed within interface descriptions. Since output
2.12 +may be generated for different kinds of files, the following concepts are
2.13 +employed to parameterise the output appropriately:
2.14 +
2.15 + * Component roles indicate the nature of the component employing the
2.16 + generated code: client or server
2.17 +
2.18 + * Function roles indicate the characteristics of the function being written:
2.19 + general or completion
2.20 +
2.21 + * Parameter roles indicate the context of an identifier at a location in the
2.22 + generated code: signature (formal function parameter), structure (member),
2.23 + invocation (actual function parameter)
2.24 +
2.25 +Through the use of roles, the same fundamental information can be expressed in
2.26 +different ways by the same routine.
2.27 +
2.28 === Compound Interfaces ===
2.29
2.30 The `begin_compound_output` function is called by the main program when
2.31 @@ -308,6 +329,7 @@
2.32 server [shape=folder,fillcolor="#77ff77",label="..._server.{c,cc,h}"];
2.33 interface [shape=folder,fillcolor="#77ff77",label="..._interface.h"];
2.34 interfaces [shape=folder,fillcolor="#77ff77",label="..._interfaces.h"];
2.35 + interface_type [shape=folder,fillcolor="#77ff77",label="..._interface_type.h"];
2.36 }
2.37
2.38 subgraph {
2.39 @@ -334,6 +356,7 @@
2.40
2.41 write_compound_interface -> interface;
2.42 write_compound_output -> write_include -> interfaces;
2.43 + write_include -> interface_type;
2.44 }
2.45 }}}
2.46
2.47 @@ -397,35 +420,74 @@
2.48
2.49 ######## End of graph.
2.50
2.51 -== Includes and Headers ==
2.52 +=== Includes and Headers ===
2.53 +
2.54 +The `includes.c` and `includes.h` files provide support for writing `#include`
2.55 +statements in C and C++ programs, with the `write_includes` function
2.56 +traversing an `include` structure list to emit a list of statements.
2.57 +
2.58 +=== Interface Definitions ===
2.59
2.60 - * `includes.c`
2.61 +The `interface.c` and `interface.h` files provide the
2.62 +`write_interface_definition` function which is concerned with generating a
2.63 +description of an interface in two different contexts: client and server.
2.64 +Some generated files are employed in both contexts such as the file of the
2.65 +form `<interface>_interface.h`.
2.66 +
2.67 +==== Client Definitions ====
2.68 +
2.69 +For client use, some types are defined for client programs to use in a header
2.70 +file of the form `<interface>_client.h`.
2.71 +
2.72 +C programs employ a collection of function signatures for the different
2.73 +operations provided by the interface plus a declaration of an interface object
2.74 +retaining references to those functions as members.
2.75
2.76 -== Interface Definitions ==
2.77 +C++ programs employ a class declaration containing the operations as methods
2.78 +and with internal state referencing the component providing the operations.
2.79 +
2.80 +==== Server Definitions ====
2.81 +
2.82 +For server use, some types are defined for server programs to use in a header
2.83 +file of the form `<interface>_server.h`.
2.84
2.85 - * `interface.c`
2.86 +C programs employ declarations of the interface object type whose members
2.87 +provide a table of references to operation functions. A reference type is
2.88 +defined as a way of referencing the component providing the operations, and an
2.89 +object type is defined that bundles this opaque reference with a reference to
2.90 +the interface details. (Such an object is populated with a pointer to a
2.91 +component and a pointer to a table of concrete functions providing the
2.92 +appropriate operations.)
2.93
2.94 -== Templates and Output ==
2.95 +C++ programs provide the rather more straightforward class declaration
2.96 +containing the operations to be implemented by a component. (The
2.97 +implementation is provided by deriving from the generated class and defining
2.98 +concrete methods.)
2.99 +
2.100 +Both C and C++ output contains additional details describing operation codes
2.101 +and message structures (incoming and outgoing) for the different operations.
2.102 +
2.103 +=== Templates and Output ===
2.104
2.105 * `templates.h`
2.106
2.107 -== Servers ==
2.108 +=== Servers ===
2.109
2.110 * `server.c`
2.111
2.112 -== Dispatchers and Handlers ==
2.113 +=== Dispatchers and Handlers ===
2.114
2.115 * `dispatch.c`
2.116
2.117 -== Parameters and Members ==
2.118 +=== Parameters and Members ===
2.119
2.120 * `declaration.c`
2.121
2.122 -== Message Structures and Access ==
2.123 +=== Message Structures and Access ===
2.124
2.125 * `message.c`
2.126 * `structure.c`
2.127
2.128 -== Summaries ==
2.129 +=== Summaries ===
2.130
2.131 * `summary.c`
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/docs/wiki/Servers Sun Apr 26 18:25:12 2020 +0200
3.3 @@ -0,0 +1,219 @@
3.4 += Servers =
3.5 +
3.6 +Server code is code that provides components in the form described by those
3.7 +components' interfaces, employing interprocess communications mechanisms.
3.8 +
3.9 +<<TableOfContents(2)>>
3.10 +
3.11 +== Introduction ==
3.12 +
3.13 +The following example interface, resident in a file called `calc.idl`, will be
3.14 +used to illustrate the mechanisms described in this document:
3.15 +
3.16 +{{{
3.17 +interface Calc
3.18 +{
3.19 + void add(in int left, in int right, out int result);
3.20 + void subtract(in int left, in int right, out int result);
3.21 + void multiply(in int left, in int right, out int result);
3.22 + void divide(in int numerator, in int denominator, out int result);
3.23 +};
3.24 +}}}
3.25 +
3.26 +To expose this interface to other programs, a server program would do the
3.27 +following:
3.28 +
3.29 + * Obtain appropriate program types to reference the interface
3.30 +
3.31 + * Initialise values or objects that reference the component implementation
3.32 +
3.33 + * Interact with interprocess communication mechanisms and request the
3.34 + invocation of the component's operations
3.35 +
3.36 +The sections below describe how this is done in the different supported
3.37 +programming languages.
3.38 +
3.39 +Note that the mechanism by which interface descriptions are processed for use
3.40 +in programs is described in the [[L4Re Support]] document. The `idl` manual
3.41 +page provides details for developers wishing to use the tool directly.
3.42 +
3.43 +== Server Header Files ==
3.44 +
3.45 +Given the existence of generated files for the interface, a program would
3.46 +include the server header file:
3.47 +
3.48 +{{{
3.49 +#include "calc_server.h"
3.50 +}}}
3.51 +
3.52 +== C Language Servers ==
3.53 +
3.54 +An object representing a server will have the `Calc` type. This encapsulates
3.55 +a reference to the object state and a reference to the interface details.
3.56 +
3.57 +Since the aim in implementing a server is to provide access to state
3.58 +information held within a process, the object state reference will refer to a
3.59 +location holding such information via a pointer member.
3.60 +
3.61 +{{{
3.62 +ref_Calc ref = {.ptr=0};
3.63 +}}}
3.64 +
3.65 +Here, a value of `0` is used because the interface operations are stateless
3.66 +(they act like plain functions):
3.67 +
3.68 +The `Calc` object is initialised using the chosen reference value and a
3.69 +reference to interface information:
3.70 +
3.71 +{{{
3.72 +Calc obj = {.ref=ref, .iface=&server_iface_Calc};
3.73 +}}}
3.74 +
3.75 +Unlike in the client initialisation where a predefined interface already
3.76 +exists, it is up to the component implementer to define the functions that
3.77 +support the exposed interface. For example:
3.78 +
3.79 +{{{
3.80 +iface_Calc server_iface_Calc = {
3.81 + .add=calc_add,
3.82 + .subtract=calc_subtract,
3.83 + .multiply=calc_multiply,
3.84 + .divide=calc_divide,
3.85 + .pow=calc_pow
3.86 + };
3.87 +}}}
3.88 +
3.89 +The `Calc` object is then associated with a server capability and invoked when
3.90 +incoming messages are directed towards it.
3.91 +
3.92 +=== Compound Interfaces ===
3.93 +
3.94 +When supporting multiple interfaces, the general initialisation resembles that
3.95 +shown above. Firstly, the object state reference is defined, as in this
3.96 +example involving a reference suitable for a `CalcCounter` object:
3.97 +
3.98 +{{{
3.99 +ref_CalcCounter ref = {.ptr=&counter};
3.100 +}}}
3.101 +
3.102 +Here, the pointer member employs the address of a counter. This is accessed in
3.103 +the appropriate operation function.
3.104 +
3.105 +The object itself is populated in the same way as shown above:
3.106 +
3.107 +{{{
3.108 +CalcCounter obj = {.ref=ref, .iface=&server_iface_CalcCounter};
3.109 +}}}
3.110 +
3.111 +The principal difference involves the interface details. Since a compound
3.112 +interface is exposed, there must be a way to address the individual
3.113 +interfaces, and this is done using members employing a specific naming
3.114 +convention:
3.115 +
3.116 +{{{
3.117 +iface_CalcCounter server_iface_CalcCounter = {
3.118 + .to_Calc=&server_iface_Calc,
3.119 + .to_Counter=&server_iface_Counter
3.120 + };
3.121 +}}}
3.122 +
3.123 +Here, the `to_Calc` member provides a reference to suitable details for the
3.124 +`Calc` interface, and the `to_Counter` member provides the corresponding
3.125 +reference for the `Counter` interface.
3.126 +
3.127 +=== Operation Implementations ===
3.128 +
3.129 +Implementations of operations employ a signature where the first parameter is
3.130 +the object state reference value. This permits access to the state information
3.131 +and allows functions to update the state of several objects independently:
3.132 +
3.133 +{{{
3.134 +long counter_increment(ref_Counter _self, int *result)
3.135 +{
3.136 + int *counter = (int *) (_self.ptr);
3.137 +
3.138 + *counter = *counter + 1;
3.139 + *result = *counter;
3.140 + return L4_EOK;
3.141 +}
3.142 +}}}
3.143 +
3.144 +Here, the pointer member is used to access the information referenced when the
3.145 +object was initialised.
3.146 +
3.147 +== C++ Language Servers ==
3.148 +
3.149 +An object representing the component will have the `Calc` type. An object
3.150 +providing a specific implementation of the component might have a type called
3.151 +`server_Calc` and be initialised as follows:
3.152 +
3.153 +{{{
3.154 +server_Calc obj;
3.155 +}}}
3.156 +
3.157 +Such an object type would need to be a subtype of `Calc` and would resemble
3.158 +the following:
3.159 +
3.160 +{{{
3.161 +class server_Calc : public Calc
3.162 +{
3.163 +public:
3.164 + long add(int left, int right, int *result);
3.165 + long subtract(int left, int right, int *result);
3.166 + long multiply(int left, int right, int *result);
3.167 + long divide(int numerator, int denominator, int *result);
3.168 +};
3.169 +}}}
3.170 +
3.171 +The `server_Calc` object is then associated with a server capability and
3.172 +invoked when incoming messages are directed towards it.
3.173 +
3.174 +=== Compound Interfaces ===
3.175 +
3.176 +When supporting multiple interfaces, the general initialisation resembles that
3.177 +shown above, as in this example involving a specific object type derived from
3.178 +the `CalcCounter` type:
3.179 +
3.180 +{{{
3.181 +server_CalcCounter obj;
3.182 +}}}
3.183 +
3.184 +Similarly, a definition of this type is required supporting the range of
3.185 +operations associated with all of the individual interfaces:
3.186 +
3.187 +{{{
3.188 +class server_CalcCounter : public CalcCounter
3.189 +{
3.190 + int counter = 0;
3.191 +
3.192 +public:
3.193 + long add(int left, int right, int *result);
3.194 + long subtract(int left, int right, int *result);
3.195 + long multiply(int left, int right, int *result);
3.196 + long divide(int numerator, int denominator, int *result);
3.197 + long increment(int *result);
3.198 +};
3.199 +}}}
3.200 +
3.201 +=== Operation Implementations ===
3.202 +
3.203 +Since C++ manages access to object state transparently, the way of accessing
3.204 +such state is more straightforward:
3.205 +
3.206 +{{{
3.207 +long server_CalcCounter::increment(int *result)
3.208 +{
3.209 + counter = counter + 1;
3.210 + *result = counter;
3.211 + return L4_EOK;
3.212 +}
3.213 +}}}
3.214 +
3.215 +== Exposing Objects as Servers ==
3.216 +
3.217 +In L4Re, component objects can be made available to other programs by
3.218 +associating them with interprocess communication (IPC) "gate" capabilities and
3.219 +then waiting for incoming messages. Upon receiving a message, the identity of
3.220 +the gate providing the message can be tested, and if it is the gate associated
3.221 +with a component, the message can then be interpreted and directed at the
3.222 +component as an invocation.