|
||||
Dynamic Linking in Eiffel1 INTRODUCTION: THE DLE AND ITS PURPOSEThis document describes the specification for a mechanism, called Dynamic Linking in Eiffel or DLE for short, enabling developers of Eiffel software to defer until execution time certain decisions which they would otherwise have to make before compilation. A system relying on the DLE mechanism may rely on one or more classes that were not known when the system was assembled, requiring the system to obtain the class descriptions from files at execution time. The DLE brings to Eiffel a set of capabilities heretofore available only in completely dynamic approaches to object-oriented computation such as Smalltalk. This advantage -- the ability to reconfigure a system dynamically -- is achieved in Smalltalk at a heavy price in safety and efficiency, since it implies the absence of static typing (hence raising the possibility of run-time errors) and the inability to generate fully compiled code. The structure of Eiffel makes it possible to keep most of the advantages of a typed approach, and to bring the performance overhead down to an acceptable level. A point of terminology: this document uses the term "developer" to denote a user of the DLE system -- that is to say a developer of Eiffel software who needs the DLE facilities. The following section presents the overall picture by describing how developers will prepare a system for use with the DLE mechanism, and then use this mechanism. The rest of the report presents the details of the mechanism. 2 THE GENERAL DLE SCHEMEUsing the DLE makes it possible to obtain a dynamically extendible system according to the following general sequence of developer actions.
Steps 4 to 6 may be repeated as many times as needed. The DLE mechanism does not make any assumption about the compiling mode used to assemble the DR-system and the DC-set, which may be any of the three compiling modes of ISE Eiffel: melting, freezing and finalizing. Compilation may be started from either the graphical environment (EiffelBench) or the command-line tool (es4). The following sections examine in more detail the actions needed in the above steps. 3 USING DYNAMIC CLASSESThe first step in using the DLE mechanism is to prepare a DR-system. 3.1 Preparing the AceA DR-system is characterized by a line of the following form in the default paragraph of its Ace:
Including this option directs the Eiffel compilation process to generate code that is ready for the insertion of extra classes at run-time. There is no limit on the number of classes that may be added dynamically. The precise definition of a DR-system used in the rest of this Report is that it is a system whose Ace includes an entry of the above form. A no value is permitted, but has the same effect as if the Ace did not include an extendible entry. The classes that are part of the DR-system at the time of its assembly will be called static classes. If you have assembled a DR-system, the DLE mechanism allows you dynamically to add to it not just classes but also features. 3.2 Taking advantage of the DLE mechanismA DR-system is able to incorporate classes compiled after the system's assembly, also called dynamic classes. Of course this capability will only be useful if the system includes dynamic operations, that is to say operations that use the dynamic classes, and if at least some of the dynamic operations appear in static classes. This creates an apparent paradox since the classes on which dynamic operations rely are not known at assembly time. Here is the way it works. The DR-system may rely on two library classes: DYNAMIC and DYNAMIC_CLASS, with the following goals:
Note the difference between DYNAMIC and DYNAMIC_CLASS, suggested by the names. An instance of DYNAMIC is an object -- an instance of a dynamic class. An instance of DYNAMIC_CLASS describes a class (one of the dynamic classes themselves). 3.3 Retrieving dynamic classesTo use a dynamic class a DR-system will need, at execution time, to obtain a description of that class, in the form of an instance of class DYNAMIC_CLASS. Assume that (using the process explained in section 6) you have compiled a dynamic class with respect to the DR-system. The result is a class description, in the form of an instance of DYNAMIC_CLASS which the compilation has stored in the directory associated with a DC-set. To retrieve that instance, you may use the following creation procedure of class DYNAMIC_CLASS: make (class_name, dc_dir: STRING) -- Initialize to representation of dynamic class of name class_name -- in the DC-set whose directory is dc_dir. -- Set retrieve_status to non-zero value if no such class can be found. require class_name_exists: class_name /= Void class_name_not_empty: not class_namelempty DC_set_path_exists: dc_dir /= Void DC_set_path_not_empty: not dc_dir.empty The second argument, dc_dir, is the project directory that has been used to assemble the set of dynamic classes, or DC-set, to which the requested dynamic class class_name belongs. Section 6 explains the notion of DC-set and shows how to assemble a DC-set. To find out whether the make creation procedure has been able to produce a useful class description, you may use the query retrieve_failed. The following cases will prevent the procedure from yielding a class description; in each of them it will set the result of the query retrieve_status to the value of an integer constant as indicated:
Procedure make of DYNAMIC_CLASS, in addition to being a creation procedure, is exported, so that it may be called again on an instance of this class after creation -- for example after one of the above error codes has been detected. 3.4 Producing instances of dynamic classesHaving obtained an object representing a dynamic class, you may use it to produce instances of that class -- dynamic objects. To obtain a dynamic object, the DR-system will use the following function from DYNAMIC_CLASS: instance: DYNAMIC -- An instance of the class represented by current object, -- initialized by procedure make of that class, using -- argument as argument require class_exists: not retrieve_failed ensure instance_not_void: Result /= Void Class DYNAMIC has a procedure called make, which expects a single argument of type ANY. Every proper descendant of DYNAMIC should also have such a make procedure to perform any necessary initialization, and should include it in its Creation clause. Class DYNAMIC_CLASS provides a procedure to specify the argument that will be passed to instance: set_argument (val: like argument) -- Define val to be the argument to be passed to creation procedures -- by subsequent calls to instance. ensure argument_set: argument = val The value last set by set_argument is accessible through feature argument of DYNAMIC_CLASS, of type ANY. Assume that class YOUR_DYNAMIC is such a descendant of DYNAMIC, entity your_object has been declared of type YOUR_DYNAMIC, entity your_class_description is attached to an instance of DYNAMIC_CLASS that describes a certain class YOUR_CLASS, and your_argument denotes some value to be used as argument to the intended creation procedure. Then the effect of the instructions [1] your_class_description.set_argument (your_argument); your_object ?= your_class_description.instance is the same that would normally be obtained, were YOUR_CLASS a static class belonging to the DR-system, through the creation instruction [2] !YOUR_CLASS! your_object.make (your_argument) 3.5 The overall schemeAs a result of the preceding discussion the normal scheme for using a dynamic class is the following. This extract assumes that you have declared a class YOUR_DYNAMIC as a descendant of DYNAMIC, and that the dynamic class YOUR_CLASS has itself been declared as a descendant of YOUR_DYNAMIC. your_class_description: DYNAMIC_CLASS; your_object: YOUR_DYNAMIC; your_argument: YOUR_ARGUMENT_TYPE; ... create your_class_description.make ("YOUR_CLASS", "your_directory_name"); if not your_class_description.retrieve_failed then -- As above: your_class_description.set_argument (your_argument); your_object ?= your_class_description.instance end; if your_object /= Void then your_object.some_feature (...) end Here some_feature is a feature of class YOUR_DYNAMIC. In the most interesting cases the dynamic class retrieved by the call to make will redeclare that feature, so that with dynamic binding the call your_objectlsome_feature (...) will trigger a feature variant that was not known at the time the DR-system was assembled. In spite of their names DYNAMIC and YOUR_DYNAMIC are static classes since they are part of the DR-system at assembly time; they are static specifications of the minimum set of properties of dynamic classes. 4 USING DYNAMIC FEATURES(This section currently not included.) 5 A SUMMARY OF LIBRARY CLASSES AND FEATURESThe DLE mechanism is supported by a library (the DLE library) whose classes and features have been introduced in the preceding sections. The complete list of these classes and features appears in appendix B. 6 PRODUCING DYNAMIC CLASSESOnce you have a DR-system you may add dynamic classes and features. To produce dynamic classes you will prepare a Dynamic Class Set or DC-set. A DC-set is similar to a system, and will be assembled as a system, with the peculiarity that its classes are permitted to depend not just on each other but also on a previously assembled DR-system, called the base system of the DC-set. (The dependencies considered here are the two kinds of class dependency permitted in Eiffel: client and inheritance.) You will prepare a DC-set the way you would prepare a normal system, with only one specific requirement: the Ace of the DC-set system must contain, in its default paragraph, an entry of the form extending ("dr_dir") where dr_dir is the project directory of its base system. (As a convension the root paragraph will repeat what has been specified for the DR-system.) A system is considered to be a DC-set if and only if its Ace contains such an entry with a non-empty dr_dir string. A few restrictions apply to a DC-set. The assembly of a DC-set will only succeed if a system obtained by merging the DC-set and its base system could be assembled successfully. This implies the first two of the following four restrictions:
Restriction 4 is an implementation constraint. It is worth noting that there is no restriction on the size of the DC-set. It is possible in principle (although not in the current release) to write more than one DC-set for the same base system, so that at run time a DR-system will be able to load dynamic classes from different DC-sets. Successfully assembling a DC set will produce, in a subdirectory of its project directory, a set of files that contain descriptions of the dynamic classes. Such descriptions can then be retrieved by the DR-system during its execution, using the make creation procedure of class DYNAMIC_CLASS as explained in section 3.3. 7 IMPLEMENTATION CONSIDERATIONSThe major implementation issues arise for final mode. The principal question is how to store the representations of dynamic classes, as produced by the assembly of a DC-set and retrieved by the make procedure of DYNAMIC_CLASS. Although it is possible to use an interpretive representation for dynamic classes, it seems preferable for performance reasons to go to C in final mode. This assumes that the platform supports a form of dynamic libraries. This is not the case with all platforms, but includes SunOS, Solaris, SGI, Windows and a few others. The current implementation under Solaris takes advantage of such facilities. Also related to final mode, compilation optimizations provided by ISE Eiffel (dead code removal, inlining, array optimization and statically bound feature calls) are supported both in the DR-system and in the DC-set. An implementation problem arises, however, with respect to statically bound feature call optimizations. A feature call which was statically bound at the DR-system assembly time might not be valid anymore after loading a DC-set introducing a class which redefines this feature. A new free option has been introduced in the default and option clauses of the DR-system's Ace to provide the developer with additional control of this optimization mechanism: dynamic (f): CLASS1 Including this option directs the Eiffel compilation process to generate dynamically bound feature calls in the DR-system for feature f applied on objects of type CLASS1 even though these feature calls could have been statically bound at that time. For convenience, the following forms are also permitted: dynamic (f): CLASS1, CLASS2; dynamic (all): CLASS1; dynamic (all): CLASS1, CLASS2 Since in most interesting cases descendant classes of DYNAMIC will redefine features inherited from the static classes, calls to these features will all be automatically bound dynamically. Also for convenience, the compilation of the DR-system in final mode generates in file EIFGEN/F_code/STATIC the list of feature calls that have been statically bound. 8 ADDITIONAL CONSTRAINTSThe following requirements are imposed on the use of the DLE mechanism:
9 RESTRICTIONSThe preceding sections have described the full mechanism. The current version of the DLE mechanism imposes an additional restriction: at most one DC-set may be used per DR-system. Trying to load more than one DC-set will set retrieve_status to the integer constant value Duplicate_DC_set.
The current DLE implementation is available on Solaris. Please
inquire with ISE
about ports to other platforms.
Table of Contents
Next Chapter
|