CA2166302C - System for object oriented dynamic linking based upon a catalog of registered function set or class identifiers - Google Patents

System for object oriented dynamic linking based upon a catalog of registered function set or class identifiers Download PDF

Info

Publication number
CA2166302C
CA2166302C CA002166302A CA2166302A CA2166302C CA 2166302 C CA2166302 C CA 2166302C CA 002166302 A CA002166302 A CA 002166302A CA 2166302 A CA2166302 A CA 2166302A CA 2166302 C CA2166302 C CA 2166302C
Authority
CA
Canada
Prior art keywords
function
class
link
library
computer
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Expired - Lifetime
Application number
CA002166302A
Other languages
French (fr)
Other versions
CA2166302A1 (en
Inventor
George Curtis Cowsar
Christopher Jordan Plummer
Michael John Quinn
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Apple Inc
Original Assignee
Apple Computer Inc
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Apple Computer Inc filed Critical Apple Computer Inc
Publication of CA2166302A1 publication Critical patent/CA2166302A1/en
Application granted granted Critical
Publication of CA2166302C publication Critical patent/CA2166302C/en
Anticipated expiration legal-status Critical
Expired - Lifetime legal-status Critical Current

Links

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/44Arrangements for executing specific programs
    • G06F9/445Program loading or initiating
    • G06F9/44521Dynamic linking or loading; Link editing at or after load time, e.g. Java class loading
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/44Arrangements for executing specific programs
    • G06F9/448Execution paradigms, e.g. implementations of programming paradigms
    • G06F9/4488Object-oriented
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/44Arrangements for executing specific programs
    • G06F9/445Program loading or initiating
    • G06F9/44536Selecting among different versions

Abstract

A system is provided for managing code resources for use by client applications in a computer, wherein the computer has internal memory storing at least one client application. The apparatus comprises a resource set catalog stored in the internal memory. The resource set catalog identifies a plurality of function sets of functions by respective function set IDs. Further, the resource set catalog includes set records which characterize the functions within me respective sets. A dispatch engine, in the internal memory, linked with a client application, supplies a particular function set ID in response to a call by the client application of a particular function which is a member of a corresponding function set identified by the particular function set ID. A lookup engine in the internal memory, coupled with the resource set catalog and the dispatch engine, is responsive to the particular function set ID to look up a set tad for a corresponding function set in the resource set catalog. Finally, a link engine in the internal memory and coupled with the dispatch engine returns the particular function to the client application in response to the set record. Thus because the link engine is responsive to the set record, which is not linked with the client, the client need not be aware of changes in the structure of the library in which the particular function set resides. Thus, the function set can be moved into and out of internal memory, revised placed in different sections of internal memory, and otherwise handled independently of the client, without requiring re-compilation of the client application.

Description

SYSTEM FOR OBJECT ORIENTED DYNAMIC LINKING
BASED UPON A CATALOG OF REGISTERED FUNCTION SET
OR CLASS IDENTIFIERS

BACKGROUND OF THE INVENTION
Field of the Invention The present invention relates to dynamic linking of client applications with function sets or classes used by the client applications; and, more particularly, to systems for dynamically linking a client application at nm time with libraries of function sets or classes registered either before or during execution of the client application.
Description of the Related Art Traditionally, an application's source files are compiled in object modules and then linked together with other object modules, generically called libraries, to form a complete stand-alone application. This is called static linking. A
disadvantage of static linking is that each application that links with the same library routine has its own private copy of the routine. Most. of the size of the applications comes from the library code linked to each application. Another disadvantage of static linking is that the functionality that the application gets from the library is fixed. If the library has a bug in it, the application has to be re-linked with the new library to get the bug fixed.
Dynamic linking, sometimes called late binding, differs because the application code and library code are not brought together until after the application is launched. If the code in the library is not loaded until it is actually required, then this is called dynamic loading.
If the same copy of library code being used by one application can be used by other applications at the same time, then the library is called a shared library.
a Dynamic linking of a class or function set involves binding code ("client application") which uses a class or function set to the code which implements the class or function set at run time. Thus, the term "dynamic" in this context, means "occurring at run time" . Linking entails both loading the code and binding imported references to exported implementations of the classes or function sets.
Existing dynamic linking systems do not provide class level or function set level dynamic linking. Instead, the linking is done at the level of the individual functions which may be exported by a library and imported by a client.
However, each individual function must be exported by the library and each function used by the client must be imported in such prior art systems. To complicate matters, the name of the functions after compilation is not the name of the same in the source code (i.e., C++). Thus, the developer must deal with so-called "mangled" names to satisfy parameters of the dynamic linking systems of the prior art.
Among other limitations, prior individual function level binding systems cause the implementation of a client to be dependent on a particular set of classes known at build time. Thus, new derived classes cannot be added later without having to rebuild the client. Further, prior art dynamic linking systems do not provide for dynamic installation of the linking system itself. In some cases, after a new linking system is installed, the host system must be rebooted or at least the client application has to be restarted.
Fisting dynamic linking systems a.re designed to support procedural programming languages and do not provide object oriented dynamic linking.
Since some object oriented languages are derivatives of procedural languages (e.g., C++ is a derivative of C) these systems can sometimes provide dynamic linking a of an object oriented language, provided the programmer deals with a class by the ~O 95101598 PCT/US94/07424 ~16~3 p~
awkward approach of explicitly naming all members of the class. Nonetheless, these systems do not directly support object oriented programming languages.
Accordingly, it is desirable to optimize a dynamic linking system to object oriented programming systems involving class level or function set level dynamic binding. Furthermore, such system should be robust, supporting efficient use of internal memory, and versioning of function sets or classes. Finally, it is desirable to provide for dynamic registration of updated or new libraries, so that a client application need not be restarted in order to take advantage of new versions of its libraries.
STJMMARY OF THE INVENTION
The present invention provides explicit support for object oriented languages, such as C++, MCL, and Dylan. This support includes linking by class or class identifier where a library exports a class and a client imports a class.
1'he client has access to all of the public virtual and non-virtual member functions of such dynamically linked classes. Also, the client may instantiate an object of a class which was not known at compile time. In this case, the client can call public virtual member functions using a known interface of one of the parent classes of a class.
The system of the present invention employs a dynamic function set catalog which can be queried directly or indirectly by the client. Since, ultimately, the implementation of a class is a set of functions, it is possible to dynamically link classes. The dynamic function set or class catalog is updated from a catalog resource when a library is registered and when a library is unregistered with the system. Each registered function set or class is given an identifier when registered.
The system is particularly suited to object oriented programming environments, where for a function set which characterizes a class; a direct catalog query by a client can determine for a given identifier, and the corresponding information in the catalog (1) whether the class is available, (2) the class IDs of its parent classes, (3) the class IDs of its derived classes, and (4) whether the class WO 95/01598 .~~ ~ ~. ; <y .-'~ = PCT/L1S94/07424 ~ ~. 6 can be dynamically instantiated by a class ID. These functions enable clients to dynamically determine the availability and compatibility of classes, and enable new functionality to be delivered in the form of new shared class libraries and added to a client without recompiling the client. Since all code that implements a class can be dynamically linked, the client is not dependent on the implementation of the a library code. A library can be fined or enhanced without having to rebuild the client or other libraries. This simplifies the development and distribution of fixes and enhancements, and is generally better than existing patching mechanisms.
Since other dynamic linking systems are not aware of classes as a distinct entity, the concept of class identification and class catalog management does not exist in these systems.
Accordingly, the present invention can be characterized as a system for managing code resources for use by client applications in a computer, wherein the computer has internal memory storing at least one client application. The apparatus comprises a resource set catalog stored in the internal memory. The resource set catalog identifies a plurality of function sets by respective function set B7s. Further, the resource set catalog includes set records which characterize the implementation of functions within the respective sets.
A dispatch engine, in the internal memory, linked with a client application, supplies a particular function set 1D in response to a call by the client application of a particular function which is a member of a function set identified by the particular function set ID. A lookup engine in the internal memory, coupled with the resource set catalog and the dispatch engine, is responsive to the particular function set m to look up a set record for a corresponding function set in the resource set catalog. Finally, a link engine in the internal memory and coupled with the dispatch engine returns the particular function to the client application in response to the set record. Thus, because the link engine is responsive to the set record, which is not linked with the client, the client need not be aware of changes in the stn~cture of the library in which the particular function set resides.
Thus, the function set can be moved into and out of internal memory, revised, placed in ~O 95/01598 PCT/US94/07424 different sections of internal memory, and otherwise handled independently of the client, without requiring re-compilation of the client application.
The resource set catalog is characterized as containing set records for function sets, where a class for an object oriented system is a type of function set.
Thus, where the term "function set" is used in the claims, it is intended that a species of function set may be a class.
According to one aspect of the invention, the dispatch engine includes a dispatch record which is linked with the client, and stores a particular function set LD corresponding to a function set of which the called function is a member.
~~lso, a dispatch routine is included in the dispatch engine, which is linked to the dispatch record and the lookup engine, and responsive to the call to the particular function to supply the particular function set In to the lookup engine. In one preferred embodiment, the dispatch routine includes a first level dispatch segment linked to the client and to a global variable in the internal memory, and a second level dispatch segment linked to the global variable and the lookup engine.
According to yet another aspect of the present invention, the dispatch record includes a function link cache and a set link cache. The function link cache stores a link to the particular function which is supplied by the link engine in response to the return of the particular function to the client. The dispatch engine includes a routine which looks at the function link cache for a cached link to the particular flunction and jumps to the particular function in response to the cached link if present.
The set link cache stores a link to the set record for the set of functions including the particular function which had been previously called by the client.
7.'he link engine includes a routine that supplies the link to the set link cache in response to return of a particular function to the client. The dispatch engine vncludes a routine which looks in the set link cache for a cached link to the set record, and returns the set record to the link engine in response to the cached link a upon a call to a function which is a member of the function set.
~::~''~~~' "' ~ PCT/US94/07424~
Thus, a function call can be executed quickly if the function link cache is full, with a medium level of speed if the set link cache is full, and more slowly if a catalog search is needed to bind the function implementation.
The invention further provides for assignment of version numbers to function sets according to a standard protocol. The dispatch record in this aspect includes version information linked with the client indicating a minimum version number supported by the client for the function set of which the particular function is a member. The set record includes a version number for the corresponding function set. The link engine in this aspect includes a routine which is responsive to the version information in the dispatch record and the version number in the set record to insure that the client supports a version of the particular function in the function set.
In addition, the function sets are assigned serial numbers when loaded in internal memory. The dispatch record further includes a serial number linked with the client indicating a serial number of the corresponding function set when the set link cache is filled. The set link cache stores a pointer to a link structure in internal memory and the link structure includes a pointer to the set record having the particular function set ID. The set record stores the assigned serial number for the function set when it is loaded in internal memory. 3'he link engine includes a routine responsive to the serial number in the set record, and the serial number in the dispatch record to insure validity of the set link cache entry, and a routine for clearing the link structure when the corresponding function set is loaded.
The invention further provides for a use count record within the set record.
The link engine in this aspect includes a routine to increment the use count when a client application binds with the function set corresponding to the set record, and to decrement the use count when a client application frees the function set corresponding to the set record. When the function set characterizes a class, the use count is incremented when a constructor for the class is called, and decremented when a destructor for the class is called. Thus, using the use count, a the memory management system can unload function sets which are not in current use by any active applications.
~O 95/01598 ', PCT/US94/07424 Since a client can enumerate all derived classes of a given class by class ID, it can determine what classes are available dynamically. The set of available classes can be extended at run time when new libraries are registered and a client can instantiate a class even though it is added to the system after the client was launched. New classes can be copied into a library directory or folder in the file system at any time and are automatically registered, or a new folder or file can be explicitly registered as a library container by a client.
Dynamic registration of libraries of function sets or classes is accomplished using the class catalog. Because the class catalog is not bound with clients, all that needs to be done to register a new library, is to write the appropriate records into the class catalog. Once the appropriate records are written into the class catalog, fhe new library becomes available to the new client. The procedures outlined above are in place to protect the client from using a version of a class or function set which it does not support, and for fording an unloaded and reloaded version of a particular function which it has already used.
The invention further provides for insuring type safety of the dynamically linked classes and function sets by means of shared library functions specifically designed to take advantage of the class catalog to insure such safety. The particular functions include the new object function, by which a client application nnay obtain information needed to construct a new object using the shared library manager, with reference to the class 1D of the new object. Thus, using a class ID, t!he library manager looks up the information about the class in the class catalog, and returns a constructor for the class to the client. The client is then able to call tike constructor, even if it did not know at the time it was written or compiled about the class.
In addition, the library manager provides a verify class routine, by which a client application may verify the parent of a particular derived class for type safety. Finally, a cast object routine is provided, by which a client may cast an instance of a particular object as a parent class object. This routine utilizes the class catalog to return offsets within the particular object to the elements of the WO 95/01598 , ~ PCT/US9410742 ~1~6~a parent, even though the client application may not have been aware of the structure of the parent at the time it was written or compiled.
Accordingly, it can be seen that the present invention provides a dynamic class catalog which given a class ID can be queried to determine whether the class is available, the class IDs of the parent class or classes, the class ID or IDs of the derived class or classes, and whether the class can be dynamically instantiated by class ID. When an object is instantiated, the library or libraries which implement the class and its parent classes are dynamically loaded. An object can be instantiated by a client which had no knowledge at compile time of the class of the object. If such client was compiled with the interface of a parent class of the object, then the object can be used as if it were an instance of the parent class.
The system is particularly suited for object oriented dynamic linking which enables dynamic library registration, dynamic inheritance, and on-demand type-safe dynamic instantiation of objects by class identifier.
Other aspects and advantages of the present invention can be seen upon review of the figures, the detailed description, and the claims which follow.
$RIEF DESCRIPTION OF TI-IE FIGURES
Fig. 1 is a schematic diagram of a computer system implementing the shared library manager of the present invention.
Fig. 2 is a schematic diagram of the resource set catalog used according to the present invention.
Fig. 3 is a diagram of the data structures involved in the dynamic binding of the present invention.
Figs. 4A-4C provide the "C" language definition of the stub record, client VTable record and class VTable records according to a preferred embodiment.
Figs. SA and SB provide a flowchart for the basic dispatching architecture used with the shared library manager of the present invention.
Figs. 6A, 6B, and 6C provide a flowchart for the GET CLASS VTABLE
J
RECORD step 112 of Fig. 5B.
_g_ ~O 95/01598 PCT/US94/07424 21~~3p~ ~ .
. . ., Fig. 7 is a schematic diagram of the library registration function, and arganization.
Fig. 8 is a flowchart illustrating the operation of the dynamic registration routine using the structure of Fig. 7.
Figs. 9A and 9B illustrate a new object routine executed by the shared library manager.
Fig. 10 illustrates a variant of the new object routine used when type safety is desired to be verified.
Fig. 11 is a flowchart for a verify class routine executed by the shared library manager.
Fig. 12 is a flowchart for a cast object routine executed by the shared library manager.
DESCRIPTION OF THE PREFERRED EMBODIMENTS
A detailed description of preferred embodiments of the present invention is provided with respect to the figures. Figs. 1-12 provide a high level overview of enabling various aspects of the present invention. A detailed description with references to segments of the source code follows a description of the figures.
Fig. 1 shows a computer system in which the present invention is loaded.
7Che computer system includes a host CPU 10 which includes a plurality of registers 11 used during execution of programs. The CPU is coupled to a bus 12.
7Che bus communicates with an input device 13 and a display 14 in the typical computer system. Further, non-volatile memory 15 is coupled to the bus 12. The non-volatile memory holds large volumes of data and programs, such as libraries, client applications, and the like. A high speed memory 16 is coupled to the bus 12 for both data and instructions. The high speed memory will store at least one client application 17, a shared library manager 18, shared library manager global variables at a predetermined address space within the memory 16, exported libraries 20, and other information as known in the art.
According to the present invention, when a client application is compiled, a number of items are provided within the application. These items include a stub WO 95/01598 . _ ~ PCT/US94/07424~
f.
~lss3o~
record, stub code, a library manager interface, a client VTable record, and a first level dispatch routine. The shared library manager will include a library builder routine, a resource set catalog, a second level dispatch routine, class VTable records for registered libraries, a lookup function, and a link function.
As mentioned above, the resource set catalog provides information for , function sets or classes which are available to a client. The stub record points to the client VTable record within the client. The first level dispatch routine uses information in the client VTable record to call the second level dispatch routine.
The second level dispatch routine calls the lookup function to find information about the called function in the resource set catalog. That information is provided to a link engine in the form of a class VTable record which links the client to the particular function that it has called. A particular protocol for using these features of the client and the shared library manager are described below with reference to Figs. 5 and 6.
The implementation of the resource set catalog, also called a class catalog herein, is shown in Fig. 2. A class catalog is a record 30 which includes a first field 31 which stores a number indicating the number of exported classes in all the library files which have been registered with the catalog 30. Next, the catalog includes an array 32 which stores class information records, one per exported class. The class information record in the array 32 consists of a structure 33 which includes a number of parameters. This structure includes a first field named library which points to the library in charge of the code for the particular class or function set. A second field 35 stores a class serial number which is unique for each instance of the class; that is, it is incremented on registration of the class.
A next field 36 stores a VTable record pointer which is the pointer to the VTable record for this class. A next field 37 stores a class m, which is a class identifier for the class. A next record 38 stores the parent class m. This is the class ID for a parent of this class. Next, a plurality of flags are stored in field 39 which are defined in more detail below. A next field 40 is a class link pointer.
This points to a link structure for establishing a link with the client VTable record.

~O 95101598 PCT/US94/07424 Field 41 stores a version parameter indicating a version of the class implementation.
The class information record is loaded from a library resource having a i structure described below with reference to Fig. 8.
Fig. 3 schematically illustrates the records used for dynamically linking a function call in a client to a class or function set. The figure is divided generally along line 50. Where elements above line 50 are linked with the client during compile time, and elements below line 50 are linked with the shared library manager. Thus, the client includes a stub record 51 which provides a function link cache for a pointer to the implementation of the called function, and a pointer 52 to a client VTable record 53. The client VTable record stores the class identifier, for the class or function set, and a class link pointer providing a set link cache.
The class link pointer 54 points to a link structure 55 which stores a pointer 56 to a class information record 57 in the class catalog. The class information record vncludes a pointer 58 to the class VTable record 59. The class VTable record includes a pointer 60 to the actual VTable of the class, and a pointer 61 to an export table for non-virtual functions.
If the class link pointer 54 is null, then a lookup function is called which accesses the class catalog 62 to look up the class information record 57 for the corresponding function. If that function is registered, then the class information record 57 is supplied, and the class VTable record 59 may be retrieved.
The figure also includes a schematic representation of a load engine 64.
'The load engine is coupled with the class information record 57. If the class corresponding to the class information record is not loaded at the time it is called, then the load engine 64 is invoked. When the information is moved out of longterm storage into the high speed internal memory, the class information record :57 and class VTable record 59 are updated with the correct pointers and values.
F
Figs. 4A, 4B, and 4C respectively illustrate the actual "C" definitions for 'the stub record, client VTable record, and class VTable record according to the preferred implementation of the present invention. Details of these structures are provided below in the description of a preferred embodiment. They are placed in WO 95/01598 ~ z ~ PCT/US94/07424 2.~ 663.~2~ ~' these figures for ease of reference, and to illustrate certain features. It can be seen that the client VTable record (Fig. 4B) includes version information (f Version, fMinVersion) which indicates a current version for the function set or class to which the class link pointer is linked, and the serial number (fClassSerialNumber) for the same. The class information record 57 of Fig. 3 also includes version , information for the currently loaded class for a function set, and the serial number for the currently loaded class or function set. These fields are used for insuring version compatibility between the client and the currently loaded library, as well as validity of the link information.
The class VTable record 59 (Fig. 4C) also includes a use count parameter (fUseCount). The use count parameter is incremented each time a class is constructed, and decremented each time a class is destructed. When the use count returns to zero, the class or function set is freed from internal memory.
Figs. SA and SB provide a flowchart for the basic implementation of the run time architecture. The algorithm begins by a client application calling a class constructor or a function by name (block 100). The stub code, generally outlined by dotted line 90, in the client with a matching name refers to the linked stub record (block 101). The stub code then tests whether the stub record includes the address for the constructor or function in its function link cache (block 102). If it does, then the stub code jumps to the address (block 103). This is the fastest way in which a function may be executed.
If the stub record did not include a valid cached address for the function, then the stub code calls a first level dispatch routine (block 104).
The first level dispatch routine is generally outlined by dotted line 91. The first step in this routine is to load a pointer to the library manager interface in the client in a host register (block 105). Next, the offset to the second level dispatch routine is read from the SLM global variables in internal memory (block 106).
Next, the second level dispatch routine is jumped to based on the offset read in block 106 (block 107).
The second level dispatch routine is generally outlined by dotted line 92.
The second level dispatch routine begins by pushing pointers for the client library ~O 95/0159;8 manager interface and stub record onto the stack (block 108). Next, a lookup function is called for the class catalog (block 109).
The lookup function is generally outlined by dotted line 93. The first step in the lookup function is to take the stub record and library manager interface for the client (block 110). Using the information, the lookup function retrieves the class identifier for the named class or function set from the client Viable record (block 111). Next, the class Viable record (a set record) is retrieved based on the class ID (block 112). This step can be accomplished using the class link pointer for cached classes or function sets, or requires a lookup in the class catalog. Once the class Viable record is found, a link engine, generally outlined by dotted line 94, executes. The first step in the link engine is to get the function array pointer fmm the class Viable record (block 113). Next, the array is searched for the particular called function (block 114) . Next, a pointer to the function is stored in the stub record for the client providing a function link cache value (block 115).
Finally, the function pointer is returned to the second level dispatch routine (block 116). The second level dispatch routine then cleans up the process and jumps to the function (block 11'x.
Figs. 6A, 6B, and 6C provide a flowchart for the step of block 112 in Fig.
SIB, which returns a class Viable record in response to~ the class ID. Thus, the algorithm begins by taking the class ID as input (block 150).
Using the class ID, the class catalog object is called which first compares the class serial number in the client Viable record to a global start serial number maintained by the shared library manager. The shared library manager insures that all serial numbers of valid clients are at least greater than the global start serial number.
If this test succeeds, then the algorithm loops to block 152 where it is determined whether the class link pointer in the client Viable is null. If it is null, then the algorithm branches to block 161 in Fig. 6B. However, if the pointer is p not null, then the class record is retrieved based on the information in the link pointer.

WO 95/01598 'T ', t~ '' ' ~ PCT/US94/07424 After retrieving the TClass record, the class serial number in the client Viable is compared with the same in the TClass record. If they do not match, then the algorithm branches to block 161. If they do match, then the library record TLibrary for the class is retrieved from the information in TClass (block 155). The library record indicates whether the VTables for the class are initialized (block 156). If they are not, then the algorithm branches to block 162. If they are initialized, then the "code" serial number in the client Viable is compared with the same in the library record (block 157). If they do not match, then the algorithm branches to block 162.
If the code serial numbers match, then the class Viable record is returned in response to the information in the TClass record (block 158).
After retrieving the class Viable record, the class Viable record use count is incremented as well as the library use count (block 159). After block 159, the algorithm is done, as indicated in block 160.
Fig. 6B illustrates the routine for handling the branches from' blocks 152, 154, 156, and 157. For branches from blocks 152 and 154, this routine begins with block 161 which calls a lookup class function to get the TClass record from the class catalog (block 161). After retrieving the TClass record, the class Viable record is retrieved in response to the information in TClass (block 162).
Next, the class Viable record use count and library use count are incremented (block 163).
The class Viable record is reviewed to determine whether it includes pointers to the Viable and the export table for the class (block 164). If there are pointers, then the algorithm is done (block 165). If not, then a set up function is called to initialize the class Viable record (block 166). The setup function is described in Fig. 6C. This algorithm begins with an access to the library record to determine whether the code is loaded (block 167). If the code is loaded, then the library use count is incremented (block 168). If the code is not loaded, then the library is loaded, and its use count incremented (block 169).
After either block 168 or 169, the client Viable record is retrieved from the library, and the pointer to the class Viable record is retrieved (block 170).
The pointer taken from the client Viable record in the library is used to get the class a WO 95/01558 ~ PCT/US94/07424 VTable record (block 171). Next, the cache links in the client VTable record in the client, and the same in the loaded library, and the cache links in the TClass record are updated with information about the class VTable record (block 172).
Finally, the algorithm is done (block 173).
Fig. 7 is a schematic diagram of the structure for the library's files which can be dynamically registered in the class catalog. The library files are normally stored on disk 200. These library files are registered in an extensions folder which is graphically illustrated on the user interface of the device, such as the Macintosf~ computer. The extension folder includes a number of management files 202, and a plurality of library files 203, 204, 205. The library files are all registered in the class catalog. The library files having a file type "libr"

include a number of segments, including code resources 207, a dictionary "libr"
resource 208, and dictionary "libi" resource 209. The code resources 207 include the library code segments such as classes and generic function sets. The dictionary "vibr" resource describes the library. Dictionary "libi" resource lists libraries which this library depends on. The dictionary "libr" resource 208 is shown in more detail at block 210. This resource includes a library ID field 211 which is the character string identifying the library. A second field 212 in the structure 210 identifies the code resource type. A third field 213 identifies the template version number for the library file. A fourth field 214 identifies the version number of the library, which is maintained according to a standard protocol by the developers of the libraries. The next field 215 stores a plurality of library flags. The next field 216 identifies the number of elements in an exported class information array 217.
This information array 217 includes one record per exported class in the library.
Each record includes a class identifier 218, class flags 219, a version number of the current version of the class 220, a minimum version number for the backward compatible version number for the class 221, a number 222 which indicates the number of elements in the following array 223 of parent class IDs. The array of parent class IDs includes the identifier of each parent of the class. The information in this resource 210 is used to create the class information records for the class catalog upon registration of the library.

WO 95/0159s t ~ $,~ ~, ~ d PCT/US94I07424 Fig. 8 illustrates the basic algorithm for dynamically registering libraries using the structure of Fig. 7.
As indicated at block 300, the operating system designates a special folder.
such as Extensions folder 201 in Fig. 7, and applications may designate additional folders for registered libraries.
The Library Manager intercepts operating system calls which indicate a file has been copied or moved. Then it is determined whether the file subject of the call is in the special folders or one of the additional folders (block 301).
If a new file is found, then it is determined whether the new file is a shared library resource. If it is, then library is registered in the class catalog by providing information to fill the TClass records for the classes in the class catalog (block 302). If a library has been moved out of the folder, then the library manager will leave it registered until it is no longer in use. After it is no longer in use, then it is moved out of the class catalog (block 303).
The shared library manager also provides functions which are linked to the clients, and allow them to take advantage of the class catalog for various functions.
Particular routines include a new object routine which is described with reference to Figs. 9A and 9B, a variant of the new object routine shown in Fig. 10, a verify object routine shown in Fig. 11, a cast object routine shown in Fig. 12, and a GetClassInfo routine shown in Fig. 13.
As indicated in Figs. 9A-9B, the new object routine takes as input the class identifier for the new object and an indication of a memory pool for allocation of the object (block 320). Using this information, it is determined whether the memory pool has actually been allocated for the object. If not, then the pool is allocated (block 321). Next, a lookup class function is called in the class catalog to get the TClass object for the identified class (block 322). Next, flags maintained in the TClass object indicate whether the new object routine is supported for the particular class (block 323). If it is supported, then it is determined whether the TClass record for the class is associated with a library other than the rat library. If it is a root library class, then it is guaranteed to be always loaded, and the use content is incremented (block 324).

t .i ( 4 If the class is associated with a library other than a root library, a load function is called to either load the library and then increment the use count, or if the library is already loaded then just increment the use count (block 325).
Next, the TClass object is used to retrieve the class VTable record (block 326). Using the flags in the class VTable record, it is determined whether the new object routine is supported for the class (once again) (block 327).
Next, the size of the object is determined from the class VTable record, and memory of that size is allocated to the pool (block 328). Next, a pointer to the allocated memory is retrieved (block 329). The library manager requires that the se~~cond slot in the export table for classes in the library contain a pointer to a constructor for the class. Thus, the pointer for the constructor is retrieved from the export table location indicated in the class VTable record (block 330).
Using the constructor pointer, the constructor is called which places an object in the allocated memory (block 331).
Next, the use count is decremented by one to balance the use count (block 332). This is required because the load function step of block 325 increments the use count, as does the calling of a constructor in block 330. Thus, the decrementing of the use count is required for balancing the use counts. After the decrementing of use count in block 332, then the algorithm is done (block 333).
Tlws, a client is able to obtain and call a constructor for a class of which it was not aware at compile time.
Fig. 10 illustrates a variant of the new object routine which has better type safety. In particular, if the client is aware of the parent of the new object to be created, then the variant of Fig. 10 can be called. The variant of Fig. 10 takes as input the parent identifier for the parent of the class, the class ID of the new object to be created, and the memory pool allocation parameters (block 340). Next, a verify class function which is described with respect to Fig. 11 is called to insure that the identified class is derived from the identified parent (block 341).
If this verification is successful, then the new object routine of Figs. 9A and 9B is called for the identified class (block 342). (See Appendix, TLibraryManager::NewObject (two variants)).

WO 95/01598 ° PCT/CTS94/07424 ~~~s~o~ ~ ~ ~ v~
Fig. 11 illustrates the verify class routine called in block 341 of Fig. 10.
Also, this routine is available to the clients directly. The verify class routine begins by taking the class ID of the base class and of a derived class (block 350).
Next, the lookup class function of the class catalog is called to get the TClass record for the derived class (block 351). The TClass record for the derived class will include a list of parent classes. This list is reviewed to determine whether the identified parent class is included (block 352). If the parent class is found, then the algorithm is done (block 353). If the parent class is not found, then go to the TClass record of each parent of the derived class in order. The list of parents for each parent is reviewed to find the identified parent class, following this recursion to the root class. The algorithm ends when the parent is found, or the root class is reached. (See Appendix TLibraryManager:: VerifyClass and : . internal VerifyClass).
If there is more than one immediate parent in the list of parents for the TClass record, then a case of multiple inherency is found. In this case, the parent class hierarchy must be reviewed to insure that at least one parent appears as a virtual base class (block 355). If the identified parent in the call of verify class is not found as a virtual base class, then it is determined not related to the derived class for the purposes of this function.
Fig. 12 is a flowchart for a cast object routine executed by the shared library manager and linked to the clients by the required structure of the objects of the shared library manager environment. Using this function, a client can cast an object of a derived class as a parent class object, even though it may not have been aware of the structure of the parent at the time it was compiled. This algorithm takes as input a pointer to the object and an identifier of the parent class (block 400). Next, the class of the object is determined based on the required structure of the object (block 401). This structure involves placing the pointer to the VTable as the first data member in the object. Also, the first slot in the VTable is a pointer to the VTable record of the shared library manager.
Using the class ID of the object determined from the class VTable record, and the parent ID provided when cast object was called, the verify class routine WO 95/0159 j , PCT/US94107424 is then called (block 402). If the verify class succeeds, then it is determined from the class Viable record of the object, whether single or multiple inheritance is the case is found (block 403).
If a case of single inheritance, then the algorithm is done because the offsets are determinate in that case (block 404). If a case of multiple inheritance is encountered, then the correct offsets are found within the object to the data of the parent class (block 405). This can be determined based on the place of the parent class in the hierarchy of parent classes found in the TClass records. (See Appendix TLibraryManager::CastObject and ::interact CastObject).
GetClassInfo is a member function of TLibraryManager, or a non-member function is provided which calls gLibraryManager- > GetClassInfo for you.
Given a class id which specifies a given base class and an error code pointer it returns a TClassInfo for the given class if the class is registered in the class catalog. The TClassInfo can then be used to iterate over all of the derived classes of the given base class. If the class is not registered or an error occurs GetCIassInfo returns MULL. (See Appendix, TLibraryManager::The GetClassInfo).
The GetClassInfo algorithm is shown in Fig. 13. It involves the following:
Steps:
1. Call the LookupClass function with the class id. If this returns a pointer that is not NULL then we know that the class is registered with the class catalog. If it returns NULL then set the error code to kNotFound and return NULL for the function return value (block 500).
2. Using the fCla,sses field of fCla.ssCatalog, which is a TCollection class instance, call the CreateIterator function. If the iterator cannot be created then return NULL for the function return value and set the error code to kOutOfMemory (block 501).
3. Create a TClassInfo instance and set the flterator field to the iterator returned in step 2. Set the fBaseClassID field to the given class id. If the TClassInfo cannot be created then return NULL as the function return value and set the error code to kOutOfMemory (block 502).

,.
4. Call the Reset function of the iterator to re-start the iteration. Return the TClassInfo as the function return value and set the error code to kNoError (block 503).
The functions of TClassInfo which include using the TClassInfo instance returned by GetClassInfo::
virtual void Reset();
virtual void* Next(); // safe to cast to TCIassID* or char*
virtual Boolean Iteration Complete() const;
// TClasslnfo methods TCIassID* GetCIassIDp;
Boolean GetCIassNewObjectFlag() const;
Boolean GetClassPreloadFlagi) const;
size~t GetCIassSize() const;
TLibrary* GetLibrary() const;
TLibraryFile* GetLibraryFile() const;
unsigned short GetVersion() const;
unsigned short GetMinVersion() const;
Copyright Apple Computer 1991-1993 Data members of TClasslnfo include:
TCIassID fBaseCIassID;

TCIassID fCIassID;

TLibrary* fLibrary;

TLibraryFile* fLibraryFile;

unsigned short fVersion;

unsigned short fMinVersion;

Boolean fNewObjectFlag;

Boolean fPreloadFlag;

Boolean fFunctionSetFlag;

Boolean fFiller;

size t fSize;

Tlterator* flterator;

TClass * fClass;

Copyright Apple Com puter 1991-1993 Reset - starts the iteration over from the beginning.
Next - gets the next derived class in the list.
IterationComplete - returns true if Next has been called for all derived classes of the given base class.

WO 95/0159'8 ~ PCT/US94/07424 GetClassID - returns the class id of a derived class (fClassID).
GetClassNewObjectFlag - returns true if the class id returned by GetClassID
can be used to create an object using the NewObject function.
GetClassPreloadFlag - returns true if the class is preload flag is set to preload the class implementation at boot time.
GetClassSize - returns the size of the data structure for an instance of the class.
GetLibrary - returns the TLibrary for the class.
GetLibraryFile - returns the TLibraryFile for the class.
GetVersion - returns the current version of the class.
GetMinVersion - returns the minimum compatible version of the class.
The algorithm for TClassInfo includes the following steps.
1. When the TClassInfo is created the fBaseClasslD field is set to the class id passed to GetClassInfo, the flterator field is set to a class catalog iterator which iterates the TClass records registered in the class catalog, and fClass is set to the TClass for the class corresponding to fBaseClassID.
2. The function Next sets the data members fClassID, fLibrary, fLibraryFile, fVersion, fMinVersion, fNewObjectFlag, fFunctionSetFlagandfSize.
It gets this information from the next TClass record, using the flterator, which has the desired "is derived from" relationship of the class given by fBaseClassID.
3. The "getter" functions listed above return the information in the corresponding data member of TIterator.
4. The first time the getter functions are called, or after Reset is called, the information returned is for the fBaseClassID class itself.
Source code for the cast object, verify class, new object and get class info routines is provided in the Appendix. Also, the Appendix provides selected class interfaces and functions which may be helpful in understanding a particular implementation of the present invention, when considered with the detailed description of the run-time architecture which follows.
A more detailed description of a particular implementation of the shared library manager is provided below with reference to a code written for the Macintosf~ computer.

~~~.66~0~
Overview The Shared Library Manager (SLM) described herein provides dynamic linking and loading facilities for the 68K Macintosh. The system can be adapted to any platform desired by the user. SLM provides dynamic loading, a.k.a. on-demand loading, both for procedural programs and for C++ programs. This is different from the traditional approach of launch-time loading, also referred to as "full transitive closure" , which means that all required libraries are loaded and relocated at once when an application is launched.
SLM provides procedural programming support for exporting and importing functions from C, Pascal, Assembler, or any language with compatible calling conventions. In addition, SLM provides extensive support for exporting and importing C++ classes, with an emphasis on providing the dynamic features which are fundamental to building extensible applications and system components for Macintosh.
Shared libraries can be installed at any time and called in a transparent fashion. There is no dependency when building a client on where the libraries that it uses are, what the filenames) are, or how many of them may eventually be used during a session. The libraries are loaded and unloaded dynamically based on use counts. The SLM takes care of all of the details of binding and loading, and the client only has to know the interfaces to the classes and functions that it wants to use.
SLM provides facilities for instantiating objects by class name, for enumerating a class hierarchy, and for verifying the class of an object or the class of a class.
Basis of the architecture The architecture for SLM is based on the 68K run-time architecture and the MPW tools architecture. A build tool, for the SLM takes an exports file (.exp) and an MPW object file (.o) as input and generates a library file. It does this by t processing these files and then calling the MPW linker to finish the job.

" ~ . #
For C++ libraries, SLM is based on the MPW/AT&T 2.1 CFront v-table dispatching model. Development tools must generate v-tables compatible with this model. In particular, we assume that the first entry in the v-table is not used --' S:C.M uses it to point to class "metes-data".
SLM also requires the v-table pointer to be the first data member in an object in order for certain functions to work. Since these functions do not know the class of the object (their job is to find out the class) they can only find the class metes-data via the v-table pointer if it is in a known place in the object.
It is theoretically possible for SLM to support more than one dispatching model, however for interoperability it would not be desirable to have more than one model. A dispatching agent could arbitrate between different dispatching models or even different calling conventions which would introduce considerable nm-time overhead. It would be possible for different dispatching models to co-exist and yet not intemperate.
SLM and 68K libraries support both single (SI, SingleObject rooted) and multiple inheritance (non-SingleObject rooted) classes.
A development tool wishing to support the SI M in a non-MPW environment will need to generate a 'libr' resource, a set of code resources, and optionally, a 'libi' resource, a shown in Fig. 7. The jump table resource is not modified at build time -- it is a normal model far jump table. It is modified by SLM at load time but the build tools don't need to be aware of this. The glue that does 32-bit relocation and the data initialization glue are code libraries statically linked into the library initialization segment.
Shared libraries have a jump table resource ('code' 0) plus an initialization code segment ('code' 1) plus at least one implementation segment ('code' 2 and up). If more than one library is in a library file then the resource type for each set of code resources must be unique (usually 'cd01', 'ed02' etc.).
~.,ibrary resource - Specifies the type of the 'code' resources, and the classes and function sets exported by this library. Of course, the resource ID for each 'libr' resource in a file must be unique.

~'VO 95/01598 ' PCT/US94/07424 ~. 6~0~
Jump Table resource - Always present in the file, present in memory only if -SegUnload option is used to SLMBuilder. Note that NoSegUnload is the default.
Initialization code segment resource - Only contains code linked to % ASInit or ASInit segment and used at initialization time, must not contain any other code unless -SegUnload option is used to SLMBuilder.
Implementation code segrnent(sl - Contains any implementation code for the library, including the CleanupProc if any. Often libraries will have only one implementation segment although there is no harm in having more.
Implementation segments are numbered 2 and up.
When the SLM loads a library, the jump table resource is loaded, plus the initialization segment. After initialization this segment is released -- it will not be needed again unless the library is unloaded and then reloaded.
If the "NoSegUnload" option is used (NoSegUnload option to LibraryBuilder is the default) then all code segments are loaded. The jump table plus the relocation information generated for each segment is used to relocate the jump table based addresses in the code to absolute addresses pointing to the target function in the target code resource. The jump table resource is then released.
When using this option the library should normally have only one implementation segment but this is not a requirement.
If the "SegUnload" option is used (SegUnload option to LibraryBuilder) then the implementation segment is loaded, plus any segments designated preload (preload resource bit can be set on a per-segment basis from a statement in the .r file), or all segments are loaded if a library itself is designated preload (preload flag in the Library descriptor). Each jump table based reference in the code is relocated to point to the absolute address of the jump table entry. The jump table is modified to contain pc-relative jsr instructions instead of segment loader traps. "
The jsr goes to the SLM segment loader entry point just before the jump table (in the 32 byte gap). This limits the size of the jump table to 32K, which should not be a problem since libraries should not be huge bodies of code -- library files can easily have multiple libraries in them if packaging is an issue. It is a jsr and not a jmp since the segment loader uses the return address, which now points to the last two bytes of the jump table entry, to compute which segment is to be loaded.
At load time the SLM moves the segment number information out of the jump table entry to an array following the jump table. This is due to the fact that the jsr pc relative takes 2 more bytes than the original segment loader trap. Note that all the machinations on the jump table are transparent to a tool developer.
A segment is loaded when a jump table (jt) entry is called and the jump table is then modified to contain an absolute jump for all jt entries for that segment. When segments are unloaded, the pc relative jsr is put back in the jump table for each entry for that segment.
The data segment based addresses (the "global world", i.e. what would have been A5 based) are relocated to the absolute address of the data.
Building a shared library Any application, extension, driver, or other stand-alone code resource on the Macintosh can use shared libraries. Of course, a client can also be another shared library. A shared library can import and export functions or classes. A
nan-library client (for brevity, an "application") can only import functions or classes. An application can sub-class an imported class, but it cannot export a class. This is a minor limitation since an application can contain shared libraries as resources in the application itself, or register a special folder containing shared libraries that are effectively part of the application.
The Shared Library Manager accomplishes it's sharing by examining and modifying the object file destined to become a shared library. It generates several source and resource files that are then used to create the shared library and to provide clients with linkable "stubs" to gain access to the functions and classes in the shared library. In the sections which follow, we will examine each of these files.

Dispatching Architecture First and foremost of the files generated by the SLM LibraryBuilder tool is the file SharedLibTemp.stubs.a. This is an assembly language file that contains the stubs for all of the functions that are exported. Exported functions fall into five categories. They are: 1) function set function; 2) class constructor; 3) class destructor; 4) class virtual functions; and 5) class non-virtual functions.
There is a separate dispatching function for each of these classifications, and the stubs are generated slightly different for each. Each one will be examined in detail shortly.
For the purposes of explaining the architecture, an exported function in a function set will be used.
For each dispatching function, there are 5 parts. The first two parts are supplied by the build tool, and are unique for each function. The other 3 parts are supplied by the SLM.
The first part is a structure called a stub record (see Fig. 6).
_stbSample RECORD EXPORT , IMPORT _CVRExampIeFSet:Data DC.L 0 DC.L _CVRExampIeFSet DC.L 0 DC.W 3 EN DR
Copyright Apple Computer 1991-1993 The stub record contains 2 fields used internally by the Shared Library Manager (the first and third fields in the example shown above). The second field is apointerto the ClientVTableRec. The ClientVTableRec is a structure (see Fig. 6) that is linked with the application that has all of the information that the SLM needs to dynamically fmd and load the function set or class referenced by the stub.
This is the "C" definition of the ClientvTableRec:
struct ClientVTabIeRec -TLink'" fClassLinkPtr;

long fCIassSeriaINumber;

long fCodeSeriaINumber;

short fVersion;

WO 951015913 , PCT/US94107424 short fMinVersion;
char fCIassIDStr[21;
};
Copyright Apple Computer 1991-1993 The fClassLinkptr field contains information used by the SLM to cache ' the link to the internal TClass object which contains all of the information known about the class or function set. The two serial number fields are used to insure that the cached information is still valid (if the library unloaded and a new version of a class or function set in the library was dragged into a registered folder, any cached information is invalid). The version number fields contain information about the version number of the class or function set that your application (code resource, extension, etc.) linked with, and the fClassIDStr field contains the actual ClassID of the class or function set so that it can be found in the SLM
catalog.
The last field in the stub record is an index. It tells the SLM which entry in the function set VTable contains a pointer to the desired function.
Most stub dispatching comes in 3 speeds - very fast, fast, and slow. Very fast dispatching occurs when you have already used the function before. In this case, the first field of the stub record contains the address of the actual function, and can be called immediately. If you have never called this function before, then a dispatching stub is called which causes the SLM to examine the ClientVTableRec. If you have already used another function in this same class or function set, then the ClientVTableRec already contains cached information as to the location of the tables containing the function addresses. In this case, your stub is updated so that the address of the function is cached for next time, and the function is then called. If the ClientVTableRec does not contain cached information, then the SLM must look up the class or function set by the . 30 ClassID stored in the ClientVTableRec, load the library containing the class or function set if it is not already loaded, update the cached information in the ' ClientvTableRec, update the cached information in the stub, and then finally call the function.

~'VO 95/01598 PCT/US94/07424 The second part of the dispatching mechanism is the actual stub code that a client links with:
Sample PROC EXPORT
IMPORT _stbSample:Data _ IF MODEL = 0 THEN
lea stbSample,a0 ; Get the stub record into a0 ELSE
lea t stbSampIel.L,aO "
ENDIF
move.l (a0),d0 ; Get the cached function address beq.s @1 ; Not cached - do it the hard way move.l d0,a0 ; Get address into a0 jmp (a0) ; and jump to it IMPORT _SLM1 1 FuncDispatch @1 IF MODEL = 0 THEN
jmp SLM 1 1 FuncDispatch ; More extensive dispatching needed ELSE
jmp ( SLM1 1 FuncDispatch).L
EN D
IF MACSBUG = 1 THEN
it DC.B 580, 506 DC.B Sample DC.w 0 ENDIF
ENDP
Copyright Apple Computer 1991-1993 Normally two (or maybe four) versions of the stub are assembled - one in model near (MODEL = 0), and one in model far (MODEL = 1). There may also be debugging versions generated with Macsbug symbols for each (MACSBUG
= 1).
Notice that the first thing that the stub does is to check whether the first field of the stub record is non-zero. If it is, it just jumps through the pointer stored there. Otherwise, it calls a first level dispatching function called SL1~11FuncDispatch (or one of the other 4 variations of this function).
This function is the third part of the dispatching code:
SLM11 FuncDispatch PROC Export move.l 52B6,a1 move.l 510CIa1 ),a1 move.l SLMGIobaLfStubHelp+16ta1),a1 IF MODEL = 0 THEN

WO 95/01598 ' k PCT/LTS94/07424 move.l _gLibraryManager,d0 ELSE
move.l ( gLibraryManager).L,dO
ENDIF
jmp (a1 ) ENDP
Capyright Apple Computer 1991-1993 The first two instructions fetch the SLM globals. The SLM stores it's global information in a low-memory structure known as the ExpandMemRec (location $2B6 in the Macintosh contains a pointer to this structure). The SLM global information is stores as a pointer at offset $ l OC in this structure. One of the fields in this structure contains a vector of dispatch functions. This dispatcher uses the 5th element in the vector to dispatch through (this is the vector to dispatch functions in function sets).
The code for this dispatching function (and the other four variations) are supplied in LibraryMa.nager. o and LibraryManager. n. o, so clients can link with it.
The fourth part of stub dispatch is the second level dispatching function that is stored in this vector:
SL.MFuncDispatch PROC Export move.l d0,-!sp); Push the library manager move.l a0,-(sp); Push the stub record move.l d0,a0 ; Put TLibraryManager into a0 move.l 20fa0),a0; Get the class catalog move.l a0,-isp) move.l (a0),a0 move.l CatVTabIe.LookupFunction(a0),a0 jsr (a0) ; Call the LookupFunction method lea 12(sp),sp; Drop parameters move.l d0,a0 ; Get the function jmp (a0) ; Call it Copyright Apple Computer 1991-1993 This dispatcher calls a function in the TClassCatalog object, which is the fifth and final part of stub dispatch. A partial declaration for TClassCatalog follows.
#define kTCIassCataloglD "lSccat,l.1"

WO 95/01598 . PCT/><JS94/07424 typedef ClientVTabIeRec CVR;
typedef FunctionStubRec FSR;
typedef void (*VF)(void);
typedef Viable VF(l;
class TCIassCatalog : public TDynamic TCIassCatalog();

virtual --TCIassCatalog();

//

// These first ons are here for backward compatibility with functi // SLM 1 .0 //

#if COMPAT10 virtual VR ExecDestructor(CVR*) const; -virtual VR ExecConstructor(CVR*, size_t idx) const;

virtual VR ExecVTabIeEntry(CVR*, size_t idx) const;

virtual VR ExecExportEntry(CVR*, size_t idx) const;

virtual void ExecFunction(FSR*, TLibraryManager*) const;

virtual VR ExecRootDestructorICVR*) const;

virtual VR ExecRootConstructor(CVR*, size_t idx) const;

virtual VR ExecRootVTabIeEntry(CVR*, size t idx) const;

virtual VR ExecRootExportEntry(CVR*, size t idx) const;

#endif virtual VF LookupFunction(FSR*, TLibraryManager*);
virtual VTabIeRec* GetVTabIeRecMemorylsize_t num) const;
virtual VTabIeRec* Init1 VTabIeRec(VTableRec*, ProcPtr setupProc, CVR* client) const;
virtual VTabIeRec* InitVTabIeRec(VTabIeRec*, Viable viable, Viable exportTable, CVR* parent, long size, char*) const; ' virtual VTabIeRec* InitVTabIeRec(VTabIeRec*, Viable exportTable, char*) const;
#if COMPAT10 virtual VTabIeRec* GetGenVTabIeRec(CVR*) const;
#endif virtual VTabIeRec* LookupVTabIeRec(CVR* theClient) const;
virtual VTabIeRec* GetVTabIeRec(CVR*, Boolean isSub) const;
virtual VTabIeRec* ReleaseVTabIeRec(CVR*) const;
virtual OSErr InitLibraryManager(TLibraryManager**, long*, size t poolsize, ZoneType theZone, MemoryType theMemType); ' virtual Boolean CleanupLibraryManager(TLibraryManager**);
virtual VF GetDestructor(FSR*, TLibraryManager*) const; ' virtual VF GetConstructor(FSR*, TLibraryManager*, Boolean isSub) const;

95/0159~B ~ PCT/US94/07424 };
virtual VF GetVTabIeEntry(FSR~', TLibraryManager*') const;
virtual VF GetExportEntry(FSR*', TLibraryManager*') const;
virtual VTabIeRec*' GetParentVTabIeRec(CVR~') const;
Copyright Apple Computer 1991-1993 There are five routines in the TClassCatalog, corresponding to each of the five dispatch methods. They are: 1) LookupFunction; 2) GetConstructor; 3) GetDestructor; 4) GetVTableEntry; and 5) GetExportEntry.
It is not necessary that any generated code know vtable offsets into the class catalog. These offsets are known by the vectorized dispatch code. In fact, the dispatch code was vectorized specifically so that offsets in the TClassCatalog cauld change without causing recompilation of clients.
This fifth and final dispatch routine does the actual fording of the class, and staring of any cached values.
In the code examples that follow, code and structures that have a bold header and trailer is code that must be generated by a build tool in order to create a shared library. Code that is not in bold is shown only for reference.
Generating Function Set Code To import a function a client has to include the interface file when compiling (in C, the .h file), and link with client object file (.cl.o or .cl.n.o) provided by the library developer. The client object file contains the client stubs far the functions that the client calls.
Consider the following example function set which is exported by the ExampleLibrary.
This ~ is the FunctionSet declaration in the exports file (FxampleLibrary.exp):
FunctionSet ExampIeFSet id = kExampIeFunctionSet;

~'VO 95/01598 PCT/US94/07424 /l ' ' // We could use the following export line, but we want all exported // functions from the library to be exported, so we say nothing!
//
// exports = Hello, extern HeIIoC, Pascal extern HeIloPascal, Goodbye, // Pascal GoodbyePascal, TExampIeCIass::Test;
};
Copyright Apple Computer 1991-1993 These are the prototypes from the interface file (ExampleLibrary. h) char'' Hello(ulong&);
char' Hello(ulong'');
extern "C" char'" HeIIoC(ulong~');
ulong Goodbye();
Pascal Ptr HeIloPascal(ulong& theHeIloTicks);
Pascal ulong GoodbyePascall);
Copyright Apple Computer 1991-1993 Function set function dispatching <stubsl The build tool, Libr3ryBuilder, generates stubs to be linked with the client for each FunctionSet function exported by a given library.
~ A stub is generated for each function. Here is the stub record and the stub that is generated for the "HelloC" function (in SharedLibTemp.stubs.a):
_stbHeIloC RECORD EXPORT
IMPORT _CVRExampIeFSet:Data DC.L 0 DC.L _CVRExampIeFSet DC.L 0 DC.W 3 ENDR
HeIIoC PROC EXPORT
IMPORT _stbHeIloC:Data IF MODEL = 0 THEN
lea _stbHeIloC,aO
ELSE
lea ( stbHeIloC).L,aO
ENDIF
move.l (a0),d0 ' beq.s @1 move.l d0,a0 jmp (a0) "
IMPORT SLM11 FuncDispatch @1 IF MODEL = 0 THEN
jmp SLM 1 1 FuncDispatch ELSE

jmp ( SLM1 1 FuncDispatch).L

END

IF MACSBUG = 1 THEN

its DC.B $80, SOB

DC.B 'stub HeIIoC' DC.W 0 ENDIF

ENDP

Copyright Apple Computer 1991-1993 This is the structure of the stub record in C:
struct FunctionStubRec VirtuaIFunction fFunction;

ClientVTabIeRec'~ fClientVTabIeRec;

FunctionStubRec* fNextStubRec;

unsigned short fFunctionlD;

}:
Copyright Apple Computer 1991-1993 When the stub is called, it first checks to see if the address of the function is already cached. If so, it jumps immediately to the function. Otherwise, it jumps to the function dispatcher LSLMIIFuncDispatch) with the stub record as a parameter in register A0. The stub dispatcher then obtains the address of the actual dispatching code from a low-memory global set up when SLM was originally loaded, and it jumps to that code. This extra indirection allows SLM
the flexibility to modify the function loading and dispatching mechanism without affecting client code (since clients are linked with the SLMIIFuncDispatch code).
~ This is the function dispatcher that is linked with the client.
aLM1 1 FuncDispatch PROC Export move.l S2B6,a1 " move.l S10C(a1),a1 move.l SLMGIobaLfStubHelp+16(a1),a1 IF MODEL = 0 THEN
" move.l gLibraryManager,d0 ELSE
move.l ( gLibraryManager).L,dO

216~3~~
ENDIF
jmp (a1 ) ENDP
Copyright Apple Computer 1991-1993 ~ This is the actual function dispatcher that is linked with the Shared Library Manager for reference: ' iSLMFuncDispatch PROC Export move.l d0,-(sp) ; Push the library manager move.l a0,-(sp) ; Push the stub record move.l d0,a0 ; Put TLibraryManager into a0 GetCIassCatalog a0 ; Get the class catalog into a0 move.l a0,-(sp) ; Push it move.l (a0),a0 ; Get the VTable move.l CatVTabIe.LookupFunction(a0),a0 ; Get the function jsr (a0) ; Call it lea 12sp),sp ; Pop the parameters move.l d0,a0 ; Get the function address jmp (a0) ; jump to it ENDP

Copyright Apple Computer 1991-1993 The CatVTable . Lookup Function is a call to the TClassCatalog: :LookupFunction method.
~ A ClientvTableRec is generated per function set (to be linked with the client in SharedLibTemp . stubs . a):
_CVRExampleFSet RECORD EXPORT
DC.L 0, 0, 0 DC.W 50100 DC.W 50000 DC.B 'appl:examSExampIeFSet', 0 ENDR
Copyright Apple Computer 1991-1993 Function set function dispatchin~Initialization) The initialization code is generated in two files:
SharedLibTemp . init . a and SharedLibTemp . init . c. Most of the generated code is in "C", but for each class or function set, a ClientvTableRec is generated which is put into the assembly file. It is possible to put the ClientVTableRec definition in "C" (the inline "C"-string -34- .

WO 95101598 ~ PCT/US94/07424 makes it a little more challenging, but it can be done), but we chose to leave it in assembly. Strictly speaking, if your initialization code is going to link with your stub library, a ClientV~rableRec does not need to be generated for ' initialization, but it makes things easier just to generate one as a matter of course.
~ The vector table is generated into SharedLibTemp.Init.c (to be linked with the library):
typedef void ('"ProcPtr)(void);
ProcPtr _vtbl_ExampIeFSet[I =
{
0, // First entry is normally 0 (ProcPtr)Hello FRUI, (ProcPtr)Hello FPUI, (ProcPtr)HeIIoC, (ProcPtr)HELLOPASCAL, (ProcPtr)Goodbye_Fv, (ProcPtr)GOODBYEPASCAL, (ProcPtr)Test l3TExampleCIassSFUI, (ProcPtr)Test 13TExampIeCIassSFPc, 0, };
Copyright Apple Computer 1991-1993 The SLM allows functions to be exported by name, as well. If any functions are exported by name, one more structure is created. Assuming that the HelloC routine and the GOODBYEPASCAL routine were'to be exported by name, the following extra code would be generated:
static char _Str_Sample 2[) _ "HelloC";
static char _Str_Sample_2p = "GOODBYPASCAL";
chary SampIeNameStrucll =
f (char')-1 L, (char')-1 L, _Str Sample_1, (chart)-1 L, _Str Sample 2, };
Copyright Apple Computer 1991-1993 Any slot corresponding to a function that is not exported by name is filled with a (char*)-1L. A slot with a NULL (0) pointer terminates the list of names.
A pointer to this list of names is stored in the first entry of the vector table:
ProcPtr vtbl ExampleFSet[] _ {
iProcPtr)SampIeNameStruc, (ProcPtr)Hello FRUI, (ProcPtr)Hello FPUI, (ProcPtr)HeIIoC, (ProcPtr)HELLOPASCAL, (ProcPtr)Goodbye-Fv, (ProcPtr)GOODBYEPASCAL, (ProcPtr)Test 13TExampIeCIassSFUI, (ProcPtr)Test 13TExampIeCIassSFPc, 0, };
Copyright Apple Computer 1991-1993 ~ An initialization function is generated for each function set.
First, let's show you the header generated for the initialization file (generated in SharedI~ibTemp.iait.c):
typedef struct ClientVTableRec {
long 11;
long 12;
long 13;
short v1;
short v2;
char name[);
} ClientVTabIeRec;
void Fail(long err, const char* msg);
extern void** gLibraryManager; // A convenient lie!
extern void pure virtual called(void);

typedef void *ProcPtr)(void);
( typedef struct _mptr { short o; short i; ProcPtr func; } mptr;

typedef ProcPtr*
VTable;

typedef void*SetupProc)(void*, unsigned int);
( typedef void* (*Init1 VTabIeRecl(void*, void*, SetupProc, ClientVTabIeRec*);

typedef void* (*InitVTabIeRec)(void*, void*, VTable, VTable, ClientVTabIeRec*, unsigned int, char*);

typedef void*(*GetVTabIeRec)(void*, ClientVTabIeRec*, unsigned char);

typedef void* (*ReleaseVTabIeRec)(void*, ClientVTabIeRec*);

typedef void* (*InitExportSet)(void*, void*, VTable, char*);

typedef void* (*GetVTabIeMemory)(void*, unsigned int);

WO 95/0159a PCT/US94/07424 ~~ 663 ~.~
#define GetCIassCatalog ( gLibraryManagerf5l) Copyright Apple Computer 1991-1993 . 5 Now the SVR (SVR stands for Setup VTableRec) function (generated in SYiaredLibTemp. init. c):
. #pragma segment A5lnit void SVRExampleFSet(void*' vtRec, unsigned int vtRecSize) {
register ProcPtr toCall;
void** catalog = GetCIassCatalog; // Get Class Catalog void * * ctVTable = *catalog; ' // Get it's VTable //
// Get pointer to 22nd entry, which is InitExportSet // function //
toCall = (ProcPtr)ctVTablef22);
//
// Call it with the following parameters:
// 1 ) The pointer to the class catalog // 2) The vtable record pointer passed in to your function // 3) A pointer to the vtable we created for the function set.
// 4) A zero for future expansion /I
(*llnitExportSet)toCall)(catalog, vtRec, vtbl ExampIeFSet, 0);
Copyright Apple Computer 1991-1993 The first parameter to the SVR function is known as the VTableRec.

This is the definition of the VTableRec structure. This information is for reference only.

struct VTabIeRec {

VTable fVTabIePtr;

VTablo fExportTable;

TUseCount fUseCount; // "long" in size void* fReserved;

ClientVTabIeRec* fParentClientPtr;

unsigned short fSize;

unsigned fParentlsVirtual:l ;

unsigned fFiller:1;

unsigned fCanNewObject:1;

unsigned flsFunctionSet:1;

unsigned flsRootClass:1;

unsigned fLocaICVRIsParent:l ;

unsigned flsParentVTabie:1;

unsigned filsMasterOrLast:1;
unsigned char fDispatcher;
ClientVTabIeRec*' fLocaICIientPtr;
union {
SetupProc fSetup;
TRegisteredObjects*' fRegisteredObjects;
};
}; , Copyright Apple Computer 1991-1993 The VTableRec is used internally by the SLM to keep track of information about each function set or class. Library initialization code supplies ali of the information the SLM needs to fill in the VTableRec.
~ One initialization function per library is generated which calls the SLM
to register all of the ClientVTableRecs and SVR functions. This example shows initialization for the example library, which has the function set ExampleFSet and the class TExampleClass. Those parts of this code that you would change depending on what you are initializing are underlined.
#pragma segment A5lni voids InitVTableRecords(void) register ProcPtr toCall;
void vtRec;
void'' savedRec;
void*'' catalog = GetCIassCatalog; // Get Class Catalog void'' ctVTable = *catalog; // Get it's VTable //
// Get the pointer to GetVTabIeMemory, and call it, asking /l for memory for 2 VTabIeRecs (Of course, you would ask for // the number of VTabIeRecs that you need).
//
toCall = (ProcPtr)ctVTablefl9);
savedRec = (~(GetVTabIeMemory)toCall)(catalog, 2);
/l /l Get the pointer to the Init1 VTabIeRec method //
toCall = (ProcPtr)ctVTabIef201;
//
// Start 'vtRec' pointing to the memory that we got.
//
vtRec = savedRec;
// ' // Call Init1 VTabIeRec for our first export (a Class, in this /J case). Parameters are:

/l 1 ) The class catalog // 2) The VTabIeRec Memory // 3) A pointer to the "SetupVTabIeRec" procedure // 4) A pointer to the local "ClientVTabIeRec"
// The method will return a pointer to the next VTabIeRec ' // for use with additional initialization. Using this method, // it is not required for you to "know" the size of a VTabIeRec /l vtRec = (~'(Init1 VTabIeRec)toCalll(cataloa, vtRec __SVRTExampIeClass.
& CVRTExamoleClassl:
//
l/ Do it for the next export (a function set, in this example) //
1$ vtRec = (*'(Init1 VTableRec)toCall)(cataloc vtRec SVRExamoleFSet & CVRExamoleFSetl:
//
l/ Return a pointer to the original VTabIeRec //
return savedRec;
Copyright Apple Computer 1991-1993 Sin~y-Inherited Classes~stubs~
This section will examine the stub creation for a C++ class which is singly-inherited. This includes both forms of vtables - SingleObject derived, and standard AT&T v2.1 classes. Classes which are multiply-inherited (derive from more than 1 parent class) are handled in a separate section.
Here is the definition of the TExampleClass (from ExampleClass.h) #define kTExampIeCIassID "appl:examSTExampIeClass,1.1 "
class TExampIeClass : public TDynamic public:
TExampIeClass();
virtual ~TExampIeClass();
// New Methods virtual char GetObjectName() const;
virtual void SetObjectName(char ''theName);
virtual void DoThisAndThatU;
virtual void DoThat(); --virtual void SetGloballnt(long theValue);
virtual long GetGloballnt();

WO 95/01598 x 1 PCT/US94/07424 /l Public non-virtual function // Dynamically exported by using ExportFunction void GetGIobaIRef(long*'&);
// Public static function !/ Dynamically exported by the ExportFunction ' static Boolean Testtufong test);
static Boolean Testtchar'" test);
private:
char ''fName;
Il static gExampIeClassCount counts the number of instances static long gExampIeClassCount;
};
Copyright Apple Computer 1991-1993 Constructor stubs Constructor stubs are generated for each constructor of a class. If the export file specifies that no constructor stubs are to be exported (using the noMethodStubs or noStubs flag), then the constructor stubs must be created in the assembly language portion (SharedLibTemp . znit . a) of the initialization file. This is so that use counts can be properly maintained for every class.
~ A stub record is generated to be linked with both the client and the library (in SharedLibTemp.stubs.a or SharedLibTemp.init.a, as appropriate). This record is used much like the record for a function set - It contains cached information that is used to speed up the dispatching. In addition, it contains the index into the "structor table" for the actual address of the constructor (see the class initialization section for information on creating this table).
stb_ct_'! 3TExampIeCIassFv RECORD EXPORT
IMPORT _CVRTExampIeCIass:Data DC.L 0 DC.L _CVRTExampIeClass ; ClientVTabIeRec DC.L 0 DC.W 3 ; Index into table ENDR
Copyright Apple Computer 1991-1993 _40_ "' ~ A constructor stub is generated to be linked with both the client and the library (in SharedLibTemp . stubs . a or SharedLibTemp . init . a, as appropriate) ct_13TExampIeCIassFv PROC EXPORT

IMPORT stb-ct-13TExampIeCIassFv:Data IF MODEL = 0 ' LEA stb ct-l3TExampIeCIassFv,aO

ELS E

LEA ( stb ct l3TExampIeCIassFv).L,aO

ENDIF _ _ _ IMPORT SLM1IConstructorDispatch IF MODEL = 0 JMP SLM11 ConstructorDispatch ELSE

JMP ( SLMI1ConstructorDispatch).L

ENDIF

=

its DC.B 580, 51 C

DC.B 'stub ct l3TExampIeCIassFv' DC.B 0 DC.W 0 ENDIF

ENDP

Copyright Apple Computer 1991-1993 Notice that the constructor does not use any cached information to jump to the constructor directly. This is so that use counts may be updated (see the next bullet point).
~ This is the constructor function dispatcher that is linked with the client.
Tlhis is for, reference only -- the client should link with the version supplied by S~.M.
SLM 1 1 ConstructorDispatch PROC Export WITH FunctionStubRec tst.l (a0) ; Constructor pointer cached?

beq.s @2 ; No - do it the hard way move.l clientCVR(a0),a1 ; Get the ClientVTabIeRec move.l (a1 ),a1 ; Get the CIassLinkPtr move.l 4(a11,a1 ; Get the TClass move.l TCIass.vtRec(a1 ),a1 ; Get the VTabIeRec pointer addq.l #1,VTRec.useCount(a1) ; Increment the use count beq.s @1 ; Have to do the library count?

move.l (a0),a0 ; No - go on jmp (a0) ; Jump to the constructor WO 95/01598 . PCT/LTS94/07424 ;
Here, we have to bump the libraries use count - so we call the SLMConstructorDispatch function - but first, we have to back off the VTabIeRec use count we just incremented @1 subq.l #1,VTRec.useCount(a1) ; Back off the VTabIeRec use count ' @2 move.l S2B6,a1 move.l $10C(a1),a1 ' move.l SLMGIobaLfStubHelp+4(a1),a1 IF MODEL = 0 THEN
move.l _gLibraryManager,d0 ELSE
move.l ( gLibraryManager).L,dO
ENDIF
jmp (a1 ) ENDP
Copyright Apple Computer 1991-1993 Under normal circumstances, the bumping the use count of the VTableRec is all that is required, so dispatching is moderately fast. The only time that the more general dispatching mechanism needs to be invoked is if the constructor has never been invoked by the current client before, and there are no outstanding instances of this class among all clients of the SLM.
Of course, if your compiler has a different naming convention for constructors, you must generate stubs that have the same name as the ones generated (See the initialization section for more information).
~ This is the actual constructor function dispatcher that is linked with the Shared Library Manager. This is for reference only:
SLMConstructorDispatch PROC Export move.l d0,a1 ; Save the library manager in a1 moveq #1,d0 ;
We test the "this" pointer to see if it's NULL. If it is, then the object is being "newed", so we set d0 to 0, to tell the SLM
that we are fetching a primary object, and not a subclass. This allows the SLM a little more latitude in version matching.
;
tst.l 4(sp) ; Check the "this" pointer bne.s @1 moveq #O,dO
@1 move.l d0,-(sp) ; Push the "isSubClass" flag move.l a1,-(sp) ; Push the library manager move.l a0,-(sp) ; Push the stub record move.l 20(a1 ),a0 ; Get class catalog from lib mgr move.l a0,-(sp) ; Push it move.l (a0),a0 ; Get it's viable move.l CatVTabIe.GetConstructor(a0),a0 jsr (a0) ; Call the GetConstructor entry lea 16(sp),sp ; Drop parameters move.l d0,a0 ; Fetch constructor address jmp (a0) ; Jump to it ENDP

Copyright Apple Computer 1991-1993 The CatVTable.GetConstructor is a call to the TClassCatalog: :GetConstructor method.
Destructor stubs Destructor stubs are generated for the destructor of an exported class. If the export file specifies that the destructor stub are not to be exported (using the noMethodStubs or noStubs flag), then the destructor stub must be created in the assembly language portion (SharedLibTemp . /nit . a) of the initialization file. This is so that use counts can be properly maintained for every class.
~ The destructor stub is generated to be linked with both client and library (i:n SharedLibTemp.stubs.a or SharedLibTemp.init.a, as appropriate). Note that the stub record for a destructor is slightly smaller than one far a constructor or a normal function. This is because we do not need to store the index to the destructor in that table - it is always two (see the class initialization section for more information).
_stb dt_13TExampleClassFv RECORD EXPORT
IMPORT _CVRTExampIeCIass:Data DC.L 0 DC.L _CVRTExampIeClass ; Client VTable Rec DC.L 0 ENDR
dt_13TExampIeCIassFv PROC EXPORT
IMPORT stb-dt_l3TExampIeCIassFv:Data ~ IF MODEL = 0 LEA _stb dt_13TExampIeCIassFv,aO
ELSE

K
LEA (_'stb_t~ dt_13TExampIeCIassFv).L,aO

ENDIF

IMPORT _SLM1 1 DestructorDispatch IF MODEL = 0 JMP _SLM1 1 DestructorDispatch ELSE

JMP ( SLMIIDestructorDispatch).L

ENDIF

IF MACSBUG = 1 THEN

its DC.B $80, S1C

DC.B 'stub dt 13TExampIeCIassFv' DC.B 0 DC.W 0 ENDIF

ENDP

Copyright Apple Computer 1991-1993 Notice that the destructor does not use any cached information to jump to the destructor directly. This is so that use counts may be updated (see the next bullet point).
This is the destructor function dispatcher that is linked with the client.
This is for reference only -- the client should link with the version supplied by SLM. The DestStub record looks just like a function stub record, except that it is one short shorter (it does not need the funcm field, it is known to be two (2)).
DestStub Record 0 function DS.L 1 .

clientCVR DS.L 1 nextPtr DS.L 1 ENDR

SLM11DestructorDispatch PROC
Export WITH DestStub tst.l Ia0) ; Destructor pointer cached?

beq.s @2 ; No - do it the hard way move.l clientCVR(a0),a1 ; Get the ClientVTabIeRec move.l (a1 ),a1 ; Get the CIassLinkPtr move.l 4(a1 ),a1 ; Get the TClass move.l TCIass.vtRecfal ),a1 ; Get the VTabIeRec pointer subq.l #1,VTRec.useCount(a1 ) ; Decrement the use count bmi.s @1 ; Have to do the library count?
.

move.l (a0),a0 ; No - go on jmp (a0) ; Jump to the destructor ;

Here, we have to bump the librariesnt - so we use cou call the SLMDestructorDispatch function - but first, we _q.4_ O 95/01598, PCT/US94107424 have to back off the VTabIeRec use count we just incremented @1 addq.l #1,VTRec.useCount(a1 ) ; Back off the VTabIeRec use count @2 move.l S2B6,a1 _ Sl0CIa1),a1 move.l move.l SLMGIobaI.fStubHelp(a1 ),a1 IF MODEL = 0 THEN

' move.l _gLibraryManager,d0 ELSE

move.l ( gLibraryManager).L,dO

ENDIF

jmp (a1 ) ENDP

Copyright Apple Computer 1991-1993 Under normal circumstances, the decrementing of the use count of the V'TableRec is all that is required, so dispatching is moderately fast. The only time that the more general dispatching mechanism needs to be invoked is if the destructor has never been invoked by the current client before, and we are destroying the last outstanding instance of this class among all clients of the SLM.
~ This is the actual destructor function dispatcher that is linked with the Shared Library Manager. This function is the most complex of the dispatching functions. This is because calling the destructor of an object can cause a library to unload. Unloading only occurs when SystemTask is called. However, if the destructor were to call SystemTask, this might be highly embarrassing, so we go to some lengths to insure that the library cannot be unloaded until we return from the destructor. This is for reference only:
SI_MDestructorDispatch PROC Export WITH SLMGlobal move.l d0,-(sp) ; Push the library manager move.l a0,-(sp) ; Push the stub record move.l d0,a0 ; Put TLibraryManager into a0 move.l 201a0),a0 ; Get the class catalog move.l a0,-(sp) ; Push it move.l (a0),a0 ; Get the destructor move.l CatVTabIe.Get Destructor(a0),a0 jsr (a0) ; Call class catalog lea 12(sp),sp ; Drop parameters Fiere, we're being possibly being unloaded at the next System Task.
.Just in case the destructor calls SystemTask, we disable code unloading until the destructor is finished running. We shift the stack WO 95/01598 ~ PCT/US94/0742 down by 4 bytes so that we can save a return address, and get returned to ourselves by the destructor GetSLMGlobal addq.l #1,fNoSystemTask(a0) ; Keep system task from unloading move.l (sp),d1 ; Save return address move.l 4(sp),(sp) ; Shift Parm 1 move.l 8(sp),4(sp) ; Shift Parm 2 move.l d1,8(sp) ; Save original return address ' move.l d0,a0 jsr (a0) ; Call the destructor GetSLMGlobal subq.l #1,fNoSystemTask(a0) ; Let system task unload now move.l 8(sp),a0 ; Recover return address move.l 4(sp),8(sp) ; Put parms back where they belong move.l (sp),4(sp) addq.l #4,sp ; Drop return address slot jmp (a0) ; And return to caller ENDP

Copyright Apple Computer 1991-1993 The CatVTable . GetDestructor is a call to the TClassCatalog: :GetDestructor method.
Virtual method stubs A virtual method stub is generated for each virtual function which may be linked with the client (in SharedLibTemp . stubs . a), unless the client specified NoStubs or NoVirtualStubs in the export declaration for the class.
These stubs are only used by a client that creates stack objects since the compiler generates a direct call when the dot syntax is used. The compiler is "smart"
and "knows" the class of the object so it does not generate a v-table indirect call. It would be better for SL.M if the compiler had an option to generate v-table calls anyway.
stbGetObjectName_l3TExampIeCIassCFv RECORD EXPORT
IMPORT _CVRTExampIeCIass:Data DC.L 0 DC.L _CVRTExampleClass , DC.L 0 DC.W 9 ; Index in VTable ENDR
GetObjectName_13TExampIeCIassCFv PROC EXPORT
IMPORT stbGetObjectName l3TExampIeCIassCFv:Data .

, r .
' , 4,~,I,,~.,~

=

LEA stbGetObjectName-13TExampIeCIassCFv,aO

ELSE

LEA ( stbGetObjectName-13TExampIeCIassCFv).L,aO
-S ENDIF

_ move.l (a01,d0 ; Is function address cached?

beq.s @1 ; No - do it the hard way move.l d0,a0 ; Yes - get address into a0 ' jmp (a0) ; and jump =

LEA -CVRTExampIeCIass,a0 ELSE

LEA ( CVRTExampIeClass).L,aO

ENDIF

IMPORT SLMIIVTabIeDispatch @ 1 =

JMP SLMIIVTabIeDispatch ELSE

JMP ( SLM1 1 VTabIeDispatch).L

ENDIF

IF MACSBUG = 1 THEN

its DC.B 580, S26 DC.B 'stub GetObjectName-13TExampIeCIassCFv' DC.B 0 DC.W 0 ENDIF

ENDP

Copyright Apple Computer 1991-1993 Notice that for virtual method stubs, we can once again cache the actual address of the function and call it directly.
~ This is the virtual function dispatcher that is linked with the client.
~SLM1 1 VTabIeDispatch PROC Export move.l S2B6,a1 move.l S10C(a1),a1 move.l SLMGIobaLfStubHelp+8(a1),a1 IF MODEL = 0 THEN
move.l gLibraryManager,d0 ELSE
move.l ( gLibraryManager).L,dO
ENDIF
jmp (a1 ) ENDP
' Copyright Apple Computer 1991-1993 ~~.ss3o~z ~ This is the actual virtual function dispatcher that is linked with the Shared Library Manager.
SLMVTabIeDispatch Export PROC

move.l d0,-(sp); Push the library manager move.l a0,-(sp); Push the stub record move.l d0,a0 ; Get lib mgr into a0 move.l 20(a0),a0; Get class catalog from lib mgr , move.l a0,-(sp); Push it move.l (a0),a0; Get it's vtable move.l CatVTabIe.GetVTabIeEntry(a0),a0 jsr (a0) ; Call the GetVTabIeEntry entry lea 12(sp),sp; Drop parameters move.l d0,a0 ; Fetch function address jmp (a0) ; Jump to it ENDP

Copyright Apple Computer 1991-1993 Non-Virtual method stubs Many classes use both virtual and non-virtual functions. Virtual functions allow subclasses to overnde the behavior of a class, while non-virtual functions do not. SLM supports stubs for the non-virtual methods to be generated (generated automatically unless noStubs or noMethodStubs is specified in the export declaration for the class). Note that SLM does not export static methods automatically in this manner. Static methods should normally be exported in a function set, since they do not require an instance of the class to be in existence in order for calling the method to be valid.
o A non-virtual member function stub is generated for each non-virtual member function (to be linked with the client in SharedLibTemp . stubs . a) _stbGetGIobalRef_13TExampIeCIassFRPI RECORD EXPORT
IMPORT _CVRTExampIeCIass:Data DC.L 0 DC.L _CVRTExamp(eClass DC.L 0 DC.W 0 ; Index into _exptbl array ENDR
GetGlobaIRef_13TExampIeCIassFRPI PROC EXPORT
IMPORT _stbGetGIobalRef_l3TExampIeCIassFRPI:Data IF MODEL = 0 LEA stbGetGIobaIRef_l3TExampIeCIassFRPI,aO
ELSE
LEA ( stbGetGIobaIRef l3TExampIeCIassFRPI).L,aO

~'VO 95101598 PCT/US94/07424 ' i - ..
ENDIF

move.l (a0),d0 ; Is Address cached?

beq.s @1 ; No - do it the hard way move.l d0.a0 ; Yes - get address into a0 jmp (a0) ; and jump IMPORT SLM1 1 ExtbIDispatch @1 IF MODEL = 0 JMP _SLM1 1 ExtbIDispatch ELSE

JMP ( SLM1 1 ExtbIDispatch).L

ENDIF

IF MACSBUG = 1 THEN

its DC.B 580, S26 DC.B 'stub_GetGIobaIRef_13TExampIeCIassFRPI' DC.B 0 DC.W 0 ENDIF

ENDP

Copyright Apple Computer 1991-1993 ~ This is the non-virtual function dispatcher that is linked with the client.
SLM11 ExtbIDispatch PROC Export move.l S2B6,a1 move.l S10C(a1),a1 move.l SLMGIobaLfStubHelp + 12(a1 ),a1 IF MODEL = 0 THEN

move.l gLibraryManager,d0 -ELSE

move.l ( gLibraryManager).L,dO

ENDIF

jmp (a1 ) ENDP

Copyright Apple Computer 1991-1993 ~ This is the actual non-virtual function dispatcher that is linked with the Shared Library Manager.

SLMExtbIDispatch PROC Export move.l d0,-(sp) ; Push the library manager move.l a0,-(sp) ; Push the stub record move.l d0,a0 ; Get lib mgr into a0 move.l 20(a0),a0 ; Get class catalog from lib mgr move.l a0,-(sp) ; Push it move.l (a0).a0 ; Get it's vtable move.l CatVTabIe.GetExportEntry(a0),a0 jsr (a0) ; Call the GetExportEntry entry lea 12(sp),sp ; Drop parameters WO 95/01598 ' ~ ' ' ' move.l d0,a0 ; Fetch function address Jmp (a0) ; Jump to it ENDP
Copyright Apple Computer 1991-1993 Static method stubs Static methods should normally be exported by function sets, since they are not associated with an instance of an object. You can export a specific static method by specifying "exports=<ClassName> : : <StaticMethod>" in your function set declaration, or you can export all static methods of a class by specifying "exports = static <ClassName>" in the declaration.
S_ing_ly-Inherited Classes (initialization)_ This section will examine the initialization code for a C + + class which is singly-inherited. This includes both forms of vtables - SingleObject derived, and standard AT&T v2.1 classes. Classes which are multiply-inherited (derive from more than 1 parent class) are handled in a separate section.
~ ClientVTableRecord for TExampleClass:
CVRTExampIeCiass RECORD EXPORT
DC.L 0, 0, 0 DC.W 50110 DC.W 50110 DC.B 'appl:examSTExampIeClass', 0 ENDR
Copyright Apple Computer 1991-1993 ~ Of course the vtable for TExampleClass is generated by the compiler.
The symbol for it is imported (SharedLibTemp.init.c):
extern ProcPtr vtbl-l3TExampIeClassll;
Copyright Apple Computer 1991-1993 .
The symbols for the non-virtual member functions (in this case GetGlobalRef) and the constructor and destructor are imported. The names of ' 9510159 , PCT/US94/07424 the constructor and destructor have been mangled with a 'q' to distinguish them from the stubs.
SLM modifies the object file that contains the constructor and destructor so -a that their names are different. This forces any reference to the constructor or destructor from within the library to also go through the stub. This is so that use counts can be maintained. If a library were to create an object, give it to the client, and have the client destroy the object, it would be possible for the library to unload even though there are outstanding references to it, since construction did nat increment the use count, but destruction did.
The stub for the constructor (the one without the 'q') is called by NewObject. The real constructors and destructors (the ones with the q mangling) are in the export table so they can be called from the stubs. The original symbols far the constructors and destructors in the object file (.o file) for the library are "q mangled" by the LibraryBuilder tool.
extern void _ct_l3TExampIeCIassFv(void);
extern void _dtq_l3TExampIeCIassFv(void);
extern void _ctq-l3TExampIeCIassFv(void);
extern void GetGIobaIRef l3TExampIeCIassFRPI(void);
Copyright Apple Computer 1991-1993 Two export tables are generated. One for the constructors and destructors (-_ extbh < ClassName > ) and one for non-virtual functions ~exptbl < ClassName > ).
ProcPtr exptbl TExampIeCIassO =
(ProcPtr)GetGIobaIRef l3TExampleCIassFRPI
}:
ProcPtr extbl TExampleClassll =
- -(ProcPtr) exptbl TExampIeClass, (ProcPtr) ct-13TExampIeCIassFv, (ProcPtr) dtq_l3TExampIeCIassFv, (ProcPtr) ctq_13TExampIeClassFv r w Copyright Apple Computer 1991-1993 Note that the first entry in the "extbl" points to the "exptbl". This allows a later version of the library to have new non-virtual method exports and new constructors. The first 4 entries of the extbl are always fixed. They may be zero if the corresponding table or function does not exist. The second entry always points to the stub for the default constructor (the constructor with no r arguments). The third entry always points to the "real" destructor, and the fourth entry always points to the "real" default constructor. Any entries after the fourth are for other versions of the constructors, and they always contain pointers to the "real" version ~ctq~ of those constructors.
~ The actual initialization code then needs to be generated.
#pragma segment A5lnit void SVRTExampIeClass(void* vtRec, unsigned int vtRecSize) { register ProcPtr toCall;
void** cat = GetCIassCatalog;
void** ctVTable = *cat;
void* parentVtRec;
//
// Initialize the VTabIeRec for TExampIeClass //
extern ProcPtr _vtbl_13TExampIeClass(1;
extern ClientVTabIeRec _CVRTDynamic;
toCall = (ProcPtr)ctVTable[211;
//
// Call InitVTabIeRec.
//
vtRec = (*(InitVTabIeRec)toCall) tcat, vtRec, _vtbl_l3TExampIeClass, extbl TExampIeClass, & CVRTDynamic, 8, 0);
//
// If there is a shared parent, Get it's VTabIeRec //
toCall = (ProcPtr)ctVTablef251;
parentVtRec = (*(GetVTabIeRec)toCall)(cat, & CVRTDynamic, 1 );
/***********************~
/* This code is OPTIONAL
************************/ , /I
// If there are functions inherited from the parent, let's // copy them. For a standard AT&T V2.1 vtable format, the 3 // copy code would be modified appropriately.
//
( 95/01598 ~ ~ PCT/US94/07424 unsigned int idx;
register VTable vtbl = ''(VTable*'IparentVtRec;
register VTable myVTable = vtbl-13TExampIeCiass;
myVTable + = 2;
vtbi + = 2;
for (idx = 0; idx < 7; + +idx) '~myVTable+ + _ *vtbl+ +;
}
}
}
Copyright Apple Computer 1991-1993 This code does several things. The first is to initialize the VTableRec. The parameters to the InitVTableRec call are as follows:
1) A pointer to the class catalog, obtained from the GetClassCatalog macros.
2) A pointer to the ~ VTableRec that was originally passed in to your initialization function.
3) A pointer to the vtable for the class 4) A pointer to the export table for the class 5) A pointer to the ClientVTableRec of the first "shared" parent class, looking backwards up the hierarchy. Normally, it is the ClientVTableRec of your parent class. However, if the parent class is not a shared class, then look at it's parent, and so on until you find a parent class that is shared. Leave this parameter NULL
(zero) if no parent class is shared.
6) The size of the object, in bytes. This parameter is optional, and may be set to zero unless you want your class to be able to be instantiated with the NewObj ect function. If this is the case, you must supply the size as a negative number whose absolute value is the size of the object in bytes.
7) The last parameter is a flag to tell the SLM about the VTableRec. For singly-inherited classes, only two values are used. NULL (or 0) indicates that the class inherits from SingleObject or IiandleObject and has a vtable format that is just an array of function pointers. A value of (char*)-1L indicates that the vtable has the format of an AT&T V2.1 vtable, which looks like:
typedef struct mptr WO 95!01598 PCT/LTS94107424 short o;
short i;
ProcPtr func;
} mptr;
Copyright Apple Computer 1991-1993 Multiplv-Inherited Classes !stubs!
This section will examine the stub creation for a C++ class which is multiply-inherited. What follows is a set of declarations for several classes, culminating in the definition of the class TMixedClass2. These are the classes that will be used to demonstrate the generation of code for multiply-inherited classes.
#define kMMixin1lD "quinaestSMMixin1,1.1~
class MMixin1 : public MDynamic protected:
MMixin1 (int a);
MMixinl ();
virtual ~MMixinl ();
public:
virtual int Add1 (int a1;
virtual int Sub1 (int a);
int fFieldm;
}:
#define kMMixin2lD "quinaestSMMixin2,1.1"
class MMixin2 : public MDynamic protected:
MMixin2();
MMixin2(int a);
virtual ~ MMixin20;
public:
virtual int Add2(int a);
virtual int Sub2(int a);
int fFieldm;
}~
#define kMMixin3lD "quinaestSMMixin3,1.1"
class MMixin3 : public MDynamic protected:

2.~ X6.302 MMixin3(int a);

MMixin3();

virtual ~-MMixin3();

public:

- virtual int Add3(int a);

virtual int Sub3(int a);

int fFieldm;

};

//

// Non-shared class //

class TMainClass : public TStdDynamic public:

TMainClass(int a);

virtual ~TMainClass();

virtual int Mul(int a);

virtual int Div(int a);

int fFieldt;

};

#define kTMixedCIassID"quinaestSTMixedClass,1.1"

class TMixedClass public TMainClass, virtual : public MMixinl, public MMixin2 public:

TMixedClass(int a);

TMixedClass();

virtual ~TMixedClassO;

virtual int Sub1 lint a);

virtual int Div(int a);

virtual int Add2(int a);

};

#define kTMixedClass2lD "quinaestSTMixedClass2,1.1"

class TMixedClass2public TMixedClass, virtual : public MMixin1, public MMixin3 public:

TMixedClass2(int a);

$p TMixedClass2(1;

' virtual ~TMixedClass2();

virtual int Sub2(int a);
virtual int Mulfint a);
virtual int Addlfinta);
virtual int Add3fint a);
};
Copyright Apple Computer 1991-1993 All stubs for multiply-inherited classes are generated in exactly the same way as for singly-inherited classes. This works because all inherited virtual functions are present in the primary vtable of the class.
If you encounter a case where this is not true, SLM provides a way to deal with it. Set the high bit (0x8000) of the index value (for whichever vtable the virtual function is present in), and add a second short (two bytes) immediately after it in the stub record which is the index number of the VTableRec (0 =
primary, 1 = next one, etc.).
Multiply-Inherited Classes finitialization~
This section will examine the initialization code for a C++ class which is multiply-inherited. The situation here is much different than for singly-inherited classes. Consider: using the hierarchy above, if one has an MMixinl object in hand, is it a true MMixinl object, or is it a TMixed~lass2 object cast to an MMixinl, or even a TMixedClass object cast to an r~Vtixinl? Information needs to be made available about the offset back to the "main" object. This allows the SLM function CastObject to work properly with objects which are instances of multiply-inherited classes.
This information is stored in the NllVtixinl VTableRec, which is stored in the MMixinl vtable. However, a different VTableRec is needed for an MMixinl object which is "stand-alone", than for an MMixinl object that is part of a TMixedClass2 object. This is because the offset to the "main" object is zero for a "stand-alone" object, and probably non-zero for one of many parents of a "main" object.

WO 95/0159f3 PCT/US94/07424 ~1663Q~ia, This leads us to the conclusion that in order to initialize a multiply-inherited class, multiple VTableRecs will need to be initialized in order to keep things running smoothly.
The initialization for classes NiMixinl, MMixin2, and MMixin3 are exactly what you would expect for singly-inherited classes:
extern ClientVTabIeRec CVRMMixin1;
extern void _ct 7MMixinl F~~(void);
extern void _dtq_7MMixinl Fv(void);
extern void _ctq 7MMixinl Fv(void);
extern void -ctq 7MMixinl Fi(void);
ProcPtr extbl_MMixinl (] _ 0, (ProcPtr) ct 7MMixinl Fv, (ProcPtr) dtq 7MMixin1 Fv, (ProcPtr) ctq 7MMixin1 Fv, (ProcPtr)-ctq 7MMixin1 Fi };
#pragma segment A5lnit void SVRMMixin1lvoid* vtRec, unsigned int vtRecSize) register ProcPtr toCall;
void** catalog = GetClassCatalog;
void** ctVTable = *catalog;
void* parentVtRec;
extern ProcPtr _vtbl_7MMixinl f];
toCall = (ProcPtr)ctVTableI211;
vtRec = (*(InitVTabIeRec)toCall)(catalog, vtRec, vtbl 7MMixinl, extbl MMixin1, 0, 8, (char*)Ox0001);
extern ClientVTabIeRec CVRMMixin2;
extern void _ct 7MMixin2Fv(void);
extern vosd _dtq 7MMixin2Fv(void);
extern void _ctq 7MMixin2Fv(void);
extern void ctq 7MMixin2Fi(void);
ProcPtr extbl MMixin2p _ 0, ' (ProcPtr) ct 7MMixin2Fv, (ProcPtr) dtq 7MMixin2Fv, (ProcPtr) ctq 7MMixin2Fv, (ProcPtr) ctq 7MMixin2Fi };

. ~. ....
WO 95/01598 ~ ~ ~ ' PCT/US94/07424 #pragma segment A5lnit void SVRMMixin2(void* vtRec, unsigned int vtRecSize) register ProcPtr toCall;
void** catalog = GetCIassCatalog;
void** ctVTable = *catalog;
void* parentVtRec;
extern ProcPtr _vtbl_7MMixin2[]; y toCall = (ProcPtr)ctVTable[21 ];
vtRec = (*(InitVTabIeRec)toCall)(catalog, vtRec, vtbl 7MMixin2, extbl MMixin2, 0, 8, (char*)Ox0001 );
- - -extern ClientVTabIeRec CVRMMixin3;
extern void _ct_7MMixin3Fv(void);
extern void _dtq_7MMixin3Fv(void);
extern void _ctq_7MMixin3Fv(void);
extern void ctq 7MMixin3Fi(voidl;
ProcPtr extbl MMixin3[I =
0, (ProcPtr) ct 7MMixin3Fv, (ProcPtr) dtq_7MMixin3Fv, ( ProcPtr)_ctq_7 M M ixin3 Fv, (ProcPtr) ctq_7MMixin3Fi };
#pragma segment A5lnit void SVRMMixin3(void* vtRec, unsigned int vtRecSize) register ProcPtr toCall;
void** catalog = GetCIassCatalog;
void** ctVTable = *catalog;
void* parentVtRec;
extern ProcPtr _vtbl_7MMixin3[I;
toCall = (ProcPtr)ctVTable[21 ];
vtRec = (*(InitVTabIeRec)toCall)(catalog, vtRec, vtbl 7MMixin3, extbl MMixin3, 0, 8, (char*)Ox0001 );
Copyright Apple Computer 1991-1993 For all of these classes, the pointer to the parent ClientVTableRec is NULL, the sizes are 8 bytes long and are positive (indicating that they cannot be instantiated with NewObj ect), and the final parameter is a (char*)Ox0001, indicating that the vtable format is the standard AT&T v2.1 format (remember that a 0 as this final parameter indicated that the vtable format was that of a class ~~ 0630, inherited from SingleObject) and that this is a primary vtable. Basically, the first byte of the pointer is a "dispatch code" - 0 implies SingleObject dispatching, irmplies AT&T v2.1 dispatching, and 2 implies SingleObject-type dispatching, but not in a SingleObject or IlandleObject subclass.
S The next byte tells what kind of VTableRecord this is. Zero (0) means the primary vtable. One (1) indicates that it is a "parent" vtable. A "parent"
vtable holds the ClientVTableRec of the parent class which the vtable inherits from.
Note that this is not the same as the class of objects which we derive from.
Two (2) indicates that it is a "virtual parent" vtable. A "virtual" parent inherits the viable from a "parent" class exactly like a "parent" vtable, but the class from which we derive is a "virtual" base class.
SLM assumes that for the secondary vtables that are generated, the first 8 bytes of the vtable are unused.
TMainClass is a non-shared class, so no initialization (or stubs) are generated for it. The next class to generate initialization for is TMixed Class. As you look over the generated code, you will notice that you need to be able to figure out the names of all of the extra vtables that a multiply-inherited class generates, as well as which entries in the vtable belong to the class itself, and which are inherited.
SLM also, dynamically copies function pointers from inherited vtables to avoid being linked with stubs. In order to keep the stubs from getting linked anyway, as the LibraryBuilder tool scans the vtables in the object file, it replaces calls to inherited functions with a call to -pure virtual called. This keeps the linker from linking all of the stubs into the code.
extern ClientVTabIeRec _CVRTMixedClass;
extern void _ct_1 1 TMixedCIassFvivoid);
extern void _dtq_11 TMixedCIassFvlvoid);
extern void _ctq_1 1 TMixedCIassFv(voidl;
extern void ctq_11 TMixedCIassFi(voidl;
ProcPtr extbl TMixedClass[l =
0, lProcPtr) ct 11TMixedCIassFv, i (ProcPtr) dtq-1 1 TMixedCIassFv, (ProcPtr) ctq_1 1 TMixedCIassFv, (ProcPtr) ctq 11TMixedCIassFi.
#pragma segment A5lnit void -SVRTMixedClass(void* vtRec, unsigned int vtRecSize) register ProcPtr toCall;

void*'~ cat = GetCIassCatalog;

void** ctVTable = *cat;

void* parentVtRec;

//

// Keep track of whether we got an error or not //

int isOK = 0;

//

// Keep track of where we are in initialization.

/I

unsigned int index = 0;

//

/l Declare the needed vtables and ClientVTabIeRecs //

extern ProcPtr _vtbl_1 1 TMixedClass(l;

extern ClientVTabIeRec _CVRTStdDynamic;

extern ProcPtr_vtbl_7MMixin2_llTMixedClassll;

extern ClientVTabIeRec _CVRMMixin2;

extern ClientVTableRec _CVRMMixin2;

extern ProcPtr_vtbl_7MMixinl_llTMixedClassfl;

extern ClientVTableRec _CVRMMixin1;

extern ClientVTabIeRec CVRMMixinl;

//

/J Initialization is done in a do {} while (false) loop // so that we can break out of the loop. "index"
will // tell us how far we got if we break out with an error //

do {

//

// Start off with the primary vtable ( vtbl 11 TMixedClass) // and initialize it. The primary vtable is initialized with // the last parameter to InitVTabIeRec as (char*Ox0001, indicating I/ that this is an AT&T V2.1-format vtable, and that this is a // primary vtable.

// Like it's singly-inherited counterpart, if the size parameter // is negative, it indicates that the class can be instantiated with // a "NewObject" call.

//

toCall = (ProcPtr)ctVTablef211;

vtRec = (*(InitVTabIeRec)toCall) (cat, vtRec, _vtbl_11 TMixedClass, extbl TMixedClass, & CVRTStdDynamic, 28, (char*)Ox0001 );
//

// Now, let's get the parent. The parent vtable to 1 1TMixedClass is the vtable for TMainClass. However, //
vtbl $ _ _ // TMainClass is a non-shared class. Since TMainClass is not // multiply-inherited, we just consider it's parent (TStdDynamic) !/ to be our parent and we get the parent VTabIeRec (this // forces TStdDynamic to stay loadedl) //

toCall = (ProcPtr)ctVTabIef331;

parentVtRec = (*(GetVTabIeRec)toCall)(cat, &-CVRTStdDynamic, 1);

if (parentVtRec = = 0) break;

//

/l We increment index to indicate that, if something goes wrong, // we need to call ReleaseVTabIeRec on CVRTStdDynamic //

index + = 1;

/*

* * Ordinarily, here we would copy all of our parent's methods that * * we inherit. However, since our immediate parent is not shared, * * copying methods from TStdDynamic would get us into trouble, since * * any methods overridden by TMainClass would be lost. We content * * ourselves with linking directly with any methods that TMainClass * * overrides, and with stubs to any that it does not.

*

//

// Now, let's initialize the VTabIeRec for one of the other // vtables. This VTable has the class MMixin2 as it's parent.

// A (char*)Ox0101 is passed as the last parameter to indicate that // this is a VTable for one of the non-primary "parents", but that // it is not a "virtual" parent class.

//

toCall = (ProcPtr)ctVTablef211:

vtRec = (*(InitVTableRec)toCall) (cat, vtRec, _vtbl_7MMixin2_1 lTMixedClass, extbl_TMixedClass, & CVRMMixin2, 28, _ (char*)Ox0101 );

toCall = fProcPtr)ctVTablet331:

!/

// Fetch the parent VTabIeRec to force the parent's code to load l/

parentVtRec = (*(GetVTabIeRec)toCall)(cat, & CVRMMixin2, 1);

if (parentVtRec = = 0) break;

!/

// We increment "index" to indicate that, if something goes wrong, // we need to call ReleaseVTabIeRec on CVRMMixin2 land, of course, l/ also _CVRTStdDynamic) //

index + = 1;

/************************

/* This code is OPTIONAL

**.*********************/

ll - bl -WO 95/01598 PCT//>iJS94/07424 // Now, since we are inheriting from the class MMixin2, and it is // a shared class, we copy the pointers from the vtable for MMixin2 l/ into our own vtable. The LibraryBuilder tool replaced all of // these entries that were inherited with a reference to // -pure_virtual_called so that the linker did not try to link with // the stubs from the MMixin2 class.

unsigned int idx;

//

// Get the VTable of MMixin2 //

register mptr* vtbl = *( mptr**)parentVtRec;

/~

// Get my own VTable //

register mptr*myVTable=( mptr*) vtbl 7MMixin2 1lTMixedClass;
-//

// Save a pointer to the start of my VTable //

_mptr* base = myVTable;

//

// Now, we skip the first entry, because it's blank //

myVTable + = 1;

vtbl + = 1;

//

// The second entry (which happens to be the destructor) is a // pointer to one of the routine of TMixedClass, and not an // inherited routine. The mptr .o field of any method that _ // belongs to "this" class will have a negative number l/ indicating the offset that must be added to the parent class // pointer (in this case MMixin2) in order to get to the "real"

// object. We save that value off in the second long of the /! first _mptr entry (which is always unused in the AT&T v2.1 // format) II

base->func = (ProcPtr)(IongImyVTable->o;

//

// Then, we skip entries that are our own, and copy any entries // that are inherited.

//

myVTable + = 2;

vtbl + = 2;

(*myVTable++).func = (*vtbl++).func;

}

/****************************

/* This code is NOT Optional *****************************/

//

// Now, we initialize the last VTabIeRec. We pass (char*)Ox0201 to // indicate to the SLM that this is a VTable corresponding to a // "virtual" parent class. One of the side effects of this is that /l SLM will not allow you to cast a TMixedClass to an MMixinl WO 95/01598 . PCT/LJS94/07424 // class (neither will C++).
//
toCall = (ProcPtr)ctVTablef2ll;
vtRec = (*(InitVTabIeRecItoCall) (cat, vtRec, _vtbl_7MMixin1_l 1TMixedClass, _extbl_TMixedClass, & CVRMMixin1, 28, (char*)Ox0201);
toCall = (ProcPtr)ctVTablei:33);
parentVtRec = (*(GetVTabIeRec)toCall)(cat, & CVRMMixin1, 1 );
if (parentVtRec = = 0) break;
index + = 1;
l************************
/* This code is OPTIONAL
************************/
ll // Do all of the copying voodoo again //
{
unsigned int idx;
register mptr* vtbl = *( mptr**)parentVtRec;
register mptr* myVTable =
t_mptr*) vtbl 7MMixin1-11TMixedClass;
mptr* base = myVTable;
myVTable + = 1;
vtbl + = 1;
base->func = (ProcPtr)(IongImyVTable->o;
myVTable + = 1;
vtbl + = 1;
(*myVTable++).func = (*vtbl++).func;
/*****************************
/* This code is NOT Optional ********************,.********/
// ' // Flag success //
isOK = 1;
} while (0);
//
// If something went wrong, we have to call ReleaseVTabIeRec on any // parents where we already called GetVTabIeRec on. "index" tells us // how far we got, so we can back out.
// Then we throw an exception.
//
if (isOK = = 0) {
toCall = (ProcPtr)ctVTablet261:
switch(index) {
case 2: (*(ReleaseVTabIeRec~toCall)Icatalog, & CVRMMixin2);
case 1: (*(ReleaseVTabIeRecItoCall)(catalog, & CVRTStdDynamic);
default: break;
Fail(-3120, 0);

WO 95!01598 ' ~ ri PCT/US94l07424 ~,' t ' _ ; ; ,.
Copyright Apple Computer 1991-1993 A couple of key points to realize about the code on the previous pages. The first is that it is not strictly necessary to dynamically copy methods that are inherited. If you do not, then the vtable will link with stubs to the inherited methods, which will work just fine, and be only slightly slower.
It is also not strictly necessary to modify the object file to make inherited reference in the vtable point to lure virtual called. You could also still copy the pointers from your parent's vtable at runtime, and all that would happen is that the stubs become orphaned because no one uses them, so your library is a little bigger than it should be.
However, what is important is that you somehow determine the offset of the subclass from the main class and store that in the . func field of the first vtable entry for each VTableRec (i.e. the 4 bytes starting at offset 4 in the viable). SLM
chose to determine this at runtime, using the knowledge that the . o field of any vtable method that has been overndden by the main class has this offset akeady stored in it. This was easier than trying to fully parse the, class declarations (with all the attendant knowledge of padding rules, etc) to determine them - but whatever method works for a given environment can be used. The offset is always a negative number.
Now, we get to the initialization code for the class TMixedClass2.
extern ClientVTabIeRec _CVRTMixedClass2;
extern void _ct_l2TMixedClass2Fv(void);
extern void _dtq_12TMixedClass2Fv(void);
extern void _ctq_l2TMixedClass2Fv(void);
extern void ctq-l2TMixedClass2Fi(void);
ProcPtr extbl TMixedClass2(1 =
0, (ProcPtr) ct l2TMixedClass2Fv, (ProcPtr) dtq_l2TMixedClass2Fv, ' (ProcPtr) ctq-l2TMixedClass2Fv, (ProcPtr)-ctq_12TMixedClass2Fi _ fø _ 95/01598 ~ ~ ~ PCT/US94/07424 #pragma segment A5lnit S void SVRTMixedClass2lvoid* vtRec, unsigned int vtRecSize) register ProcPtr toCall;
void** cat = GetCIassCatalog;
void** ctVTable = *cat;
void* parentVtRec;
int isOK = 0;
unsigned int index = 0;
extern ProcPtr _vtbl_12TMixedClass2(1;
extern ClientVTabIeRec _CVRTMixedClass;
extern ClientVTabIeRec _CVRTMixedClass;
extern ProcPtr _vtbl_20MMixin2_TMixedClass_12TMixedClass2(l;
extern ClientVTabIeRec _CVRTMixedClass;
extern ClientVTabIeRec _CVRMMixin2;
extern ProcPtr _vtb!_7MMixin1 12TMixedClass2p;
extern ClientVTabIeRec _CVRTMixedClass;
extern ClientVTabIeRec _CVRMMixinl;
extern ProcPtr _vtbl_7MMixin3_12TMixedClass2[];
extern ClientVTabIeRec _CVRMMixin3;
extern ClientVTabIeRec _CVRMMixin3;
do II
// Initialize the primary vtable which has TMixedClass as Il a parent.
//
toCall = (ProcPtr)ctVTable(211:
vtRec = (*flnitVTableRec)toCall) (cat, vtRec, _vtbl_l2TMixedClass2, _extbl_TMixedClass2, & CVRTMixedClass, 36, (char*)Ox0001 );
toCall = (ProcPtr)ctVTable(331;
parentVtRec = (*(GetVTabIeRec)toCall)(cat, & CVRTMixedClass, 1 );
if (parentVtRec = = 0) break;
index + = 1;
/************************
/* This code is OPTIONAL
************************/
//
// Do the copying stuff l/
unsigned int idx;
register mptr* vtbl = *( mptr**)parentVtRec;
register _mptr* myVTable = l mptr*) vtbl-12TMixedClass2;
mptrø base = myVTable;
myVTable + = 1;
vtbl + = 1;

base->func = (ProcPtr)(long)myVTable->o;

myVTable + = 1;

vtbl + = 1;

for (idx = 0; idx < 7; + +idx) S {

_ (*myVTable+ +).func = (*vtbl+ +).func;

myVTable + = 1;

vtbl + = 1; ' (*myVTable++).func = (*vtbl++).func;

(*myVTable++).func = (*vtbl++).func;

(*myVTable+ +).func = (*vtbl+ +).func;

/****************************

/* This code is NOT Optional *****************************/

//

// Initialize a secondary vtable, which corresponds to the methods // from the MMixin2 class, but is inherited from TMixedClass II

toCall = (ProcPtr)ctVTable[211;

vtRec = (*(InitVTableRec)toCall) (cat, vtRec, _vtbl_20MMixin2_TMixedClass_12TMixedClass2, extbl_TMixedClass2, & CVRTMixedClass, 36, (char*)Ox0101 );

toCall = (ProcPtr)ctVTable[331;

//

// Get the Parent vtable rec //

parentVtRec = (*(GetVTabIeRec)toCall)(cat, & CVRTMixedClass, 1);

if (parentVtRec = = 0) break;

index + = 1;

/************************

/* This code is OPTIONAL

************************/

//

// This vtable inherits from the vtable named !/ _vtbl_7MMinx2_l lTMixedClass, which was the // 2nd VTable that was stored for TMixedClass, so we skip // the parentVtRec pointer ahead to the 2nd vtable so that // we can properly inherit the methods.

//

parentVtRec = (char*)parentVtRec + 1*vtRecSize;

!/

// Do the copying stuff II

{

unsigned int idx;

register mptr* vtbl = *( mptr**)parentVtRec;

register mptr* myVTable =

( mptr*) vtbl 20MMixin2 TMixedClass_ _12TMixedClass2; , mptr* base = myVTable;

myVTable + = 1;

vtbl + = 1;

base->func = (ProcPtr)(long)myVTable->o;
myVTable + = 1;
vtbl + = 1;
(*myVTable++).func = (*vtbl++).func;
}
/****************************
/* This code is NOT Optional ****************************/
. //

// Initialize another secondary vtable. This one corresponds // to methods from MMixin1, but also inherits from TMixedClass.

// It is flagged as a virtual parent, since MMixin1 is declared // as a virtual parent in the 'C++" header file.

//

toCall = (ProcPtrIctVTablef211;

vtRec = (*(InitVTabIeRec)toCall) (cat, vtRec, _vtbl_7MMixin1_12TMixedClass2, _extbl_TMixedClass2, & CVRTMixedClass, 36, (char*IOx0201 );

toCall = (ProcPtr)ctVTable(331;

parentVtRec = (*(GetVTabIeRec)toCall)(cat, & CVRTMixedClass, 1 );

if (parentVtRec = = 0) break;

index + = 1;

/************************

/* This code is OPTIONAL

************************/

/l // This vtable inherits from the vtable named // vtbl 7MMixin1 l1TMixedClass, which was the // 3rd VTable that was stored for TMixedClass, so we skip // the parentVtRec pointer ahead to the 3rd vtable so that // we can properly inherit the methods.

//

parentVtRec = (char*)parentVtRec + 2*vtRecSize;

{

unsigned int idx;

register mptr* vtbl = *( mptr**)parentVtRec;

register _mptr* myVTable =

( mptr*) vtbl 7MMixinl l2TMixedClass2;

_ mptr* base = myVTable;

myVTable + = 1;

vtbl + = 1;

base->func = fProcPtr)(long)myVTable->o;

myVTable + = 2;

vtbl + = 2;

(*myVTable++).func = (*vtbl++).func;

}

/****************************

/* This code is NOT Optional *****************************/

toCall = (ProcPtrlctVTable(211;
vtRec = (*(InitVTabIeRec)toCall) (cat, vtRec, vtbl 7MMixin3 l2TMixedClass2, WO 95/01598 PCT/US94/0~424 . ,_ extbl TMixedClass2, & CVRMMixin3, 36, Ichart)Ox0101 );
toCall = (ProcPtr)ctVTable(33);
parentVtRec = (t(GetVTabIeRecItoCall)(cat, & CVRMMixin3, 1 );
if (parentVtRec = = 0) break;
index + = 1;
~tttttttttttttttttttttttt /t This code is OPTIONAL
tttttttttttttttttttttt*t~
unsigned int idx;
register mptrt vtbl = t( mptrtt)parentVtRec;
register mptrt myVTable =
mptrt)_vtbl 7MMixin3-12TMixedClass2;
_mptrt base = myVTable;
myVTable + = 1;
vtbl + = 1;
base->func = (ProcPtr)(long)myVTable->o;
myVTable + = 2;
vtbl + = 2;
(tmyVTable+ +).func = (tvtbl+ +).func;
}
)ttttttttttt#tttttttttttttttt /It This code is NOT Optional ttttttttttttttttttttttttttttt~
isOK = 1;
} while (0);
if (isOK = = 0) toCall = (ProcPtr)ctVTablef261;
switch(index) case 3: (tfReleaseVTabIeRec)toCall)(catalog, 8i CVRTMixedClass);
case 2: (t(ReleaseVTabIeRec)toCall)(catalog, & CVRTMixedClass);
case 1: (tlReleaseVTabIeRec)toCalp(catalog, & CVRTMixedClass);
default: break;
}
Fail(-3120, 0);
}
Copyright Apple Computer 1991-1993}
In order for the optional method copying to work, it is vital that the ordering of the vtables be the same no matter which C++ compiler generated the vtables.
In the example above, we know that we must inherit from the 2nd and 3rd vtables in the list of vtables generated for TMixedClass (by the way, notice that you are passed the size of the VTableltec so that you can do the necessary calculations, and still allow us to change the size of a VTableRec later). If TMixedClass were generated in another library, it would be fatal for us to copy methods from those vtables if they were not generated in the same order that the SLM thinks they were generated in.
The SLM uses the order that is generated by AT&T's CFront. The algorithm looks like this:
1) Create a list of all of the parent classes in the order they were declared.
2) For each parent that was not declared "virtual" , examine all of your parents and their parents, etc. If anywhere in the hierarchy, you find this parent declared "virtual", remove this class from this list of your parents.
3) Now, create two lists of parents, a "hasA" list for virtual parents, and an "isA" list for non-virtual parents. Starting at the beginning of your original parent list, if the parent is "virtual", put it at the front of the "hasA" list, and if it is not, put it at the back of the "isA" list.
4) Now, take the "hasA" list and move each parent on the list to the end of the "isA" list. You now have a list of the parent classes in the proper order.
Now, we can generate the names of the vtables from this list.
1) Create a new list for vtable names.
2) Create a vtable called vtbl ##ClassName, where ## is the length of the class name. It's parent class is the first class in your parent list, unless that first class is flagged "virtual", in which case, there is no parent. Add this vtable to the end of the vtable list.
3) If the first thing in your parent list is a virtual parent, then another vtable must be generated with the following name:
vtbl ## < ParentName > ## < MyName >
where < ParentName > is the name of this first parent in the list. Add this vtable to the end of the vtable list.
4) Get the list of vtables belonging to the parent class that is first in your list.
Skip the first vtable in this parent's list.
5) For each remaining vtable in this parent's list, create a new vtable name:
vtbl ## < ParentSubName > ## < MyName > , WO 95/01598 PCTlUS94/07424 2.66302.
where the < ParentSubName > is derived from the name of the parent VTable as follows:
1) Strip the vtbl- from the front of the vtable name 2) Remove the numbers from the end part of the vtable name 3) Change the numbers at the front of the vtable name so that they correspond to the length of the new string. For example, vtbl '7NBViixinl-llTMixedClass becomes 20MMixinl TMixedClass.
6) If this new vtable name is not already in your list, append it to the end of the list.
7) For each remaining parent in your parent list, do steps 5 and 6 (do not skip the first vtable for the remaining parents).
At this point, you have a list of vtables for your class that is exactly the same list that the SLM LibraryBuilder tool will generate. Of course, this algorithm must be suitably modified for compilers that generate vtables with different naming conventions.
The following is the initialization code for the library that is created.
#/pragma segment A5lnit void* _InitVTabIeRecordsfvoid) {
register ProcPtr toCall;
void* vtRec;
void* savedRec;
void** catalog = GetCIassCatalog;
void** ctVTable = *catalog;
toCall = (ProcPtrIctVTable1191;
savedRec = (*(GetVTabIeMemory)toCall)fcatalog, 10);
toCall = (ProcPtr)ctVTabIe1201;
vtRec = savedRec;
//
// Initialize the MMixinl class //
vtRec = (*llnitl VTableRec~toCall) (catalog, vtRec, SVRMMixinl, & CVRMMixin1);
// Initialize the MMixin2 class //
vtRec = (*(Init1 VTabIeRec)toCall) (catalog, vtRec, SVRMMixin2, & CVRMMixin2);
/%
// Initialize the MMixin3 class _70_ . ~ ~.
"- d ', a //
vtRec = (*(Init1 VTabIeRec)toCall) (catalog, vtRec, SVRMMixin3, & CVRMMixin3);
/%
// Initialize the TMixedClass class - primary vtable //
vtRec = (*(Init1 VTabIeRec)toCall) (catalog, vtRec, SVRTMixedClass, & CVRTMixedClass);
/%
// Initialize the TMixedClass class - secondary vtable /l corresponding to a parent class of MMixin2 //
vtRec = (*(Init1 VTableRec)toCall) (catalog, vtRec, 0, & CVRMMixin2);
//
// Initialize the TMixedClass class - secondary vtable // corresponding to a parent class of MMixin1 //
vtRec = (*(Init1 VTabIeRec)toCall) (catalog, vtRec, 0, & CVRMMixin1 );
// v // Initialize the TMixedClass2 class - primary vtable //
vtRec = (*(Init1 VTabIeRec)toCall) (catalog, vtRec, SVRTMixedClass2, & CVRTMixedClass2);
J%
// Initialize the TMixedClass2 class - secondary vtable // corresponding to a parent class of MMixin2 //
vtRec = (*(Init1 VTabIeRec)toCall) (catalog, vtRec, 0, & CVRMMixin2);
/%
// Initialize the TMixedClass2 class - secondary vtable // corresponding to a parent class of MMixin1 //
vtRec = (*(Init1 VTabIeRec)toCall) (catalog, vtRec, 0, & CVRMMixin1 );
/%
// Initialize the TMixedClass2 class - secondary vtable // corresponding to a parent class of MMixin3 //
vtRec = (*(InitlVTabIeRec)toCall) (catalog, vtRec, 0, & CVRMMixin3);
return savedRec;
}
Copyright Apple Computer 1991-1993 Notice that all of the secondary vtables have a 0 for the pointer to the initialization function. The SLM will assume that the initialization function for the first prior vTableRec which has one will take care of initialization for these WO 95/01598 PCTIUS94/0742.4 2~6 ~3 Q2 VTableRecs. In addition, for all of the secondary vtables, the ClientVTableRec is not the ClientVTableRec of the class itself, but for the parent class which corresponds to the vtable which will be stored in the vTableRec, which is the class that we can cast the object to. For instance, if we look at the second call to InitiVTableRec for TMixedClass2, r CvRN~tixin2 is passed to the 5LM. If we look at the 5vlZ runcnon ror TMixedClass2,wefindthat vtbl 20MMixin2 TMixedClass 12-TMixedClass2 is the vtable that is stored into this vTableRec. This vtable is the vtable that will be used if a'1'NtixedClass2 is cast to an ~tixin2 object.
However, notice thatwepassed & CvR.TMixedClass astheClientVTableR-ec of the parent. This is because this vtable, while it belongs to the part of TMixedClass2 that is an N.~iixin2 object, actually is inherited from the vtbl 7N~lixin2 llTMixedClass vtable from TMixedClass.
The Shared Library An SLM Shared Library consists of a number of resources, bound together by a resource id and a code resource type (see Fig. 8). Any number of these libraries can be placed in a single file, as long as the resource ids and code resource types used are unique. ~ -All libraries have a 'libr' resource with a resource id. SLM will scan for all 'libr' resources within a library file in order to catalog all of the libraries within the file. Within the 'libr' resource, the code resource type that belongs to that library is defined. For library files with multiple libraries, these types are commonly 'cd01' , 'cd02' , etc.
In addition, each library may have a 'libi' resource which has the same resource id as the corresponding 'libr' resource. This 'libi' resource contains information about all of the shared classes and function sets which are needed by the library. The tool CreateLibraryLoadRsrc creates 'libi' resources.

.~y.'~... ' The 'libr' resource A library is installed when the SLM is initialized (normally at boot time) or when it is drag-installed into a library folder. This is normally the "Extensions"
folder, but additional folders may be registered by applications as library folders.
When a library is installed, its 'libr' resource is read in by the library manager. The library manager keeps a catalog of Class ms and FunctionSet ms and the data for each which it gets from the 'libr' resource. Note that a library file may have more than one library in it, in which case it has multiple 'libr' resources.
~ The 'libr' resource format (note: the array LibrLine will not have more than one entry, multiple 'libr' resources will be present instead):
type 'libr' {

array LibrLine { /* information for a library */

cstring; /* Library id */

align word;

stringt4l; /* code resource type */

hex byte; /* libr template major version */

hex byte; /* libr template minor version */

hex byte; /* Major version */

hex byte; /* Minor revision */

hex byte; /* Development stage */

hex byte; /* Release within stage */

integer; l* reserved in v1 10) */

integer; /* perClientDataSize in v1 10 = default) */

longint; /* HeapSize in v1 (0 = default) */

longint preload = 0x01, clientPool = 0x02, nosegunload = 0x04, loaddeps = 0x08, forcedeps = 0x10, loadself = 0x20, defaultHeap = 0x0000, tempHeap = 0x0100, sysHeap = 0x0200, appHeap = 0x0300, holdMemory = 0x0400, notSystem7 = 0x10000, notSystem6 = 0x20000, notVMOn = 0x40000, notVMOff= 0x80000, hasFPU =0x100000, hasNoFPU = 0x200000, not68000 = 0x400000, not68020 = 0x800000, ~'VO 95/01598 '~ . !

not68030 = Ox 1000000, not68040=0x2000000; /~' flags for the code resource ''/

integer = $SCountof(CIassIDs);/~ # class IDs *~/

array CIassIDs /~ array of classlds the library implements ~'/

{

longint preload = 0x01, newobject = 0x02, isFunctionSet = Ox04;/*' flags for the class ~'J

integer; /'~ current version */

integer; /~' minimum version */

cstring; /'~ the class id string '~/

align WORD;

integer = S$CountOf(ParentlDs);

array ParentlDs {

cstring;

}% /# the parent class id string */

align WORD;

};

};

};
Copyright Apple Computer 1991-1993 ~ ExampleLibrary 'libr' resource #define SLMType 'code' #define SLMID 0 resource 'libr' (SLMID) {
{ "appISExampIeLibrary,1.1 ","code", Ox01,Ox10,Ox01, 0x10, 0x60, 0x04, 0, 0, 2, 10, 0x0110, 0x0110, "appl:exam$TExampIeClass", { "ISdyna"
}:
4, 0x0110, 0x0110, "appl:examSExampIeFSet", {};
}
}
};
Copyright Apple Computer 1991-1993 ~ Multiple-inheritance example 'libr' resource #define SLMType cod8 #define SLMID 8 ' resource 'libr' (SLMID) {
{
"quinaestSMITest1,1.1 ","cod8", Ox01,Ox10,Ox01, 0x10, 0x20, 0x01, 0, 0, 6, {

WO 95/01598 , , PCT/US94/07424 ..
26, 0x01 10, 0x01 10, "quinaestSMMixinl ", ~}%
26, 0x0110, 0x0110, "quinaestSMMixin2", {}:
26, 0x0110, 0x0110, "quinaestSMMixin3", r 26, 0x0110, 0x0110, "quinaest$TMixedClass", "*quinaestSMMixin1 ", "quinaestSMMixin2", "! Ssdyn"
}:
26, 0x0110, 0x0110, "quinaestSTMixedClass2", "*~quinaest$MMixin1 ", "quinaestSMMixin3", "quinaestSTMixedClass"
}
}
};
};
Copyright Apple Computer 1991-1993 Notice that a star character '*' is put in front of the ClassID of any parent class which was defined as virtual in the class declaration.
There are several fields in the 'libr' resource which should be called to your attention.
1) The flags for the code resource. This field is a.bitmap that defines the attributes of the library, as well as bits that can limit when the library will load.
See the later section on the LibraryBuilder tool for the meaning of each of the bits.
2) The "heap" type is encoded in the lower 2 bits of the second byte of the flags. The next bit indicates whether the memory for the library should be "held"
when Virtual Memory is in use.
3) The longint specifying heapsize. This allows you to specify the size of the heap you want the library to load in. Normally, SLM creates a heap big enough to hold all of the code in the library. If you are planning on loading and unloading segments manually, you might want to create a smaller heap.
4) The integer specify the per-client data size. If your library requires per-clnent data, SLM will manage it for you, but it needs to know the size of data WO 95/01598 ' PCT/IJS94/07424 ~16630~2 required. You can then use the GetClientData function to retrieve a structure of this size for each client that you have.
5) The 'libr' template major and minor version numbers. These should always be set to 0x01 for the major version and 0x10 for the minor version. This corresponds to the 'libr' template definition for SLM.
6) The version number of the library is encoded in the library id.
The 'libi' resource Libraries and clients may have 'libi' resources. As has been previously indicated, the resource id of the 'libi' resource for a library must match the resource id of the 'libr' resource. For applications and clients, the 'libi' resource must have an id of 0.
The format of the 'libi' resource is:
type 'libi' {
longint = 0; // version number longint = 0; // reserved integer = SSCountOf(A50ffsets);
array A50ffsets {
integer;
};
Copyright Apple Computer 1991-1993 Currently the 'libi' resource is nothing more than AS offsets to the ClientVTableRecs that are used by the library or client. This allows us to create the 'libi' resource by scanning the map file created by linking the shared library or client for references to symbols that look like CVRxxaooocxx, and simply storing the AS offset indicated into the resource.
~brary Initialization When a library is loaded the jump table (' code ~ 0 ) and initialization ( ~ code ~ 1 ) resources are loaded and the entry point is called. The entry point , routine initializes the static data for the library and then calls the init v-table WO 95/01598 ~ PCT/US94/07424 function. The -InitVTableRecords function sets up the v-tables, vtable records (VTableRec), and binds them to the library manager internal catalog entry (TClass) for each function set and class in the library.
This is the entry point routine in the library. The LibraryBuilder link command (generated in SharedLibtemp.bat) uses the option "-m DynamicCodeEntry" which makes this the third jump table entry (in model far the first two entries are "dummy" entries).
extern "C" void _InitProc();
extern "C" void _CleanupProc();
extern TLibraryManager* gLibraryManager;
#pragma segment A5lnit /************************************************* ********
* * DynamicCodeEntry ************************************************** *******/
extern "C" long DynamicCodeEntry( CodeEntrySelector selector, long paraml, long param2) {
VTabIeRecPtr myVTabIeRecArray;
switch (selector) {
case klnitWorld:
// Our own modified _Datalnit routine relocates and // unpacks initialized data and relocates A5 relative // addresses.
InitData((Ptr) paraml, (Ptr) param2l;
return 0;
case kSetLibraryManager:
_gLibraryManager = (TLibraryManager*) param1;
return 0;
case klnitLibraryProc:
InitProcp;
return (long) CleanupProc;
case kSetupVTables:
myVTabIeRecArray = _InitVTabIeRecords();
return (long) myVTabIeRecArray;
}
}
Copyright Apple Computer 1991-1993 _77_ WO 95/01598 ~' PCTILJS94/07424 ~~~6~4~ . ... v.
The Export Definition file The "export" file defines the classes and functions to be exported. This file has 3 major components: A Library declaration, Class declarations and FunctionSet declarations. The full syntax for these declarations is described in the next section. In addition, "C" or "C + +" style comments are allowed, as well as #include statements. The LibraryBuilder application is able to scan these include files to learn the definitions of #defmed symbols that may make up parts of the export definitions.
A .exp file consists of comments, #include directives, #defme directives, a Library declaration, plus Class and/or FunctionSet declarations.
The Library declaration The library declaration defines the ID of the shared library and the version.
Additional parameters are available to configure the library.
Library initproc = <ProcName>; optional cleanupProc = <ProcName>; optional flags = <FlagOptions>; optional id = < LibraryIDString > ; required version = < LibraryVersion > ; required memory = < MemoryOption > ; optional heap = < HeapType > ; optional clientdata = < ClientData Option > ; optional };
Copyright Apple Computer 1991-1993 Element Descriptions initproc This declaration allows you to specify the name of a "C" routine (which takes no parameters and returns no value) which will be called immediately after .
loading and configuring the library. This routine may be in the ASInit segment, so that it is unloaded from memory after the library is fully loaded. .
_78_ WO 95101598 ' ' PCT/US94107424 .' cleanupProc This declaration allows you to specify the name of a "C" routine (which takes no parameters and returns no value) which will be called just before a library is unloaded from memory. This routine must not be in the ASInit segment since it cannot be reloaded.
flags = noSegUnload = ~ ! segUnload This flag indicates that the segments of the shared library will not be unloaded by the client. The SI M resolves all jump table references to code addresses at library load time and removes the jump table from memory. This is the default setting.
flags = segUnload i' !NoSegUnload This flag indicates that the segments of the shared library may be unloaded by the client. The SLM will allow segments to be loaded and unloaded in the shared library, and will keep the jump table in memory.
flags = preload This flag indicates that all segments of the shared. library should be loaded at library load time. It does not guarantee that the segments will not be unloaded so the jump table must be kept in memory and intersegment references are left pointing to the jump table. "flags = !preload" is also supported, but is the default case.
flags = loaddeps This flag indicates that the SLM should load all dependent classes whenever this library is loaded(based on the information in the 'libr' resource created during the build process). Using this flag will guarantee that all libraries that your library depends on exist. It does not guarantee that there is enough memory available to k load them.

2~~~~0. .
flags = forcedeps This flag acts just like the "loaddeps" flag, but it forces the dependent libraries to be loaded into memory.
flags = stayloaded This flag forces your library to stay loaded. It requires a call to UnloadLibraries from within your library to allow your library to unload. It is equivalent to calling LoadLibraries(true, true) within your InitProc. It also causes all of your dependencies to be loaded into memory (like the "forcedeps"-flags).
flags = system6 ~ _ ! system?
This indicates that your library should not be registered if it is installed on a system 7. x-based Macintosh. No clients will be able to see any of the classes or function sets in your library. This flag is useful if you have 2 different versions of your library - one for System 6.x and one for System 7.x.
flags = system? ~ ~ ! system6 This indicates that your library should not be registered if it is installed on a system 6.x-based Macintosh. No clients will be able to see any of the classes or function sets in your library. This flag is useful if you have 2 different versions of your library - one for System 6.x and one for System 7.x.
flags = vmOn ~ ~ !vmOff This indicates that your library should not be registered if it is installed on a Macintosh which is running with Virtual Memory (VM) turned on. No clients will be able to see any of the classes or function sets in your library. This flag is useful if you have 2 different versions of your library - one for Virtual Memory on and one for Virtual Memory off. ' a ..
flags = vmOff i i !vmOn This indicates that your library should not be registered if it is installed on a Macintosh with Virtual Memory (VM) turned off. No clients will be able to see i any of the classes or function sets in your library. This flag is useful if you have 2 different versions of your library - one for Virtual Memory on and one for Virtual Memory off.
flags = fpuPresent i ~ !fpuNotPresent This indicates that your library should not be registered if it is installed on a Macintosh without a Floating Point Unit (FPU). No clients will be able to see any of the classes or function sets in your library. This flag is useful if you have 2 different versions of your library - one for an FPU being present, and one for it being absent.
flags = fpuNotPresent ~ ~ ! FpuPresent This indicates that your library should not be registered if it is installed on a Macintosh with a Floating Point Unit (FPU). No clients will be able to see any of the classes or function sets in your library. This flag is useful if you have 2 different versions of your library - one for an FPU being present, and one for it being absent.
flags = mc68000 = S mc68020 ~ ~ mc68030 S ~ mc68040 This indicates that your library should only be registered if it is installed on a Macintosh with the specified processors. You may specify more than one processor. For example, "flags=mc68000, mc68020" will cause your library to be registered only on 68000 or 68020 processors.
flags = ! mc68000 ~ ~ ! mc68020 ~ ~ ! mc68030 ~ ~ ! mc68040 This indicates that your library should not be registered if it is installed on a Macintosh that is not one of the specified processors. You may specify more than one processor. For example, "flags =!mc68000, !mc68020" will cause your library to be registered only on Macintoshes with a 68030 or higher processor.
It is an error to mix not ("! ") terms with non-not terms (i.e.
flags=mc68000,!mc68020).
id =
This declaration defines the ID of the library. A library ID is normally in the form "xxxx:yyyy$Name". This ID string is a quoted string, but it may include #defmed constants as part of it's definition as long as you #include the files that contain the #defme declarations that resolve the constants.
version =
This declaration defines the version of the library. The version number is in the standard Apple version number form: #.#[.#] followed by either nothing or [dabfj# to indicate the release status. For example l.Ob2 or 1.1.2d5. This may be a #defmed symbol.
memory =client This declaration indicates that any "new" operations done in the library should use the client's pool. This is the default if it is not specified. It is equivalent to the useclientpool options in earlier versions of SL1VI.
memory =local This declaration indicates that any "new" operations done in the library should use the local pool.
heap = default : = temp ~ ~ system ~ ~ application [,hold][,#]
This tells the SLM where you want your library to be loaded into memory.
Normally, you should not specify this attribute unless you have a very good ' reason. However, if your library must run under virtual memory and cannot move A
in memory (for instance, a networking driver), you can specify the ",hold" .
attribute to inform the SLM that you require the memory that your library is loaded into to be "held" under Virtual Memory. You can also optionally specify the size of the heap that you want your library to load into (this option only makes sense for default or temp).
clientData = < StructureName > _ ~ #
This tells the SLM that you require per-client static data. You can specify either a number of bytes or the name of a structure. Whenever you call GetClientData, you will then be returned a structure of the specified size.
The fnrst time the structure is created for a given client, it will be zeroed.
After the fnrst time, you will get back the structure corresponding to your current client. If you specify a structure name, the object file must have the type information available to determine the size of the structure, or an error will be generated.
The Class declaration A. full class declarations is:
Class < CIassName >
. version = < CIassVersion > ;
flags = preload, newobject, noVirtualExports, noMethodExports, noExports;
exports = <ListOfFunctionNames>;
dontExport= <ListOfFunctionNames>
private='' ~ <ListOfFunctionNames>
}:
Copyright Apple Computer 1991-1993 All fields except the < ClassName > are optional.
The minimalist class declaration is just:
Class < ClassName > ;
The id of the class must be #defmed as a constant of the form lc < ClassName > ID. It is optional (but a very good idea) for your class ID
to terminate with a "," followed by the version number of the class, especially if your class can be instantiated using the SLM NewObject function. This will keep your clients from inadvertently getting a wrong version of your class.

r . _ , .., .
Element Descriptions < ClassName >
This is the name of the class that you want to export.
version = ' This declaration defines the version of the class. The version number is in the standard Apple version number form: #.#[.#]. The version number may not have the extra. release information (like b2) on it. However, the version-number may be 2 version numbers separated either by 3 dots (...) or an ellipsis (option-;) character. This indicates the minimum version number of the class that this class is backwards-compatible with, and the current version number of the class. If you do not specify a version number, if the ClassID of the class has a version number in it, that will be used. Otherwise, the version number specified in the "Library"
declaration will be assumed. This may be a #defmed symbol.
flags =newobject This flag specifies that clients are allowed to create the class by ClassID
using the NewObject routine. A fatal error will occur at build time if this flag is set, but you do not have a default constructor for your class (a default constructor is one which takes no arguments), your class is abstract (has a "pure-virtual"
method), or the class size cannot be determined from symbol information in the object file.
flags =preload This flag specifies that an instance of the class should be created whenever the system boots up. A fatal error will occur at build time if this flag is set, but you do not have a default constructor for your class (a default constructor is one which takes no arguments), or your class is abstract (has a "pure-virtual"
method).
If this flag is set, the newobject flag is automatically set.

flags=noExports This flag specifies that no methods of this class are to be exported.
NewObject is the only way that a client can use your class if this flag is set and you do not export constructors in the exports= section, and they can only call virtual functions in the class, unless you explicitly export methods (see exports =
below).
flags =noVirtualExports This flag specifies that no virtual methods of this class are to be exported.
Fo:r the purposes of consistency in the SLM, the destructor of a class is NOT
considered a virtual method, even if it was defined that way. You can explicitly export some virtual functions using the exports = clause below.
flags=noMethodF.xports This flag specifies that no non-virtual methods of this class are to be exported. This includes constructors and the destructor for the class.
NewObject is the only way that a client can use your class if this flag is set and you do not export constructors in the exports = section exports =
This declares a comma-separated list of methods that you want to export from the class. It is normally used to override the "noExports"
"noMethodExports", or "noVirtualExports" flags for individual methods. You only need to specify the function name, but if it is a pascal function, you need to put the keyword "pascal" in front of the function name. Like C++, the SI M
considers ALL variants of a member function as the same function, and will export them all. To export operators, use the C++ syntax (e.g. operator+=). To export constructors, use the name of the class, and to export destructors, use - < Name of Class > .

WO 95/01598 ° PCTlUS94/07424 2~.6~30~
dontexport =
This declares a comma-separated list of functions that you do not want to export from the class. You only need to specify the function name, but if it is a r pascal function, you need to put the keyword "pascal" in front of the function name. Like C++, the SLM considers ALL variants of a member function as the same function, and will not export any of them. You may not use both exports =
and dontexport = for the same class.
private =
This declares a comma-separated list of methods that you want to export from the class privately. Any methods specified in this list will be exported, but will go into a separate client object file (defined by the -privateNear and/or -privateFar command-line switches to LibraryBuilder).
private =
This declares that all methods that can be exported should be exported privately. If you have set noMethodExports, then all virtual methods will be exported privately that are not either explicitly exported publicly by the exports =
clause or that are specifically excluded from being exported by a dontexport =
clause. If you have set no~rtualExports, then all non-virtual methods will be exported privately that are not either explicitly exported publicly by the exports =
clause or that are specifically excluded from being exported by a dontexport =
clause. If you have neither flag set, than all methods of the class will be exported privately that are not either explicitly exported publicly by the exports =
clause or that are specifically excluded from being exported by a dontexport =
clause.
It is an error to use this switch if the noExports flag is set.
The FunctionSet declaration FunctionSet < FunctionSetName >
( "
id = <CIassID>; required interfacelD = <CIassID>; optional O 95101598 , , PCT/US94/07424 version = < CIassVersion > ; optional, exports = < ListOfFunctionNames > ; optional dontexport = < ListOfFunctionNames >; optional private = *' ; < ListC)fFunctionNames > ; optional };
Copyright Apple Computer 1991-1993 If a function set does not have an exports = clause and it does not have a ~ontexport= clause, all global functions (that are not methods of a C++ class) will be exported (subject to any constraints set by the private= clause - see below) . If there are multiple function sets in a library, only one of them can be missing both of these clauses. The function set that is missing both clauses will export all of the global functions (that are not methods of a C++ class) that are not exported by any of the other function sets in the library.
Blement Descriptions < FunctionSetName >
This provides a unique name for your function set when linking.
id =
This declaration defines the classlD of the function set. A classID is normally in the form "xxxx:yyyy$SomeName". This ID string is as a quoted string, but it may include #defmed constants as part of it's definition as long as you #include the files that contain the #defme declarations that resolve the constants. If you do not include an "id = " declaration, a #defme found in the uicluded files whose name matches k < functionSetName > ID will be assumed to be the classff~ of the class. An error will occur at build time if the classlD
of the class cannot be determined.
interfacelD =
This declaration defines an interface ID for the function set. It has the same format as all other ClassIDs. By defining an interface ClassID, you can use the _87_ . ., SLM's FunctionSetInfo methods to fmd all Function Sets which have the same interface ID. Presumably, all function sets with the same interface ID export the same functionality, either by name or by index. This gives you a kind of object-oriented ability for ordinary functions.
version =
This declaration defines the version of the function set. The version number is in the standard Apple version number form: #.#[.#]. The version number may not have the extra release information (like b2) on it. However, the version number may be 2 version numbers separated either by 3 dots (...) or an ellipsis character (option-;). This indicates the minimum version number of the function set that this function set is backwards-compatible with, and the current version number of the function set. Nothing is done with this information in version 1.0 of SLM, but future versions will take advantage of this information. If you do not specify a version number, the version number specified in the "Library"
declaration will be assumed. This may be a #defmed symbol.
exports =
This declares a comma-separated list of functions~that you want to export in this function set. You only need to specify the function name, but if it is a pascal function, you need to put the keyword "pascal" in front of the function name. Like C + +, the SLM considers ALL variants of a function as the same function, and will export them all (unless you used the -c switch on the BuildSharedLibrary command line). If you are exporting a C++ class method, you should precede the method name with < ClassName > : : . For a C + + class method, the -c switch is ignored and all variants of the method are exported.
To export C++ operator overloads, use the C++ syntax (e.g. operator+=). To export constructors, use < ClassName > :: < ClassName > , and to export destructors, use < Cla.ssName > :: - < ClassName > . Some special keywords are , . available in this clause. They are:
_88_ 2~~~~~~ w << ~: ~ .. .
1) static <ClassName> - all static methods of the specified class will be exported.
2) class < ClassName > - all non-static methods of the specified class will be exported.
3) extern < FunctionName > - the specified function will be exported by name.
4) Pascal < FunctionName > - the specified function is a Pascal function. The "Pascal" keyword can be combined with the "extern" keyword, if necessary.
dontexport =
This declares a comma-separated list of functions that you do not want to export in this function set. It has the same syntax as the "exports = "
clause, except that the "static", "class" and "extern" keywords are not valid.
private =
This declares a comma-separated list of methods that you want to export from the function set privately. Any methods specified in this list will be exported, but will go into a separate client object file (defined by the -privateNear and/or -privateFar command-line switches to LibraryBuilder). If you have not defined an exports = or dontExport = clause, then all other functions will be exported publicly.
private =
This declares that all functions that can be exported should be exported privately. If you have not defined an exports = or dontExport = clause, then all of the functions will be exported privately. If you have an exports = clause, then the functions declared there will be exported publicly, and all others will be exported privately. If you have a dontExport = clause, then the functions declared there will not be exported at all, and all others will be exported privately.
If you have both clauses, those in the dontExport = clause will not be exported, those in the exports = Claus will be exported publicly, and all others will be exported privately.

2166~0~ ~ ~~
Conclusion Accordingly, the present invention provides a system extension that brings dynamic linking and dynamic loading to a computer system architecture through the use of shared libraries. The shared library manager allows you to turn almost any code into a shared library without modifying your sources and without writing any additional code. You write the code that goes into the shared library in your chosen source language or assembly, call it from any of those languages as well.
In addition, the system allows for calling virtual functions in a C++ class in a shared library without additional overhead.
This system is especially effective for C++ classes. Object oriented languages like C++ give programmers the power of modular design with innate code reuse and offer better ways of putting together programs. However, the concept of code reuse and modularity is not fully realized in many implementations today. A general mechanism for runtime sharing of classes allows developers to take more advantage of the object oriented benefits of C++. True code sharing and reuse becomes possible. Improvements in implementations of classes are immediately usable by all applications, without rebuilding the application that uses the class. It is possible to create a class that derives from a base class which is in a shared library leading to yet another term, dynamic inheritance. In fact, the subclass itself can be in a shared library.
Thus, the present invention is particularly appropriate for applications that want to allow modules to be added on at a later time. If the modules are placed in shared libraries, the application can check to see which modules exist, and choose which modules to use.
In addition, tools such as spellcheckers are well suited for shared libraries according to the present invention. If all spellcheckers share a common interface, the application can choose which spellchecker to use. Also, the spellchecker can be used by more than one application at the same time.
In general, any code that you want to share between one or more applications is a candidate for a shared library. This is especially useful for large software companies that sell multiple applications that contain some common code.

The shared library manager makes it easy to share this code. For example, a word processor might want to take advantage of some of the graphics capabilities of a graphics program. Such abilities might be placed in shared libraries and dynamically linked according to the present invention.
Some key features of the shared library manager include the following.
Dynamic Linking and Loading Shared libraries are loaded and linked with clients at run time (and unloaded when no clients are using them). Loading occurs on-demand, not at launch time.
But the user may force libraries to load at launch time to be sure of their availability.
Dvnamic Installation Shared library files may be dragged in and out of the Extensions folder without having to reboot to use the shared libraries.
Usage Verification An application can verify that a set of classes or functions required for proper operation of the application is available. The shared libraries required can then be loaded, or loading can be delayed until the code is needed.
L~ry Preloading To guarantee that a library will be available when it is needed, a shared library may be set to preload at boot time, or it may be explicitly loaded by a client after boot time but before any classes or functions are actually used.
Performance The Shared Library Manager provides high performance dynamic loading and linking of function sets and classes, high performance construction, use, and destruction of objects. In C++, a method or virtual function is called by a single indirection through a table of pointers to the function implementations (called the A.
v-table or virtual function table). A dynamically linked function or procedure is "snap-linked", which means that the binding overhead occurs only once, after which the target address is cached (the link is "snapped") in the client.
This calling mechanism is much more efficient than the Macintosh Device Manager dispatching which is used by device drivers, or the A-trap plus selector code mechanism used by stand-alone code resources on the Macintosh (such as CDEFs, WDEFs, and the Communications Toolbox). Other mechanisms such as IPC messages are also inefficient by comparison and not well suited for time critical use (as required by high performance networking protocols or other high performance device drivers).
Dynamic Inheritance A class may inherit from a class which is not in the same shared library file.
This also means that a developer can create a class that inherits from another developer's class. The new subclass can either be in another shared library or in the application code.
Dynamic Class Creation When creating an object, you can dynamically-create it by name. This allows an application to create objects of classes it has never seen before.
Generally, these objects are a subclass of a class the application does know about.
Class Verification A client can verify at run-time that a given class is derived from a particular base class or that an object is of a particular base class. Dynamic class creation and class verification are used together.
The foregoing description of preferred embodiments of the present invention has been provided for the purposes of illustration and description. It is not intended to be exhaustive or to limit the invention to the precise forms disclosed.
Obviously, many modifications and variations will be apparent to practitioners skilled in this art. The embodiments were chosen and described in order to best WO 95!01598 . PCT/US94/07424 explain the principles of the invention and its practical application, thereby enabling others skilled in the art to understand the invention for various embodiments and with various modifications as are suited to the particular use contemplated. It is intended that the scope of the invention be defined by the following claims and their equivalents.
A computer program listing appendix under 37 C.F.R. ~1.96 follows, consisting of 54 pages.

WO 95/01598 ; . , :..: PCTIUS94/07424 COMPUTER PROGRAM LISTING APPENDIX
37 C.F.R. ~1.96 Copyright Apple Computer 1991-1993 void* TLibraryManager::InternalCastObject(VTabIeRec* vtRec, void* theObject, ' const TCIassID& baseCIassID, int level, Boolean checkVirtuals) const //
// Scan through all of the parent classes of theClass, and see if // any of them have baseCIassID as a parent. If one does, return // kNoError. But... If the object has several parents with that // same baseCIassID, then we are NOT RELATED, so we have to keep // looking after we find one to be sure.
//
void* answer = NULL;
VTabIeRec* pvtRec = vtRec - 1;
do pvtRec + = 1;
//
// If this VTable is not a parent vtable, then the parent VTabIeRec // is obtained by GetParentCVR().
/! If this VTable is Castable and it's either not Virtual, or we're // supposed to look at virtual parents, then the "castable" parent // VTabIeRec is obtained by GetLocaICVR.
//
ClientVTabIeRec* theParentRec = NULL;
if (lpvtRec-> IsParentVTable(1) theParentRec = pvtRec->GetParentCVR(1;
else if ((pvtRec-> LocaICVRIsParent() &&
ilpvtRec-> ParentlsVirtual() ~ ; checkVirtualsl)) theParentRec = pvtRec-> GetLocaICVR();
if (theParentRec) TCIassID* templD = (TCIassID*)theParentRec->fCIassIDStr;
if (*templD = = baseCIassID) //
// If this is level 0, or the parent is virtual, then this // is the "definitive" cast at this point in time.
//
if (level = = 0 ~ ~ pvtRec-> ParentlsVirtual()) long offset = pvtRec->GetObjectOffset(1;

WO 95/01598 ~ ~~ PCT/US94/07424 return (offset = _ -1 L) ? NULL : (char*)theObject - offset;
long offset = pvtRec->GetObjectOffset();
if (answer ! = NULL ; ; offset = _ -1 L) return NULL;
answer = (char*)theObject - offset;
}
else r TClass* parentClass;
if (IpvtRec-> IsParentVTable()) parentClass = (TClass*)ltheParentRec->fCIassLinkPtr->GetValue()1;
else parentClass = fCIassCatalog->LookupClass(*templD);
//
// Call ourselves with the "real" VTabIeRec pointer for the parent // class, and theObject properly "offsetted".
//
long offset = pvtRec->GetObjectOffset(1;
if (offset = _ -1 L) return NULL;
void* temp = InternalCastObject(parentClass->GetVTabIeRecPtrFast(), (char*)theObject - offset, baseCIassID, level + 1, false);
if (temp) if (answer) return NULL;
answer = temp;
}
}
}
} while (lpvtRec-> IsSoloVTable() && lpvtRec-> IsLastParent()l;
return answer;
}
void* TLibraryManager::CastObject(const void* theObject, const TCIassID&
baseCIassID, OSErr* errPtr) const OSErr err = kNoError;
void* answer = NULL;
void* newObject;
if (errPtr) *errPtr = kNoError; // so we can do blind returns if successful if (llsValidTDynamic((const TDynamic*)theObject)) if (errPtr) *errPtr = klnvalidObject;
return NULL;
}

WO 95/01598 ~ ~] PCT/US94/07424 ... ' ' if (fCIassCatalog->LookupClass(baseCIassID) _ = NULL) if (errPtr) *errPtr = kNotFound;
return NULL;
VTabIeRec* vtRec = **(VTabIeRec***)CastToPtr(theObject);
/!
// If it's a parent VTable, then first, let's see if we can // cast it without moving back to the base class. This will allow // us to cast objects that have duplicated base classes as long // as they are not in the same tree.
//
if (vtRec-> IsParentVTable()) if (vtRec->GetLocaICVR() I= NULL) TClass* temp = fCIassCatalog->LookupClassi*vtRec->GetLocaICIassID());
if (temp && temp->GetVTabIeRecPtrFast()) answer = InternalCastObject(temp->GetVTabIeRecPtrFast(), CastToPtr(theObject), baseCIassID, 0, false);
if (answer) return answer;
l/
// OK, that didn't work. Now, let's move back to the main object // and try the cast that way.
//
if (vtRec->GetObjectOffset() _ - -1 ) return NULL;
newObject = (char''lCastToPtrItheObject) + vtRec->GetObjectOffset();
vtRec = *'*(VTabIeRec"'*)CastToPtr(newObject);
else newObject = CastToPtr(theObject);
//
// If this is the right class id, then return the offsetted object.
//
if (*vtRec->GetLocaIClassIDi1 == baseCIassID) return newObject;
answer = InternalCastObject(vtRec, newObject, baseCIassID, 0, true);
if (answer = = NULL) err = kNotRelated; ' if (errPtr) *errPtr = err;
return answer;

WO 95/01598 ,~ ~ ' PCT/US94/07424 TClasslnfo* TLibraryManager::GetCIassInfolconst TCIassID& theCIassID, OSErr*
errPtr) const TClasslnfo* thelnfo = NULL;
if (errPtr) *errPtr = kNoError;
if (fCIassCatalog->LookupClass(theCIassID) != NULL) Tlterator* thelterator = fCIassCatalog->fClasses->Createlterator(fPool);
if (thelterator) thelnfo = new (fPool) TClasslnfo;
if (thelnfo) thelnfo->fBaseCIassID = theCIassID;
thelnfo->flterator = thelterator;
thelnfo-> Reset();
else delete thelterator;
if (errPtr) *errPtr = kOutOfMemory;
else if (errPtr) *errPtr = kNotFound;
return thelnfo;
void* TLibraryManager::NewObject(const TCIassID& classlD, OSErr* err, TStandardPool* pool) const Boolean ndUnload = false;
#if qDebug Trace("TLibraryManager::NewObject - CIassID = 96s\n", &classlD);
#endif void* the0bj = NULL;
VTabIeRec* theVTabIeRec = NULL;
OSErr err2 = kNoError;
TClass * theClass;
if (pool = = NULL) pool = GetObjectPool();
/* get the VTabIeRec for the class first */
theClass = fCIassCatalog->LookupClass(classlD, false);

WO 95/01598 ~ , . ~ PCT/US94/0742 if (theClass) if (ltheClass->NewObjectSupported()) err2 = kNotSupported;
else if (theClass->GetLibrary()) err2 = theClass->GetLibrary()->Load(false); /1 make sure the code is loaded first if (err2 = = kNoError) theVTabIeRec = theClass->GetVTableRecPtrFast();
ndUnload = true; // we'll do an unload later else // it's a root class theVTabIeRec = theClass->GetVTabIeRecPtrFast();
else err2 = kNotFound;
if (theVTabIeRec) if (theVTabIeRec-> CanNewObject()) theObj = pool->Allocate(theVTabIeRec->GetSizei)):
if (theObj) ConstructorPtr constructor = (ConstructorPtr)theVTabIeRec-> fExportTable[1 );
if (constructor) TRY /' constructors code or code it calls may not be loaded ~'/
CaIIConstructorltheObj, constructor);
CATCH ALL
err2 = ErrorCode();
EN DTRY
else pool-> Free(theObj);
the0bj = NULL;
err2 = kNotSupported;
else err2 = pool-> IsValid() 1 kOutOfMemory : kPooICorrupted;
else err2 = kNotSupported;

WO 95/01598 ~~ PCT/LTS94/07424 if (ndUnload) theClass-> GetLibrary()-> Unload();
#if qDebug if (err2) Trace("NewObject failed: err = °~d\n",err2);
#endif if (err) *err = err2;
return theObj;
void'' TLibraryManager::NewObject(constTCIassID& classlD, constTCIassID&
parentlD, OSErr~ err, TStandardPool* pool) const-OSErr verifyErr;
verifyErr = VerifyClass(classlD, parentlD);
if (verifyErr = = kNoError) return NewObject(classlD, err, pool);
else if (err) ''err = verifyErr;
return NULL;
void'' TLibraryManager::NewObject(const TFormattedStream&, OSErr'", TStandardPool*') const l'' 96~°k needs implentation '~/
return NULL;

~ 1 ~6v6°~~~~T
int TLibraryManager::InternalVerifyClass(TCIassID* thelD, const TCIassID&
baseCIassID, int level, Boolean& sawVirtual) const f // _ // If this guy matches, return kNoError //
Boolean isVirtual"I = false;
int saw = 0; ' if (*(char*)thelD = - '*') isVirtual = true;
thelD = (TCIassID*)((char*)thelD + 1 );
//
// If we match the class ID - then // if we are at level 0, return a 1.
// If it's a virtual parent, set sawVlrtual to true.
// Otherwise, flag that we've seen the class once.
//
if (*thelD = = baseCIassID) if (level = = 0) return 1;
else if (isVirtual) sawVirtual = true;
else saw = 1;
TClass* theClass = fCIassCatalog->LookupClass(*thelD);
if (theClass = = NULL) return -1;
//
// Scan through all of the parent classes of theClass, and see if' // any of them have baseCIassID as a parent. Keep track of how many // we saw. We need to continue scanning to the base of the tree since // if we ever see the class as a virtual base class, then the answer is // YES, we are related - no matter how many times we saw the class //
size_t idx = 0;
TCIassID* templD;
int retval;
while (templD = theClass->GetParentlD(idx++)) switch (retval = IntemalVerifyClass(templD, baseCIassID, level + 1, sawVirtual)) case 0:
break;
case -1:
return retval;

~O 95/01598 ,. PCT/US94/07424 default:
saw + = retval;
return saw;
OSErr TLibraryManager::VerifyCfasslconst TCIassID& classlD, const TCIassID&
baseCIassID) const Boolean sawVirtual = false;
TCIassID~' thelD = (TCIassID~')CastToPtr(&classlD);
switch (InternalVerifyClass(thelD, baseCIassID, 0, sawVirtual)) case -1:
return kNotFound;
case 1:
if (sawVirtual) return kNotRelated;
return kNoError;
case 0:
return sawVirtual ? kNoError : kNotRelated;
default:
return kNotRelated;

/*
*/
File: CIassCatalog.h Contains: Declaration of the TCIassCatalog class To Do:
#ifndef _CLASSCATALOG_ ' #define CLASSCATALOG
#ifndef _LIBRARYMANAGERCLASSES_ #include < LibraryManagerClasses.h >
#endif #ifndef _SLMGLOBAL_ #include < SLMGlobal.h >
#endif #ifndef _VTABLETOOLS_ #include < VTabIeTools.h >
#endif /***************************************************************
* * Forward class declarations ****************************************************************/
class TCIassCatalog;
class TLibraryManager;
class TLibraryFileManager;
class TClass;
class TLibraryFile;
class LoadList;
class Tlnspector;
class TlnspectorHelper;
struct AAPBRec;
/***************************************************************
* * Some Typedefs ****************************************************************/
typedef void (*RunSystemTasksProcPtr)(unsigned long);
/***************************************************************
* * Class TCIassCatalog **
* * TCIassCatalog's keep track of TClasses, most likely for a TLibraryManager.
* * You can register and unregister TClasses and also look them up based on * * their classld. Normally there will only be 1 TCIassCatalog running on the * * system unless there is a need to keep a group of classes private.
**********t*****************************************************/
#define kTCIassCataloglD ")Sccat,l.1"

~O 95/01598 PCT/US94/07424 class TCIassCatalog : public TDynamic friend class TLibraryManager;
public:
TCIassCatalog();
virtual -TCIassCatalog();
//
// Keep these at the front. The stub file generator assumes /l they are here!
//
#if COMPAT10 virtual VirtuaIFunction ExecDestructor(ClientVTabIeRec*) const;
virtual VirtuaIFunction ExecConstructor(ClientVTabIeRec*, size_t idx) const;
virtual VirtualFunction ExecVTabIeEntry(ClientVTabIeRec*, size_t idx) const;
virtual VirtuaIFunction ExecExportEntry(ClientVTableRec*, size_t idx) const;
virtual void ExecFunction(FunctionStubRec*, TLibraryManager*) const;
virtual VirtuaIFunction ExecRootDestructorICIientVTabIeRec*) const;
virtual VirtualFunction ExecRootConstructor(ClientVTabIeRec*, size_t idx) const;
virtual VirtualFunction ExecRootVTabIeEntry(ClientVTabIeRec*, size_t idx) const;
virtual VirtuaIFunction ExecRootExportEntry(ClientVTabIeRec*, size_t idx) const;
#endif virtual VirtuaIFunction LookupFunction(FunctionStubRec* theStubRec, TLibraryManager* theMgr);
virtual VTabIeRec* GetVTabIeRecMemory(size t num) const;
virtual VTabIeRec* Init1 VTabIeRec(VTabIeRec* vTabIeRec, ProcPtr setupProc, ClientVTabIeRec* client) const;
virtual VTabIeRec* InitVTabIeRec(VTabIeRec* vTabIeRec, Viable viable, Viable exTable, ClientVTabIeRec* parent, long size, char*) const;
virtual VTabIeRec* InitVTabIeRec(VTabIeRec*, Viable exTable, char*) const;
#if COMPAT10 virtual VTabIeRec*GetGenVTabIeRec(ClientVTabIeRec*) const;

#endif //

// Knowledge of these 3 offsets is in our assembly language code (VTable.a) //

virtual VTabIeRec*LookupVTabIeRec(ClientVTabIeRec*
theClient) const;

virtual VTabIeRec*GetVTabIeRec(ClientVTabIeRec*, Boolean isSub = true) const;

virtual VTabIeRec*ReleaseVTabIeRec(ClientVTabIeRec*) const;

//

// Knowledge of these 2 offset is in DeveloperUtilities.cp //

virtual OSErr InitLibraryManager(TLibraryManager**, long*, size t WO 95/01598 . 'k PCTIUS94/07424 poolsize, ZoneType theZone, MemoryType theMemType);
virtual Boolean CleanupLibraryManager(TLibraryManager**);
//
// Knowledge of these 4 offsets is in our assembly language code (VTable.a) /l virtual VirtuaIFunction GetDestructor(StructorStubRec*, TLibraryManager*) const;
virtual VirtualFunction GetConstructor(StructorStubRec*, TLibraryManager*, ' Boolean isSub) const;
virtual VirtuaIFunction GetVTabIeEntry(CIassStubRec*, TLibraryManager*) const;
virtual VirtuaIFunction GetExportEntry(CIassStubRec*, TLibraryManager*) const;
//
// Knowledge of this offset is in the LibraryBuilder tool //
virtual VTabIeRec* GetParentVTabIeReciCIientVTabIeRec*) const;
//
// Knowledge of these 4 offset is in DeveloperUtilities.cp //
virtual Boolean InstaIIDeathWatcher(TNotifier*);
virtual Boolean RemoveDeathWatcher(TNotifier*);
virtual void NotifyDeathWatchClients(TLibraryManager*) const;
virtual void LeaveCodeResource(GIobaIWorld savedWorld, TLibraryManager* savedClient);
// Inspector dependent on this offset - must be rebuilt if changed virtual void Registerlnspector(Tlnspector*);
//
// below here you can move stuff around .
//
#if qDebug virtual void Dump() const;
#endif // New Methods TCollection* GetClasses() const;

TSimpIeList* GetLibraryFiles() const;

TSimpIeList* GetLibrariesp const;

TSimpIeList* GetLibraryFileManagersp const;

SLMGlobal* GetSLMGlobalp const;

virtual TClass*LookupClass(const TCIassID&
theCIassID, Boolean isSubClass = true, Version = 0) const;

virtual TClass*LookupClass(ClientVTabIeRec*, Boolean isSubClass = true, TLibrary* = NULL) const;

~i'O 95/01598 . ' PCT/US94/07424 . , ~, E
virtual TLibrary* LookupLibrary(const TLibrarylD&) const;

virtual void RegisterClass(TClass* theClass);

_ virtual void UnregisterClass(TClass* theClass);

virtual void RegisterLibraryFileManager(TLibraryFileManager*);

' virtual void RegisterDynamicObject(TDynamic*, Boolean onlylflnspecting = false);

virtual void UnregisterDynamicObject(TDynamic*);

virtual RunSystemTasksProcPtr GetRunSystemTasksProc() const;

virtual void SchedulelnitGrafProc() const;

virtual void InstaIIVectors();

virtual Boolean ShutDownForlnstaller(AAPBRec* pb);

virtual Boolean OkToUnIoadLibraryManager(Boolean ifDecUseCount);

virtual TLibraryFileManager*

GetApplicationFileManager() const;

virtual TCIassID* CreateCIassID(char*);

#ifdef ForROM

virtual void RegisterMacOSLibraryFileMgr(); // only needed for ROM

Builds #endif virtual void InstaIIPatches();

virtual void RemovePatches0;

private:

SLMGlobal * fGlobals;

TSimpIeList* fLibraryFileManagers; // registered TLibraryFileManager's TSimpIeList* fLibraryFiles; // all TLibraryFiles TSimpIeList* fLibraries; // all TLibraries THashList* fClasses; // all Classes known to the TCIassCatalog THashList* fCIassIDs; // all CIassIDs known to the TCIassCatalog Tlnspector* flnspector;

TlnspectorHelper* flnspectorHelper;

TSimpIeList* fDeathWatchers;

TMacSemaphore fSemaphore;

Boolean fDontRegisterObjects;

};

' /* _________________________________________________________________________ inlines for TCIassCatalog _________________________________________________________________________ */

inline TCollection* TCIassCatalog::GetClasses() const ;, . , .
return fClasses;
inline TSimpIeList* TCIassCatalog::GetLibraryFiles() const { _ return fLibraryFiles;
inline TSimpIeList* TCIassCatalog::GetLibraries() const ' {
return fLibraries;
inline TSimpIeList* TCIassCatalog::GetLibraryFileManagers() const {
return fLibraryFileManagers;
inline SLMGlobal* TCIassCatalog::GetSLMGlobal() const {
return fGlobals;
#endif ' /***************************************************************
** PUBLIC Load ****************************************************************/
OSErr TLibrary::Load(Boolean forceAll, PreloadList* IoadList) {
OSErr result = kNoError;
if (llsCodeLoadedU) {
if ((result = ReaIlyLoad(forceAll, IoadList)) _ = kNoError) IncrementUseCount();
else {
// if forceAll was specified then we need to make sure all of the code // segments are loaded if (forceAll) {
Loadedlnfo* info = GetLoadedlnfo();
for (short theSegID = klmplementationSegment; theSegID < = info >fNumCodeSegs; theSegID++) {
if (info->fCodeSegments(theSegID-1 ) _ = NULL) OSErr err = LoadSegment(theSegID);
if (err) return err;

if (IoadList) result = GetLibraryFile()->GetLibraryFileManager()->
GetLoadList(GetLoadedlnfo()-> fCodesLibraryManager,loadList);
if (result = = kNoError) IncrementUseCount();
return result;
/***************************************************************
* * PUBLIC Unload ***************************************************************/
void TLibrary::Unload() Boolean ndRelease = true;
gSemaphore-> Grab();
if (lfUseCount.IsUnused()) if (fUseCount.Decrement() && IsLibraryLoadedp) //
// If we're not on the list, add us on and schedule // the unloader, if necessary. We have // an f!_ink field that is not really a TLink, so // we cast it as one to make everybody happy.
//
if (lfUnIoadScheduled) //
// If the useCount reached 0 as a result of another library // being unloaded, then unload the library right away. Note /l that the library will only be partially unloaded and the // remainder of the unloading is handle by the UnIoadScheduler.
l/
Boolean unloadNow = gProcessingUnloads && lAtlnterruptLevel();
if (unloadNow) fLibraryLoaded = false; // it's no longer safe to assume we are loaded after this point gUnIoadList-> AddLinkFirst((TLink*)&fLink);
fUnIoadScheduled = 1;
if (lgOpScheduled) ..
gOpScheduled = true;
gSemaphore-> Release();
ndRelease = false;

WO 95/01598 PCTlUS94107424 GetSLMG lobal ()- > fUnIoadScheduler- > Schedule(gUnIoadCodeOp);
if (unloadNow) ReaIlyUnload(true);
else DebugBreak("TLibrary::Unload: fUseCount < 0");
if (ndRelease) gSemaphore-> Release();
/***************************************************************
* * PROTECTED ReaIlyLoad ***************************************************************/
OSErr TLibrary::ReaIlyLoadCBoolean forceAll, PreloadList* IoadList) OSErr err;
void* savedZone;
long savedRefNum;
TLibraryFileManager* fileMgr = GetLibraryFileU->GetLibraryFileManager();
if (AtlnterruptLevel()) // fail at interrupt time return kCodeNotLoaded;
if (fFlags & kLibraryNoSegUnIoadFlag) forceAll = true;
savedZone = EnterSystemMode();
if ((err = GetLibraryFile()-> OpenLibraryFile()) ! = kNoError) LeaveSystemMode(savedZone);
return err;
if ((err = GetLibraryFile()-> Preflight(savedRefNum)) ! = kNoError) GetLibraryFilefl-> CIoseLibraryFileU;
LeaveSystemMode(savedZone);
return err;
err = fileMgr->LoadLibrary(this, IoadList, forceAll);
if ierr 1= kNoError) fCodeLoaded = false;

~~~,., p ,.
fUseCount.lnit();
/* If we were able to Preflight the file then PostFlight it. If we can */
/* PostFlight the file but were unsuccessful in loading the code then */
/* close the file. */
if (GetLibraryFile()-> Postflight(savedRefNum) _ = kNoError) if (err ! = kNoError) GetLibraryFile()-> CIoseLibraryFile();
if (err = = kNoError) GetLibraryFile()-> PreloadClasseslthis);
fLibraryLoaded = true; // the library is done loading now LeaveSystemModelsavedZone); // back to state we were in return err;
/***************************************************************
** PUBLIC Unload ***************************************************************/
void TLibrary::Unload0 Boolean ndRelease = true;
gSemaphore-> Grab();
if (IfUseCount.IsUnused()) if (fUseCount.Decrement() && IsLibraryLoaded()) //
// If we're not on the list. add us on and schedule // the unloader, if necessary. We have // an fLink field that is not really a TLink, so // we cast it as one to make everybody happy.
/l if (IfUnIoadScheduled) //
// If the useCount reached 0 as a result of another library // being unloaded, then unload the library right away. Note // that the library will only be partially unloaded and the // remainder of the unloading is handle by the UnIoadScheduler.
//
Boolean unloadNow = gProcessingUnloads && lAtlnterruptLevel();
if (unloadNow) fLibraryLoaded = false; // it's no longer safe to assume we are loaded after this point gUnIoadList->AddLinkFirst((TLink*)&fLink);
fUnIoadScheduled = 1;
if (!gOpScheduled) gOpScheduled = true;
gSemaphore-> Release();
ndRelease = false;
GetSLMGlobal()->fUnIoadScheduler-> Schedule(9UnIoadCodeOp); ' if (unloadNow) ReaIlyUnloadltrue);
else Debug Break("TLibrary::Unload: fUseCount < 0");
if (ndRelease) gSemaphore-> Release();
/**********************************************************~.****
** PUBLIC LookupVTabIeRec ***************************************************************/
VTabIeRecPtr TLibrary::LookupVTabIeRec(const TCIassID* classlD, OSErr* err) if (lAreVTablesSafe()) DebugBreak("TLibrary::LookupVTabIeRec - attempt fo get an unsafe vtable");
if (err) *err = kCodeNotLoaded;
return NULL; /l someone tried to get an unsafe vtable at interrupt time //
// find theVTabIeRec that matches theClient->fCIassIDStr // However, do not look at "parent" VTabIeRecs //
size_t idx;
size_t num = GetLoadedlnfoU->fVTabIeRecArray->fNumVTabIeRecs;
VTabIeRec* vtRec = GetLoadedlnfo()->fVTableRecArray->fVTabIeRec;
for (idx = 0; idx < num; + + idx, vtRec + = 1 ) if (IvtRec->isParentVTablep) if (strcmp((const char*)classlD, (char*)vtRec->GetLocalCIassID()) _ = 0) .
break;
if (err) if (idx > = num) *err = kNotFound;
else *err = kNoError;
return (idx > = num) 1 NULL : GetLoadedlnfo()->fVTabIeRecArray->fVTabIeRec +
idx;
VTableRecPtr TLibrary::LookupVTabIeRec(ClientVTabIeRecPtr theClient, OSErr*
err) VTabIeRecPtrtheVTabIeRec =LookupVTabIeReciITCIassID * )theClient-> fClassl DStr, err);
if (theVTabIeRec) theClient->fCodeSerialNumber = fCodeSeriaINumber;
return theVTabIeRec;
/*,.*************************************************************
* * PROTECTED ReallyUnload ***************************************************************/
void TLibrary::ReaIlyUnload(Boolean delayedUnload) Boolean firstPass = lfi=irstPassComplete;
Boolean IastPass = fFirstPassComplete ~ _ ldelayedUnload;
void* savedZone = EnterSystemMode(); /* make sure we do everything in system mode */
if (firstPass) // CYA for when ReaIlyUnload is called by someone other than ProcessUnload.
fLibraryLoaded = false;
GetSLMGlobal()-> fCIassCatalog-> NotifyDeathWatchClients(GetLoadedlnfo() > fCodesLibraryManager);
//
// Call the CleanupProc for the library - Make sure the global // world and client are set up to the library itself.
//
GIobaIWorld savedWorld = ::SetCurrentGlobaIWorld(GetLibraryWorld());
. TLibraryManager* savedClient = SetCurrentClient(GetCodesLibraryManager());
(*GetLoadedlnfo()->fCleanupProc)();
//
// Reset our usecount now //
fUseCount.SetValuelGetLoadedlnfo()-> fSavedUseCount);

_ s~. ' //
// Call any cleanup routines that were specified l/
TLibraryManager*~ myMgr = GetCodesLibraryManager();
ProcPtr* procs = (ProcPtr*)myMgr->GetClientlnfo(0);
if (procs) size t num = (size t)CastToLong(procsLO]); ' for (size t idx = 1; idx < = num; + +idx) if (procstidx]) //
// Just in case we can't load the segment. It was preloaded, if possible, // but for ThinkC that's not possible.
l/
TRY
(procs fidx]) ();
ENDTRY
myMgr->SetClientlnfo(0, NULL);
delete (void*)procs;
SetCurrentClient(savedClient);
::SetCurrentGlobalWorld(savedWorld);
if (IastPass) TSimpIeList* clientList = GetLoadedlnfo()->fClients;
GetLoadedlnfo()->fClients = NULL;
if (clientList) TLibraryManager* Imgr;
while flmgr = (TLibraryManager*)clientList->RemoveFirst()) !/
// If the client record is a ClientData record, then deal with // it appropriately.
/l if (CastToLong(Imgr) & 1 ) TCIientData* data = (TCIientData*)((char*)Imgr - 1 );
data-> GetClient()-> DetachLibrary(this);
else Imgr-> DetachLibrarylthisl; , delete clientList;

WO 95/01598 PCTlUS94/07424 f GetLibraryFile()-> GetLibraryFileManager()-> UnIoadLibrary(this);
if (delayedUnload && firstPass) CodeUnloaded(true);
fFirstPassComplete = true;
if (IastPass) fLibraryFile-> CIoseLibraryFile();
fFirstPassComplete = false;
LeaveSystemMode(savedZone); // back to state we were in class Loadedlnfo public:

//

// All "Loaded"
Info Structure must start off with these // first 6 fields.

//

TLibraryManager*fCodesLibraryManager;// Library's TLibraryManager VTabIeRecArray* fVTabIeRecArray; // the list of vtable records ProcPtr fCleanupProc; // pointer to the library Il cleanup proc long fSavedUseCount; // fUseCount after Load() is !/ called for first time GIobaIWorld fLibraryWorld; // the Library's shared A5 world TSimpIeList* fClients; // Current client library managers Ptr* fCodeSegments; // pointers to the loaded code // segments short fNumCodeSegs; // number of loaded code // segments short fFiller;

TLibraryManager*fLastClient;

void * fLastCIientData;

};
class TLibrary : public TDynamic public:
TLibrary(TCIassID* thelD, ResType theType, short reslD, Version theVersion, unsigned short clientDataSize, size t codeZoneSize, long theFlags, unsigned char compilerType, WO 95/01598 . ~ PCT/US94/07424 TLibraryFilePriv* theLibraryFile);
virtual -TLibrary();

// TDynamic Overrides virtual char*
GetVerboseNametchar*) const;

// New methods // These are methodsmight get exposed to the user someday so that keep them I/ up front. They are already exposed through glue code so don't change /! their order after 1.1 goes GM.

virtual OSErr LoadSegment(long theSegld); /l this guy will // return an error virtual OSErr LoadSegment(ProcPtr theRoutine); // this guy will ream an error virtual OSErr UnIoadSegment(long theSegld);

virtual OSErr UnIoadSegment(ProcPtr theRoutine);

virtual void* GetCIientData(TLibraryManager*);

virtual void DetachClient(TLibraryManager*);

virtual void AddClient(TLibraryManager*);

OSErr Load(Boolean forceAll, PreloadList* = NULL);

void Unload(1;

void IncrementUseCount();

Boolean DecrementUseCount();

TLibraryFilePriv*GetLibraryFile() const;

TLibraryManager* GetCodesLibraryManager() const;

ResType GetCodeType() const;

long GetSeriaINumber() const;

long GetFlags() const;

Boolean OkToUnload() const; /* can we load the code *I

int IsLibraryLoadedf) const;

int IsCodeLoaded() const;

Boolean AreVTabIesSafe() const;

int AreVTableslnitialized(1 const;

GIobaIWorld GetLibraryWorld() const;

short GetLibraryLibrID() const;

void SetPreloadFlag();

int IsDuplicatei) const;

void SetIsDuplicate(int);

VTabIeRec* LookupVTabIeRec(const TCIassID* classlD, OSErr* = NULL);

VTabIeRec* LookupVTabIeRec(ClientVTabIeRec*,OSErr*

= NULL);

Version GetVersion() const; , TCIassID* GetID() const;

Loadedlnfo* GetLoadedlnfo() const;

~O 95/01598 ~PCT/US94/07424 void SetLoadedlnfo(Loadedlnfo*);
size t GetCodeZoneSize() const;
void* PrivateLoadSegment(long theSegld); //this // can /tow // an // exception virtual void InformDebuggerAboutLoadedSegments();
//
// Don't mess with these 3 //
void InformDebuggerOfSegmentStatus(long id, void* theCode, Boolean ifLoad);
void CodeLoadedlProcPtr codeEntry, Ptr);
void CodeUnloaded(Boolean delayedUnload = false);
void InitializeCode(ProcPtr codeEntry, PreloadList*);
OSErr ReaIlyLoadIBoolean forceAll, PreloadList* = NULL);
void ReaIlyUnload(Boolean delayedUnload = false);
Boolean LoadLibraries(PreloadList*);
CompilerType GetCompilerType() const;
protected:
static void ProcessUnload(TOperation *);
static TOperation*gUnIoadCodeOp;

static TSimpIeList*gUnIoadList;

static TMacSemaphore*gSemaphore;

static Boolean gOpScheduled;

static Boolean gProcessingUnloads;

private:

//

// LoadCodeSegment.a depends on this first field // and the Stubs generated by 1.1 depend on the 2nd field.

//

Loadedlnfo* fLoadedlnfo;

TUseCount fUseCount;

//

void* fLink;

TCIassID* fLibrarylD; // id of this library TLibraryFilePriv*fLibraryFile; // TLibraryFile in charge of this instance long fCodeSeriaINumber; // changes when the code is // unloaded long fFlags; // code resource flags ResType fCodeType; // code resource type short fResID; // Resource ID

Version fVersion; // packed version =

// major+minor bytes unsigned shortfClientDataSize; // Size of Client Data ~~~~,~302 size_t fCodeZoneSize; // 0 if not specified CompilerType fCompilerType;
unsigned fLibraryLoaded:1; // true only if we are completely done // loading the library unsigned fCodeLoaded:l ; // true if code is loaded, but vtables may // not // have been initialized yet unsigned fVTableslnitialized:1; // true if vtables have been initialized unsigned fFirstPassComplete:1; // true if first unload pass has been made unsigned fUnIoadScheduled:1;
unsigned flsDuplicate:1;
unsigned fFiller:2;
};
/* _________________________________________________________________ inline methods */
inline long TLibrary::GetFlags() const {
return fFlags;
inline TLibraryFilePriv* TLibrary::GetLibraryFile() const {
return fLibraryFile;
inline Loadedlnfo* TLibrary::GetLoadedlnfo() const {
return fLoadedlnfo;
inline void TLibrary::SetLoadedlnfo(Loadedlnfo* info) {
fLoadedlnfo = info;
inline TLibraryManager* TLibrary::GetCodesLibraryManager() const {
return GetLoadedlnfo() ? GetLoadedlnfo()->fCodesLibraryManager : NULL;
inline ResType TLibrary::GetCodeType() const {
return fCodeType;
., inline long TLibrary::GetSeriaINumber() const return fCodeSeriaINumber;

~O 95/01598 PCT/US94/07424 . ; . .. t inline GIobaIWorld TLibrary::GetLibraryWorld() const return GetLoadedlnfol)->fLibraryWorld;
inline short TLibrary::GetLibraryLibrID() const return fResID;
inline Boolean TLibrary::OkToUnload() const return fUseCount.IsUnused();
inline int TLibrary::IsLibraryLoaded() const return fLibraryLoaded;
inline int TLibrary::IsCodeLoaded() const return fCodeLoaded;
inline int TLibrary::AreVTableslnitialized() const f return fVTableslnitialized;
inline Boolean TLibrary::AreVTabIesSafe() const /*
It's safe to use the vtables if they have been initialized or if they haven't been initialized but the code is loaded and we aren't at interrupt time.
*/
return fVTableslnitialized ;, (lAtlnterruptLevel() && fCodeLoaded);
inline Version TLibrary::GetVersion() const return fVersion;
inline TCIassID* TLibrary::GetID() const return fLibrarylD;
inline size t TLibrary::GetCodeZoneSize() const return fCodeZoneSize;

inline void TLibrary::SetPreloadFlag() fFlags ; = kLibraryPreloadFlag;
inline int TLibrary::IsDuplicate() const return flsDuplicate;
V
inline void TLibrary::SetIsDuplicate(int flag) flsDuplicate = flag;
inline void TLibrary::IncrementUseCount() f fUseCount.lncrementp;
inline Boolean TLibrary::DecrementUseCount() return fUseCount.Decrement();
inline CompilerType TLibrary::GetCompilerType() const return fCompilerType;
/***************************************************************
* * Class TClass **
* * There is one TClass for every exported class in a library except for * * classes in the root library. When the implementation of the class is * * loaded the fVTabIeRec field will contain information about the loaded ** code (such as vtables and use counts).
***************************************************************/
#define kTCIassID "lSclss,1.1"
class TClass : public TDynamic friend class TCIassCatalog;
public:
TClass(TCIassID* thelD, void* theParentlD, long ttieFlags, TLibrary*, Version version, Version minVersion);
virtual ~TClass(1;
// TDynamic Overrides virtual char* GetVerboseName(char*) const;

~O 95101598 . ' PCT/US94/07424 #if qDebug virtual void Dump() const;
#endif // New Methods long GetFlags() const;

TLibraryFilePriv*GetLibraryFile() const;

long NewObjectSupported() const;

long IsPreload() const;

long IsFunctionSet() const;

long IsRootClass() const;

void SetVTabIeRecPtrFast(VTabIeRec*);
VTabIeRec* GetVTabIeRecPtrFast() const;
OSErr Load(Boolean forceAll, PreloadList* = NULL);
void Unload(1;
TCIassID* GetID() const;
virtual TCIassID* GetParentlD(size_t idx = 0) const;
ClientVTabIeRec* GetParentCVRfsize t idx = 0) const;
virtual ProcPtrGetFunctionPointer(const char* name) const;

virtual ProcPtrGetFunctionPointer(unsigned short index) const;

virtual TClassID*GetCIassID();

virtual void*GetParentCIassIDPointer();

virtual void SetCIassID(TCIassID*);

virtual void SetParentCIassID(TCIassID*);

virtual void SetParentCIassIDList(void*);

virtual void SetVTabIeRecPtr(VTabIeRec*);

virtual VTabIeRec* GetVTabIeRecPtr() const;
private:
void SetCIassLinkPtr(TLink* theLink);
' TLink* GetCIassLinkPtr() const;

long GetCIassSeriaINumber() const;

TLibrary*GetLibrary0 const;

size_t GetCIassSizel) const;

Version GetVersion() const;

Version GetMinVersion() const;

void CacheClasslnformation(ClientVTabIeRec*);

VTabIeRec* GetVTabIeRec(ClientVTabIeRec*);
//
// This first field is known to the stub generation //
TLibrary* fLibrary; // TLibrary in charge of class's code //
long fCIassSeriaINumber; // unique for each class VTabIeRec* fVTabIeRecPtr; // v-table record for this class WO 95/01598 PCT/US94/07424~
//
// Creole "knows" about the fields above //
TCIassID* fCIassID; // classlD for this TClass void' fParentCIassID; // classlD for the parent of this TClass long fFlags;
TLinkt fCIassLinkPtr; // Library link Version fVersion; // Class version Version fMinVersion; // minimum supported version };
/~- _________________________________________________________________ Inline methods _____________________________________________________________ inline long TCIass::NewObjectSupported() const return fFlags & kCIassNewObjectFlag;
inline long TCIass::IsPreload() const return fFlags & kClassPreloadFlag;
inline long TCIass::IsFunctionSet() const return fFlags & kClassIsFunctionSet;
inline long TCIass::IsRootClass() const return fFlags & kCIassIsRoot;
inline long TCIass::GetFlags() const return fFlags;
inline OSErr TCIass::Load(Boolean forceAll, PreloadList* list) return fLibrary 1 fLibrary->Load(forceAll, list) : klnvalidObject;
inline void TCIass::Unload() if (fLibrary) fLibrary-> UnloadU;
inline TCIassID" TCIass::GetID() const ~O 95101598 PCT/US94/07424 ;: y w return fCIassID;
inline void TClass::SetVTabIeRecPtrFast(VTabIeRec* theVTabIeRec) {
fVTabIeRecPtr = theVTabIeRec;
inline VTableRec* TCIass::GetVTabIeRecPtrFast() const {
return fVTabIeRecPtr;
inline void TCIass::SetCIassLinkPtr(TLink* theLink) fCIassLinkPtr = theLink;
inline TLink* TCIass::GetCIassLinkPtr() const {
return fCIassLinkPtr;
inline long TCIass::GetCIassSeriaINumber() const {
return fCIassSeriaINumber;
inline TLibrary* TCIass::GetLibrary() const {
return fLibrary;
inline size t TCIass::GetCIassSize() const { _ return (GetVTabIeRecPtr() _ = NULL) 7 0 : GetVTabIeRecPtr()->GetSize();
inline Version TCIass::GetVersion() const {
return fVersion;
inline Version TCIass::GetMinVersionp const {
return fMinVersion;
inline void TClass::CacheClasslnformation(ClientVTabIeRec* cvr) cvr->fCIassLinkPtr = fCIassLinkPtr;
cvr->fCIassSeriaINumber = fCIassSeriaINumber;
if (fLibrary) WO 95/01598 PCT/US94/07424~
cvr->fCodeSeriaINumber = fLibrary->GetSeriaINumber();
/~- ________________________________________________________________ Some private TLibraryManager Inline methods _________________________________________________________________ inline void TLibraryManager::SetException(TException~' theException) V
fException = theException;
inline TException*' TLibrarylVlanager::GetException() const return fException;
inline TLibrary'' TLibraryManager::FastGetLibrary() const return fLibrary;
infine void TLibraryManager::SetGIobaIWorld(GIobaIWorld world) fGIobaIWorld = world;
#if COMPAT10 inline void TLibraryManager::SetLibraryFile(TLibraryFile' file) fLibraryFile = file;
#endif inline void TLibraryManager::SetCIassCatalog(TCIassCatalog' cat) fCIassCatalog = cat;
inline void TLibraryManager::SetLibrary(TLibrary* lib) fLibrary = lib;
f /f File: SLMGlobal.h #ifndef _SLMGLOBAL_ #define SLMGLOBAL
#ifndef LIBRARYMANAGERUTILITIES

~O 95/01598 . . PCT/US94/0~424 :~ . ' .:
#include < LibraryManagerUtilities.h >
#endif /***************************************************************
* * Forward class declarations **.~...****************************~.*******************************/
#ifdef cplusplus class TLibraryManager;
class TCIassCatalog;
class TLibraryFileP~llanager;
class TTraceLog;
class TTaskScheduler;
class TSeriaIScheduler;
class TArbitrator;
class TCollection;
class TStandardPool;
class TMemoryPool;
class TArbitrator;
class TDebuggerHelper;
struct VTableRecArray;
#else #define TLibraryManager void' #define TCIassCatalog void' #define TLibraryFileManager void' #define TTraceLog void *
#define TTaskScheduler void' #define TSeriaIScheduler void' #define TArbitrator void' #define TCollection void' #define TStandardPool void' #define TMemoryPool void' #define TArbitrator void' #define TDebuggerHelper void' #define VTabIeRecArray void' #endif typedef struct VTabIeRec* VTabIeRecPtr;
typedef ProcPtr (*DispatchFunc)(void*, size t);
***************************************************************
* * LibraryRec is a record used by LibraryManagerEntry and LibraryManagerUnloader * * to keep information about a root library.
***************************************************************~
coast long kMaxRootSegments = 2;
struct LibraryRec WO 95/01598 _ , PCT/US94I07424~
Ptr fWorIdPtr;
Ptr fWorld;
VTabIeRecArray* fVTabIeRecArray;
Ptr fCodePtr;
Ptr* fCodeSeg(kMaxRootSegmentsl; // Handle to all the // segments short fNumCodeSegs;
};
#ifndef cplusplus typedef struct LibraryRec;
LibraryRec #endif /***************************************************************

* * Equates for "fSystemType"

***************************************************************/

#define klsSystem7((unsigned short)Ox01 ) #define klsSystem6((unsigned short)Ox02) #define kVMOn ((unsigned short)Ox04) #define kVMOff ((unsigned short)Ox08) #define kHasFPU ((unsigned short)OxlO) #define kHasNoFPU((unsigned short)Ox20) #define k68000 ((unsigned short)Ox40) #define k68020 ((unsigned short)Ox80) #define k68030 ((unsigned short)Ox100) #define k68040 t(unsigned short)Ox200) /*********************t*****************************************

* * the SLMGlobal *******.*******************************************************/

struct SLMGlobal unsigned long fVersion; // keep this puppy here -SLM version ProcPtr fShutDownProc; // keep this puppy here void'' fCIosePatch; // keep this puppy here TLibraryManager* fCurrentClient; // keep this puppy here TCIassCatalog* fClassCatalog; // keep this puppy here long fNoSystemTask;

void * fH FSPatch;

void * fDeletePatch;

void * fRenamePatch;

TLibraryManager* fLibraryManager;

TTraceLog* fTraceLog;

TStandardPool* fCIassCatalogPool;

TMemoryPool* fCIassLinkPool;

TTaskScheduler* fTaskScheduler;

TArbitrator* fArbitrator;

long fExecLevel;

long fSequenceNumber; // current sequence number long fStartSequenceNumber; // sequence number when we // loaded OM

~U 95/01598 ~, PCT/US94/07424 ProcPtr' fDebugVTable;

LibraryRec' fRootLibrary; // pointer to the root library TLibraryFileManager*' fLibraryFileManager;

TDebuggerHelper~ fDebuggerHelper;

ProcPtr fLoadSegCallback; // debugger callback ProcPtr fUnIoadSegCallback; // debugger callback GIobaIWorld fDebuggerGIobaIWorld;

ProcPtr fLoadVector;

long fParIDExtFolder; // ~96~ Temporary hack for Jasik short fVRefNumExtFolder;

unsigned short fSystemType;

void * fASStack;

size_t fA5Stacklndex;

ProcPtr fStubHelp f51;

void' fCIassIndexTable;

long fSystemModeCount;

void # fTimeVector;

size_t flnitCount;

TSeriaIScheduler~"fUnloadScheduler;

void'" fWaitNextEventPatch;

void'' fGetNextEventPatch;

void'' fEventEvaiIPatch;

DispatchFunc~ fDispatchers;

long fMinStackSpaceForLoadLibrary;

//

// DON'T CHANGE ORDER OF ANYTHING ABOVE HEREII!!
THE

// Better yet, just always add fields to then end of the structure.

// Don't forget to change the record in LibraryManager.a //

unsigned fSystem7:1; // true if running system 7.0 unsigned fUseTicksForTime:1;

unsigned fShutDown:1; // true if shutting down for installer unsigned flnitTime:1; // true until Finder is launched unsigned fBootTime:1; // true while Loading SLM at boot time // #if qUseFileIDs unsigned fUseFSSpecs:1; // true if we track files using fsspec /! records #else unsigned fCauseCompilerError:1; // make sure we get error if // fUseFSpecs is used #endif unsigned fRunningSystemTask:1;
unsigned fRunninglnterruptScheduler:1;
unsigned fAutoUnload:l ; // true if we auto unload slm.
unsigned fFiller2:23;
};
#ifndef cplusplus typedef struct SLMGlobal SLMGlobal;
#endif #ifdef cplusplus extern "C"

WO 95/01598 ~ ~ ~ ~ PCT/US94/07424~
#endif void* PatchTrapishort, ProcPtr, void* prevPatch);
void DisablePatch(short, void*);
Boolean RemovePatch(short, void*);
long NewSeriaINumber();
Boolean SetSLMGlobal(SLMGlobal*1;
Boolean GrowExpandMemRec();
#if MACOS ' #pragma parameter _AO GetSLMGlobal SLMGlobal* GetSLMGlobal() _ 0x2078, Ox02b6, /* move.l ExpandMem,AO */
0x2068, Ox010c /* move.l ExpandMemRec.emELAPGIobals(AO),AO/"
#else SLMGlobal* GetSLMGlobalp;
#endif #ifdef cplusplus };
#endif #ifdef cplusplus inline TCIassCatalog* GetGlobaICIassCatalog() return GetSLMGlobal()->fClassCatalog;
inline TDebuggerHelper* GetDebuggerHelper() return GetSLMGlobal()->fDebuggerHelper; , inline void SetDebuggerHelper(TDebuggerHelper* helper) GetSLMGlobal()->fDebuggerHelper = helper;
#endif #endif /***************************************************************
** PUBLIC GetVTabIeRec ***********************************************.****************/
VTableRec* TClass::GetVTabIeRec(ClientVTabIeRec* theClient) if (fLibrary ! = NULL) .
OSErr err = fLibrary->Load(false); // loads codes if not loaded and increments // use count ~O 95!01598 ; ~ PCT/US94/07424 , 5 if (err ! = kNoError) DebugFail(err, "TCIass::GetVTable could not load code");
if (fVTabIeRecPtr == NULL ; ~ theClient->fCodeSeriaINumber != fLibrary > GetSeriaINumber()) if (fVTabIeRecPtr = fLibrary->LookupVTabIeRecItheClient)) CacheClasslnformation(theClient);
//
// Make sure the local client has the cached information //
if (fVTabIeRecPtr) CacheClasslnformation(fVTabIeRecPtr-> GetLocaICVR());
return fVTabIeRecPtr;

WO 95/01598 ~ PCT/US94/07424 /~**t*e*w****trr*~**rr~*i~~a~:et*r*rest****s=s*~**rr~r***a~rrr~***mc~****r ~* PUBLIC GeCVTnbleRoc ***********t****sfr~**t*rr****rtt****e::****rr*****rre*~i**rra~!~**vrs:**~/
VTaDleRCC* TClasaCatalog::GetVTableRec(regiator CliontVTableRec* LheCl.ienL, Boolean lsSub) const rogistor TLibrary* theLibrarys rogiater TClass~ theCisas a fiULLS ' YTaDleRsc* theVTableRec ~ HULL;
if ((thoCllenL->fClassSerialNUmber > tGlobela->fStartSequencgNUmber) ~G
theClient->fClassLinkPtr ss (theClasa a (TClaas=) theClient->fClassLinkPtr->GetValuol))) ( if (LhcClient->fClaaaSerialNumbcr ~ theClass->GetClasaSerialNumbcr()) t if ((theLibrary - thcClaas->GetLibrarY()) ~° NULL) return rheClasa->CetVTableReePtrFast(11 if (theLibrary->ArevTableaInitializcd() cG
theClipnt->fCodeSOrialNUmber r- theLihrary->GetSerlaiNumber()) ( theVTableRcc L LhoClsaa->GetVTableRacftrFast():
if (theVTabl~Rec->inaromontUsaCOUnt()) theLibrary->IncrementUaoCOUnt()s // ve do this instead of calling Lead() // because ve knox tho code is loadod return thevTabloRec=

if (theLibrary->7~reVTablea5afe() i theclicsnt->ICOdeSerialNumber s~ theLibrnry->GatSerialNumber()) ( thcVTabloKee = theClnas->GOtVTableRecPLrFast()f ) else theClnss = NULL: // wa need this so Code below will work ) if (theVTableRCC == NULL) //
// If the class 5s NU1.1.. look up the class //
ii (theClass =~ HULL) theCljenC-afClassLinkPtr ~ NULL:
theClass - LookupC:lass(theCllenL, LsSub)f //
// NoW, get the VTableRec. Tho Glass will load the eead, ii necessary.
//
if (cheClass ~$ NULL 11 (CheVTableRec - thoClaaa->GetVTableRoc(theClienC)) ~= NULL) DebugFail(kNotYOUnd, "GetVTablsRec failed~);
!/ .
// He incremented the "theLibrary"s use count by calling GetVTablPRec.
// Ii our VTableRac use count is not 0, ve necd to undo the ~lond"
// done above.
//
if (!thoVTableiiec->lncrementUseCOllnt() it (Lhe3.ibrary ~ theClasa->GCt7.ibreTyl) ) ) thoLibrary->Uecromenl:USeCount():
alse if (LheVTnbleRcc->IncremcntUfeCounL() iG (tho).ibrary = theClass->GeaLibrary())) ~O 95!01598 , PCT/US94/07424 theLibrary->ZncremontUseCount():
if (theVTableRec->iExportTable =a NULL) ( theVTableRec->iSotup(theVTnblokec, siteoftVTableRee)):
theVTableRec->fRcgisteredObjccts ~ NULLt return thsVTableRoc) '/*tt***t***tettt**t**ttttttt**t*t*rtt*ttit*ttrtrtttt*tt*t*rrrrtt***it**
*~ PUDLIC ReleasoVTableRec ***ttr**ttttttrt***t*tt***r**t*t*t*t*rt**t****ttttrrt**t**ttrrer**tt*t*/
VTabloRec* TClassCatalog::ReleaseVTableRec(CllentYTableRecr ChoCl~ent> coast ( regiator TCiass* theClasst register TLibrary* theLibraryt //
// This loop is so that the "normal" case has no branehos in it //
do ( if (theCllonL->fClassLinkPtr iC
(theCiass - (TClasst)(theCllent->fClnsaLinkPtr->GetValue())) cs theClicnt->iClB~sSprialNUmber ~= tlloClass->Gel:ClassSerialNumbcr(>) l if (ttheLibrary = theClass->GetT.ibrary()I ec theClicnt->fCodoSerialNumber -i thslibrary->CetSerialNumber()) if (t;hcClaes->GeLVTableRCCPtrFaat. () -- NULL) IyebugFail(kUneonsLructedObject. "TClassCatalog::ke)aaseVTablekec -dest:ructoz called .
/r 7'he iol7oMing is a hack so wP don't hews to call Unioad() unless the usecovnt is 0, since all Unload dope is decrement Lhe use count unless the vsecount goua LO sero. IL's ak ii t,c decreaenL the usecount and then someono else interrvpts us and decrements it.~again. The worse that vilT happon is rre Will Qo through the code that calls unload even though the eod~ that interrupted us may have done this for use airoady.
Unload vil) handlo this.
*/
if (ItheClaas->GetVTablekeePtrFasL()->DecremcntUseCOUnt() tl lLhoLibrary->UecramenLUseCount()) return LhoClass->GotVTableRecPtrFastt)t theLibrnry->IncretnentUSOCOUnt(): //. Unload(1 will decrement it again theLibrary->Unload():
roturn t,hcClass->GetVTablckeePtrFast()t else if (theLibrary == NULTr) a return LheClass->GetVTableRaePl.rFast(>;

theCiass - LoakupclassttheCiient>:
if (theClasu =s NULL) ( UobugFail(kNoti'ound, "TClsssCatalog::koJ~aeAVTabl~Rec failed~):
return NUI.Lt theLibrary K thcClass->GetLibrary(It if (thoLibrary ct tLheLibrary->AroVTablasinitialized()) ( _ DebugFail.(kUnconsLructedObject, ~TClaasCatalog::ReleaseVTableftnc - code not goaded~):

O 95101598 ~ PCT/US94/07424 SetupPatchea t t~ void SetupPatchcs(Doolean (TMaeOSLibraryFiloHanager::')(short), /' CheckCloae ~

t void (TMacOSLibraryFileHanager::~) (CHovePDPCr). /*
CheekHove */

. . void (TMacOSLibraryFileManager::~)(ParmAlkYtr), /~ ChockDelete */

vo5,d (TMacOSLibraryFlleHanageT::')(Parm8lkPtr).
l ChcckRename */

r THacosl.ibraryFiiersanager*) " YROC SetupYatchea Export libFlloHgr, c7oseYetch, cheekHove, eheckDeleto.
checkltennmo lea closoPatch, 7~0 move.l 8(A't),(AO)+ ; save CloaePatch method mova.l 1G(A7),(AO)a = nave ChockHove method move.l 24(A7).(AO)+ t save CheckDolote method move.l 37(A7),(AO)+ t save CheckRennma method move.l 36(1171. (AO)t l libFileMgr i.nataaoe snve its closePatchDC.L 0 checkMove DC.L 0 checkDeleteDC.L O

cheekRenameDC.L o llbFileMgrUC.L 0 EHDPROC
-i CloaoPatch _PROC C7.oscYatch Import libl;'iloHgr, cloaePatch MOVEH.LAO/Dl/D?.,-(t,7) moveq #O. Dl movo.u 24(AO),Dl ; GeL Lhe Refnum of Lho file ble.s enrlyoxiL : The Refnu~ rnuat be negative btst 10, D1 beq.s Check earlyoxit movem.i(1~7)+,AO/D1/D2 ) restore ovr zPgistors rta t LsL patch Qo to real close!

Chock HOV.H D7,-(A~) ) put thd ref nvm on the stack SUBQ.F1#2, A7 s because C uses longs for shorts MOVE.L 7ibFileMQr,-(A7) t put tha libFileHgr pol.nter on stack HoV.L closePatch. AO

JSR (110) : libFileMgr->CheckClose(thePB) ADDQ.H #ti, A7 ; cleanup Lhe stack MOVEM.L(117)+,AO/Ul/D2 : restore our registers TST.H DO t is iL ok to close the filo?

BEQ.S notrCloso t nopo, cull our modified clone Rea7Cloae RTS t Lot patch go to real closol ne~rClose CLR.N 16(110) , iorosult a no~rr CLR.H DO t result - no~rr addq.l i4.n7 : Drop return addross its ENDYRUC
_PROC AFSPatch Import libFi7eHgr,checkMove movem.l AO/DO/D1/D2,-(117) if (DO!~S) do real trap r Cmp.v 15, D0 , if not CatPSove saleetor bnc.s roaltlt'S : go to real thing ; call libFileHgr->CheekMove(thePB) where thePB is in AO
move.l 110,-(A7) ; puL the parameter block on thr stack move.l libFileHgr,-(A7) t and the libFilerigr instance mova.l ~hwakHova,AO 7 libFlloHgz->ChcckMovc(thePB) 3ar (A01 ~x WO 95/01598 ~ PCT/US94/07424~
sw addq.~ #8, A7 zonlHF6 movem.l(A7)+,AO/DO/D1/D2 rta ENDpk(x _PRDC DeletePatch Import libFileHgr,chockDalate movem.l AD/D1/D2,-(A~) movo.l A0.-(A7) ~ put the pazamoter block on Lhe stack move.l llbFiloHgr,-(A7) r end the libF'iletigr inetanca movo.l aheckDolole.AO ; libFlleHgr->ChcckDelete(LhePB) jsr (AO) addq.u #S, A7 movom.l (A7)+,AO/O1/D2 its ENDPROC

_PROC RenamoPateh Impart libFileligr,eheckRename movem.l It0/Dl/D2,-(A7) movo.l Ao,-(7th) : put the parameter block on the stack movo.l libFileMgz.-tA9) ; and the libFlleMgr instanco movo.l checkkenamC.AO : libFileMgt->ChockRenane(thePD) jsz (AO) addq.v #8, A7 movem.l (117)+,AO/Dl/D2 Its ENDPROC

~.~ ~ 6 3 p ~ PCT/US94/07424 ', /etwttt*r*r*r*t**tr*r*r*****tter*rrttrtttt*t*rrrrr*w*trrta~tt*t****ert*r**tt*rt tt ** PROT~CTEU SchedulepatehOperation rr ** Utility routine used by the Close. CatMovo, and DeleCe patches below t*tt*tt*ttttttttttttt**********rta*rtrtttree*ettttttt**tt**rrtrrrr***ttttttttt*
a/
void TMacoSLibraryFileHanagez::SChedulePatchOperation( Stringpcr filename, StringPtr oldfiloname, // only use by CheckRename long dlrID, long oldDirID, // only used by CheckMovo ' short vReilJum, ProcesaProe proceasProc) lrtfterIntorrupt(): // rre need La assume xe are at interrtup lcval sv // the pool won t try to grow.
TStnndnrdPoal* pool ~ GoLLOCaIPvo1()s FilelnfoRec* info - necr (pool) FiloInfoROC(): // create a record for saving into abou~
TOperation* op - nay (pool) TOporation(procesaPrve,inPo)s // create the operation that Will prace~
StringPtr name ~ (SLringPLr)pvvl->Allocate(filename[O)tl): // get memory for the nnmc StringPtr oldnama r NULL:
if (oldfilcnama) oldnnmo - (StringYtr)pool->1111ocnto(oldiilename(O)tlls // qet memory for the name if (info ~- NULL I( op - NULL (I namc ~~~ NULL I( (oldnnma -- HULL ci oldfilennme !- NULL)) ( delete i.afo;
delete ap:
delete cram~;
delete aldnames l.eaveInterrupt () returns // ttt we need Lo schedule some sort of re-sync operation ii this happens ) info->loNamePtr ~ names info->iooldNamepLr = oldnamc;
info->mgr - this;
memcpy(info->loNameptr,~iilenamd, filanamo(0)+1); // copy the aamc if (oldfilonamc) memcpy(info->ioOldNameptr, oldfilename, oldfilename(O)tl)t // copy the old name else info->ioOldDirID = oldDirlD~ // copy the oldDir7D
info->loVRefNum ~ vRefNum: // copy the VRefNum info->loDirID ~ dirID: ' // copy the Di.rlD
op->6etSavedGloDalWorld(GetClobalHVrld())~
GeLGl~balTaskSchedular()->Schedule(op): // schedule the operation Loavolnterrupt();
/**t*ttttttet**ttett*ar***tttt*t*tttttttt*r**t*ttir~rrar***ttttttt*ttttttertrtt t ** PROTECTED IaThisAFileWeCareAboul **
** Utility routine used by tha procesaCheckMove and ProcessCheckClaae, *trttttt*r*tt*t*rratttttrttt**tatrrtrra**t*t*rttt*tttt a ***r*trrrrrrerrrttar*tta/
Boolean TMac06LibraryFileHanayer::lsThiaAFlleGieCareAbouL(FilclnfoRrcr theFile!
1!ParamBlockRec pb2t oSErr crr:
pb2.filePazaa.ioComploSaon ~ NULL:

WO 95!01598 PCT/US94/07424~
pb2.fileParam.ioNameptr - thoFilo->ioNamePtr:
pb2.filoParam.ioVRefNum - therilc->ioVRefNum:
pbZ.fileParam.ioFDirindcx = o;
pb2.filoYarnm.ioDirID = theFile->loDirIDt //
// prevonts rocursi.ve calls Lo close patch caused by PBIiGoLFInfo // call when Stuffit Spacesaver is installed // -gCUrrentFile = LheFilet Orr ~ PBHGetFInio(ipb2,false)f qCUrrentF3.le = NULLf ii (szr I~ kNoErrorl // maybe the file qot moved n9ain or.doloLOd before we could process 1t return false;
if ((pb2.fileParam.ioFlFndrInfo.fdFlagt 6 klsAlias) 1= 0) raturn falso: // ignore alias tiles if ((pb2.fileParnm.loFlfndrlnfo.fdType :- kHaeoSLibrnryType) st (pb2.filePRrare.3oFlFndrlnfo.fdType :- k).3braryManagerfypo !!
pb2.fileParam.3oF7Fndr7nfo.fdCreator !- kLibraryManagerCrentor)) return false; // it's not a file gar care about.
return tzuef /**tt**t*t~t*rtt*t**trrrrrrrrrrrrrrrrrrrrrrrtrrrrrrrrr~rrrr~r~rrrrrrrrrtrrrrrr*
t t~' PROTECTED CheckClose rr Called by our Closo trop. We need to roturn true if it's ok for the t* file Lo be called and false othcrKise. If it is ok to close the file ** and the file is in tha extensions folder. we need to scheduler a ** TTaskScheduler operation to ses ii tho fila thnt qot closed it n *~ library file that He don't know nbout yet (3c.. ono that wet just.
aop5e:d).
t***e:**r*r*rrr*rr*rttrtt*:*rtttrr*t~~*it**tt*ttttt****rttt~trttrt*t*~trt*t~ttt t/
/r &ome info about the F'CH that ve need to know about.
a/
aLruct FC13 r long f ebFlNUmf short f 1112[2):
long 6114(3);
VCD~ feDVPtrf long fi115f short fi116t long fi117[7)f long fcbD3r7Df Str31 fcbCNamef )f eoolcan TMaeoSLibraryFilcManaqer::CheekCloso(ahozt refNum) r THecOSLibraryFilC~ thcLibraryFile:
/r */
Get the FCB pointer tdefino PCBSPTR Ox031e ~dafine FSFCHLon Ox03F6 fdefino MAXREFDiUH *r(shortrrIYCDSYfR - rishort~)FSFCBLen i . y FCB~ fcb ~ (FCB*)(*(Yir")FCBSpTRtref~tum); // fcb for thin refnUm /*
Mako auze Lhe refnum is valid */
if (zAtNUm > HAXREFNDM () (refNum-siaeof(shozt)) ! ~(short~)FSFCBLen !- O) ( DebugHzeak("CheckClosc - this reLaum is iavalld!~):
return trues ' ) /*
/~
!)ail if ue'ze being callod because of Stuffit SpaceSaver calling close during our call to PBIIGetFlnfo dono in ProceaaCheckCloae.
~'/
if (gCurrentFile !- NULL) ( if (gCUrzontFilc->loVRciNUm ~ fcb->fcbYPt;z->vcbVRefNum ~G
gCurrentFile->iouirlD -- fcb->fcbDirID ct memcmp(gCurrent!~'!)e->loNamePtr,fcb->fcbCNnmo,fcb->icbCName(O)+1) ~ o) ( roturn truer see if the file is a library iile xe knor about #if qi7aeFileIDa if (cetSLMGlobal()->fUsefSSpccs) ( #e~ad! f TMacFileSpec iileSpec(icb->febVYtr->VCbVRCfNum, fcb->fcbUirlD, fcb->fcbCNnmc)t thel.ibzaryFile = (TMacoSLibraryFilo*)LookupLibrarytile(file5pec)t fif qUseFileZDs else ( TFilolDfileSpec fllespec(feb->febVPLr->vebVRefttum, fcb->fcbFlNUm);
theLibraryFile = (TMacOSLibraryF!)pt)l~ookupLibraryFile(fileSpec);
#endif if (theLibraryFilo .-.~ NULL) ( // flail if the file ian't in a zeglstered folder if (FindRCgisteredFolder(Lcb->febDizID. fcb->fcbVPtr->vcbVRefNum) _= O) roturn true;
/*
11x17 !f it's one of our library file reLnums and xc don~t want it closed.
Note, xe never want to bat) if we are on Lho delete list becauae this might actually be a new file Lo roFlaco Lhe de)eted one.
*/
if (LheLibraryFiie != NULL) 1/ check tho system eliant first TMacOSLl.brnryFileClient* client - (TMncOSLibraryFilaClient~)thlLibraryFilo->GetSystemCllont()~
if ;client !- NOLL GC (c)lent->f!tefNum -= retNum) tt (!c7lent->LOkTOCloseFile)) ( //DebugBZeak(~'Can~t eloac fJ)e,");

WO 95/01598 PCTlUS94/07424 roturri talsct // don't alloy file to be closed // chock all the other clients TLiat,rierator c)lent7ter(theLibraryFilo->cotCliontsl))s While (client - (THacoSLibraryFilaClionta) cllentlter.Next(1) ( it ((cliont->fRefNum == refNUm) iC ()client->fOkToCloaeFile)) //OebugAreak(HCan'C close tile.")s return fakes // don't allox flle to be closed if (theLibraryFile) I
// We need to let ProcessUelete know if this library file might be // a nex one so ProcossDClete doesn°t see this file and think that // the delete may havo failed.
theLibraryFiie->SetOnCloceid st(true)s ) /*
r/
Schedule an operation to ace if this is a nev file in the extensions Loldor.
SchedulePatchOperation(fcb->icbCName, HULL, icb->fcbDirTD, 0, fcb->IcbVYtr->vcbVReiNum. YrocesaCheckClose)s return trues // ok, close it /riaaaaaaattrrrrrrrra*rrrrrrrrrsraaa*raarrrrrrraara*arta~rrrrrr~*ataaraaaerarrr rr rr PROTECTED PzocessCheckCJnse *a as Setup by ChockClose. The operation is in charge of seeing if the 'a file closed is a new library tile in tho extensions foldcz. We need. to dofcr as thin until SystemTaak time so we can safely make sync HFS calls.
rra*ta~trrrerraa*ataarrrrrrt~aarrrrrrrerawararrtrrsr...aaarr**rrrrrr.arat*aaaae rr/
void TMaeOSLibrazyFlleHanager::ProcesaChockClose(TOpsratlona op) FSleInfoRec* pb ~ (FileInfoRecr)op->GetCreaCOrPtr():
TMacOSLibzaryFileP3anngera mgr - pb->mgrs if ()GetSLMGlobal()->fShutUOUn) ( !f (rFSBusy) ( Debugllreak (~~ProceasCheekClose: aaync 1(fS calls aro st! 71 queu~rd" ) s GetGlobalTaskscheduler()->SChedvle(op)s // roschedule the operation returns OSSrr orz - kNOErzors //
// Mnko sure t,tc care about this file and it's in a registered Loldcr //
l.f (IaThlsAFilvWCCareAb~ut(pb) Gc mgr->FindRcgistercdFoldoz(ph->loDlzIP. pb->loVRefNUm) !- of ( //
// Register this llbrazy files it ve haven't already // -return falser // don't alloy file Lo bw closed ) // check all the other clients TListIterator cl.ientIter(theLibraryFilo->GetClients(11:
xhile (client - (THacOSLibraryFileClientt) clientItor.Noxt()) I
if ((client->fRefNum == rofNUm) Gi (:client->fOkToCloaoFllc)) ( //DebugBroak(°Can'L close file.")i return ialso: /! don't allox tile to bo closed </

if (thel.ibraryFilel ( // We need Lo lot YrocessDelete know if this library file might be // a new one so YzocessDelete doesn~C sco Chis file and think that // the doleto may have failed.
theLibraryFile->SetOaCloseLiat(true);
l /t Schedule an operation Lo sec if this is a new filo 1t1 the extansions folder.
SchedulePatchOpczation(fcb->fcbCName. NULL. fcb->fcbDirID. 0, fcb->icbVPtr->vcbVRefNum, ProcessChockClose);
return true: // ok. close it /~tt~~tta~rtttrrrrttttrtttr~~Ittttrrerrtttttttttt~tt~t~~ttttttttrrtrrrrtrtttttt t~t tt PROTECTED ProceaaChockClose er rr Botup by CheckClose. The opezation is in ehazge of cooing if the tt iilo closod is a new library file in the extensions foldor. fc need t~
defer to this until System:ask times so xe can snfoiy mnko sync HFS calls. , trtrttrtt~t~~ttttttrrr«rtrrttri*~tttttttrttrtt<rt<trtttttttt~aaa«
attttrtrrrrrr/
void THncOSLlbraryFileManagcZ::PxocnssChnekClosa(TOporationt op) ( FilelnfoRect pb .- (FilelnloROCt)op->GetCreatorPlr();
THaeOSLibraryFileManager* mgr ~ pb->mgrt ii (IGOtSLHGloba.l()->iShutUoxn) 1f (rFSBUay) ( DebugBrvak(°YZOCessCheekCloso: asyne HFS calls aro still queued");
GetGloba.LTnskschedvler()->SChodule(op); // roachedulo the operation restore:
) OS~rr o n - kNoPrror:
J/
// Mnke sure we care about this filo and it's in a registered folder //
1f (7sThisAFilcWcCar~l~bout(pb) tt mqr->FindRPgiaLezcdFolder(pb->loDizlU, pb->ioVRofNvm) !- 0) //
// Resistor this library file ii we heven't alrondy //

WO 95/01598 ~ ~ ~ , x TFSIeSpec' LiloS(~OGPtr7 TMacFileSpee filoSpecl(pb->loVRefNum, pb->ioDirID, pb->ic7NamArtr):
rif VUaeFiloIDa TFIlolUt'ileSpec fileSpec2(pb->loVROfHum.O)J
if (GOtSLMGloba)()->fOseFSSpoca) ( fendif filespecPLr - sfileSpeei:
dii qVaaFiloTDs ) olse ( OSt;rr err - :sGetFilaID((consL
F&Spoct)fileSpecl.fVReftium.f3leSpee2.fFile~ID);
if (err t~ kNoError) ( DebugHreak('~2HaeOSLibraryFilaHnnagnr::CheckClosc - GetE°I7eID
i'ailed'~);

also flleSpocPtr ~ tfileSpec2:
) fendif ' ii (err =~ kli0t:rrOr) ( THacOSLibraryFilet tholibraryFile - (TMacOSLibraryFilet)mgr->LookupLibraryFile(rfileSpecPL1 if (theLibraryFila « NOLL) mgr->RegiatorLibraryt'i1e(tf37eSpecPtr);
else LhclibraryFi7e->SetOnCloseLiat(talae)t ) delete opJ
delete pb->ioNnmePtr:
delete pb:

/tttttttttt*r*rrrtterr**tetrr*trttttttttttatttttttttt**tttrr*tt***rrttrrtrt**rr r tt PROTECTED CheckHovo tt tt Calied by our Cat!lovo patch. 7f a file is being moved into or out of ~* the extensions folder, vc need to schedule a TTaakseheduier operation rr to check if the file vas a libzary file, and a then add or remove the librazy r* doponding on xhether the file was draggod into or out of the extensions t~ folder. ' rrrrrrrettttttttttt*ttt*tt***t*e**r*rrrtrttttttttttttitttttttrt*trttt****rtrrrt r/
void THacOSLibraryF37eManager:sCheckMOVO(CHovoPDPtr pb) ( _ .
/t see it the file is a l.ibrazy file ve knuu about t/
TNaeOSLlbraryFilct LhaLibraryFile = NULL:
(fif qt)seFileJDa if (GetSLMGlobal()->IUSCFSSpacs) ( rondif if (pb->ioNamePtr(0) <a 32) ( TMacFiieSpee filcSpec(pb->loVRefNum, pb->ioUirlD, pb->ioNamePtr):
theLibraryFile ~ iTMncC~.:LibraryFiler)LookupLlhreryFile(fileSpec);
/t 8ai1 if ve don't knee about this file and it's not being moved into a rqgiatered folder.
t/

) ) aloe ( if (t:heLibzaryFil~ _= NULL «
FindReylstorcdFOldez(pb->ioNevDirID~ pb->loVRefHUm) --- O) ( return:
~ //
// Ii ve already knov about a file in the locution this one is being moved // Lo, then the existing fife vas probably alroady deleted, but // rrocassCheck~e)ete has not be~n called yot. Ka need to let it know about // the pending move, Saying that bhe filo is on the c)ose list does // the job.

illeSpcc.fYarID - pb->ioNevDirID;
l:)~oLlbraryflla - (THaeOSLibraryFilo*)Lookupl.lbraryFile(fileSpec):
if (CheLibrazyFila) theLibraryFile->SetOnCloseList(true):
else return:
ø!.f qUaeFileIDa ) yandif /*
) &chedule an operation to see if this is a library file being dragged into or out of the extensions folder.
/
SchedulaPntchOpPration(pb->IoNamcPtr. NULL, pb->loNevDirID, pb->ioDirID, pb->ioVRei',NUm, ProcessCheckHove);
/****tttt*tt~.*~~.r*ttttttttrttt***t.*=**=e.~ttttt**itt*tat**~t*ttt*vta~,r~*~i*
*i*~
** PROTECTED rrocesschcckHoV~
**
** 8etup by ChcekMove:. The operation is in charge of seeing if the ** file being moved is a now library fllo in the extanaions folder or an existing *~ library file bolng moved out of the oxtansions folder.
~~t=**t******t*tt*~et*r**r«
=s~ttlr****ttttttt*t*et**e~e~=~~~t*ttt**t*t*~*~tttttt*/
void TMaeOSLibraryk'ileManagar::ProcesacheckMove(TOperatlon* op) FileJnfoRec~ pb a (Fil~infoRect)op->GetCreatorPtr();
THeCOSLibraryFileManagcr~ mgr ~ pb->mgr7 do if (GetSLMt:lobal.()->fShutDoWn) break;
if I*FSBUSy) ( DcbuqBreak("YrocessCheckMove: async HFS calls are aLlll queued");
GetClobal=nakScheduler()->SChedul.e(op); // roschedule the operation return;
) TMacOSLihraryFile~ Lhci.lhraryFile:
Boolcdn movinyOUG. movinqln;
TFileSpec* filaSpecPtr = NULL) THaeFlleSpec flleSpdcl(pb->IoVRefNum. rb->ioUirID, F.b->ioNamePtrl:
iif qtlseFilcIDs TFSlerDFilaSpoc iilcspae2(pb->ioVRofNutn.O)r londif /r Get xome Snfo xe'11 need later ~/
Iif qUseFileIDs if (GetSLHGlobal()->IUsoFSSpOCS) ' ( fandif // make sure the file xas really moved FInfo fndrinfo:
it tHGeLFInfo(pb->ioVRefHuw, pb->~oDIrID, pb->ioNamePtr. tindrlnfo) I~ noErr) ( break: // e5ther CatHove failed or a folder vas moVSd fileSpecPtr = LfilcSpec7:
fileSpecl.fPnrJ)~ - pb->ioOldDirID: /! so LookupLibrnryFilc will xork since xe still // retGember the TLibraryFile by it's old DizID.
theLibraryF5le = (THacoSLibraryFilet)mgr->Lookupl.3braryFi~e(fileSpecl):
/.
Some IN1T~s cause 2 calls to Cat!love to be mado, but only one call actually ends up moving the file. We need to check if the Lirst call xns alrendy made and noH the TLlbraryFile is already known to be in the extcncions folder.
s/
if (theLibrary,File -- HULL) filvSpocl.fParlD - pb->ioDirID;
if (mgr->LookupLibraryFile(fileSpecl)) break;
I
f5f qUaeFiloIDs ~lao ( // make sure the file was really movod filespocl.fYarlD - pb->ioDirID:
oSErr err = ::GetfileIDiteonst FSSpect)file5pecl.fvRofNum,fileSpec2.fFila7A):
if (err 1= kNvErZOr1 // looks like the Cattiova must have fa5)ad ( DebugBreak (~ChcekHove - looka like t;he Catltovc mint have falle:d~~! ;
break:
iandif /r flloSpecPtr - tfileSpec2;
thoLibraryFi)e L trHaeoSLlbraryFile~~ mgr->)~ookupLibraryFiie(iilespoe2)o.
// mako sure this flag gets cloerad here if (LheLibraryFS)e != ROLL) theLibrnryfile->SetonCloseList(falsc)J
/.
Aail ii the file isn'i a library Slle xe already know about and its type isn't 'libr' and it's not the Sharsd Librnry Hanager file.
a/
if (thcLibraryFile == NULL Gt lIsThisAFileWaCarchbout(pb)) break; // it's not a file xe care about 60o if ve are moving into or aut of a registerod folder.

Note: :It~a possible Lhnt vo nzc doing both i/
/! if we have a registered file then just say LhaG:both arc true if (the(.ibraryFile tt thel.ibraryFilo->RegisteredFlle()) moving0ut ~- movingIn = true;
olse ( // if we knw about the file then ve moat be moving out movingaut ~ (thc).ibraryFile to NULIa:
movingIn ~ falsot for (short idx - 0; idx < mgr->fNunReQiatezedFoldera; idx++) ( if (pb->loVRCfHUm -- mgr->fReqisteredFoldnrs[idx).fVRei)ium) ( // are vp moving out of thin foldor?
if (pb->io0ldDirID ~ mgr->fReglateredFoldozs(Sdx].f(~irIU) t movin90ut - true:
iI (movingln) break;
) // are We moving into this folder?
else if (ph->ioDirID ~ mgr->iRegistorcdFoldcrs(idx].fUirlO) ( movinq)n - true;
if (movingOUt) break:
) /f ' lire vc moving out of one regiaLere3 foldor and into nnothef?
a/
if (movingln t~ moving0ut) #if qUaeFileIDs if (GctSLMGiobal()->fUseFSSpeca) ( Iendlf // ivo need of update the dirID for the llbzary file. Since the file // na finger xill hash to the snmc value, ve also need to rdmove // and then re-add it to tho hash~list so it kill be In Lhe right /! hash bucket for it~a TFilr~pec, mgr->GeLLibraIyFilosJ)->Remove(theLibraryFi )1 thnl.ibraryFiie->GOtMacFileSpec()->fParID = ->SoDizlUt // fixup f he dlrID
mgz->GetLibraryFilos()->Add(theld braryFila):
#if qUaeFilalDs ) Iondif !! make t.hc inspector update itaolf UnreglsterUynamicObject(ChoLibraryFile);
GeLGlohalClassCtLalog(D->RegisterDynacaicObject(LhcLlbzaryFile, true);
) break:
/s Azo ve moving out of a registerod folder?
e/

if (movingOut) ( /~ Tt's ok if theLibraryFile == NC:.L. This heppens vhcn CatHove gars patched and for ~/
/- some reason it ends up being called more than once (lt actually gets ~/
/~ moved only one of the times). ~/
if (theLibraryFilc ~- NOLL) /~ If the library file is no longer in the extensions folder and aoae ~/
/~ of its TCiassos are in use than unregistar the TCiasses aad /t Dispose Lha library fi7a. ~/ ' elae if (LhdLibrnryFile->GetapenCount() ~ 0) t delete thcLibraryFiie;
) /t If the library file is no longer in the extensions ioider and ono or more ~/
/~ TClasses are in uss than mark the Class as being moved. ~/
else t fif qUaeFiloIDt if (GetSL23Global()->fUseFSSpeea) // the PdrID has changed so change it to the nev one ( tendif // We need of update the dirID for the library file. Since Lhe file // no longer ~riil hash Lo the same value. ve also need to remove // and then re-add it to the hash list so it will be in the right // hash buekei fez it's TFileSpae.
mgr->GOLLibrBryFiles()->Remove(thaLibraryFilc);
thcLibraryFiie->GettiacFiloSpec()->ffarID - pb->ioDirID; // fixup the dir)1) mgr->GetLibraryFilea()->Add(theLibraryFile)t of qUseFileIDs ) f andif theLibraryFilo->MarkNoved();
// make the Inspector update itself Unregistornynanieobject(theLibraryFilo);
GetGlobalClassCataloq()->RegistorDynnmicObjeet(theLibraryFils, truc)~
) /v ' Arc We moving into a re~istered.lder7 e/
a else if (movingln) ( if (theLibraryfila -~ NULL) // we are a nex library file mgr->RegiatorLibrdryFile(~filospo.ePtr)7 else // We are an old library file just boin~ dragged back in ( o f qUaoFilclhs "
if (GctS).tiGlobal()->fUscFSSpecs) tondif thel.ibraryFilc->GCtHacFilespec()->fYarID - pb->i~DirID: // fixup the dirlU
theLibraryFl)e->UnHarkMOVCd();
I
) ) while (fnlse):
delete opt del.eta pb->loNan.rsPtr:

WO 95/01598 ~ ~ PCT/US94/07424 delato pbt /rtwraatt****raaatttrrrrrwa*ttrrewaaa**w'rrraaaaattttrrrrraaa*ttarerwwaaaa*twwr ra tw PRpT):CTED ChockDeleLo to *t Cnllad by our _Deioto patch. Schodviea an operation thnt cheoka to wr sae if any library files Truro deleted.
aaaxx*trwxtaat***rrwaataxwtxrtraat*tw~r**aaaaxxtwrrr*aaatxwwrr*aaaatr*wrwaxtaaa */
void TMacOSLibray-yFileManaQer::ChackDQioto(ParmBikPtr pb) ( /*
*/
/*
Bail if i:his is a Loldoz and not a file if (pb->fileParam.loHamoPtr -a MOLL) roturnt see i! the fife is n library file va know about t/
THnc03LibraryFilc* theLibraryFilo ~ NU1~L) o f aUSOFiIc7Da if fGOtSLMGiobal()->fUaeFSSpocs) I
tandiL
if (pb->filcParan.loNameFtr(0) <- 32) ( THacFiioSpcc fileSpoc(pb->filoParam.ioVROfNUm, pb->filoParam.ioFlHUm, pb->iilaPnram.ioNamoptr);
theLibrnryFile ~ (THacOSLibrnryFiler)LOOkup).ibraryFile(filespoc)) if IthaLibraryFilo ~- HDLL) return;
) ~l=~
returns of qvseFileIDa elao ( // wo never need to havo mores than one delete oForat)on schoduled if (lfProceaaChcekDea eteschodviedl fPraceasChockDeleLOSCheduiud .. trues eiso roturn; // ignore iL f!)e namo inc)udea-pnth tondif /w t/

scheduia an operntion deal with library fife boing deleted.
ScheduleYatahOporat)en(pb->fl7eParam.loHamoPtr, NULL, pb->flleParam.loFlHum, 0, pb->filaParam.ioVRe=Hum. ProcoasCheckDeloto);
/eaarrr*rrraaaa~r*e*raaatxwrwraaarrertrata**rrwrwaaarrrrrraaaaarwrwaaarawrrraaa ar rt PROTECTED YrocaayCh~ckDel~te r.
ra Cheek to aoo if any library tiles HCre delotod.
r*erwwa***rwraartrrwrawwrrawaaarrraaatrwrrrraattwrrwwaa*rrrwwaawwrrrwraawrrrraa a/
void TMacOSLibraryFileHanager::PrnceaaChcckDeloLO(TOparationr op) d /a Delete the library tile that has gone away */
FilolnfoRoe~ pb - (FileInfoROe~)op->GOtCreatorrtr(11 TMncOSldbraryFileManagcr~' mgr ~ pb-»Ort do ( if (GOtSLMGlobal()~->fShuLDOwn) broak~
if (~FSSUSy) ( DobugRreak(~YroceasChockMovez async HFS calls are still queved~);
CetGlobalTaskSchedulor()->Schodule(op): // reschodulw the operation) return:
lif qDsoF3.leIDs ii (GetSZMGlobal()->ftlscFSSpecs) landif TMacFileSpoc fiiespoc(pb->ioVRCfNum, pb->ioA3rID, pb->3o>zamertr)t // nuke aura its one of ovr iibrary files TMacO.SLibraryFile~ LheLibraryFilo - (TMacOSLibraryFilo~)mgr->LookupLibraryFilo(f3leSpsc)t SL (thel.ibraryF3le == NULL) breakt // looks like it wasn't a library Lilo // c,nko sure the file no longer exists Flnt:o fndrlnfW
if (HCetFlnfe(pb->IoVReiNUm. pb->ioDirlD. pb->ioNamcPtr, cfnOrlnfo) ~- noLrr) ( //
// The file is still around, ve need co figure out i>< it might actually // bo a new file that was crecated before ve wore called.
l/
// IL the file is still open. then us know that Lho delete must have // failed ao we abort. 7f the file is not open and it is on the close !/ list, then even if the deloCO didn't fail. St would bo safe to delete // the TLibraryFiio because it will ba recreated when // YrocesaCheckCloao is called. whether or not the file is nou.
//
if (theLibraryFila->GetOpenCOUnt() > 0 )I
:theLibraryFile->IsOnCloseLltt()) ( OebuqDroak(~Procosscneckoelete - oho delete must have tailed"):
breakt // looks like the delete auat have failed // ok, it'a history delete theLibt:aryFilet lif qOaaFileIDs ) /s Delete all library fi7~s that have gone away , '!
ols~ // we're using filclU's ~, f~
( T)[ashLia~Itorrtor iCOr(mqr->COtLibraryFilos())T
TLibraryFllerriva theLibraryFiler ' mgr->fProoeaaChackDel~toSCheduled ~ falser othiln (theLibrazyFile ~ (TLibraryFilcPriv*)(citor)->Next()) ( FSSpee thoFSSpecT
OSFrr err ~ ::GetFSSpcc(*thuLibzaryFiia->FactGatFileSpec(), theFSSpnc)J
if (err i-~ noErz) ( iter.RsmovoCUrrentob~cct()7 // usua)ly -TLibraryFilePriv takes aaro of this but delete thaLibraryFiie; // re donut Want our itozator to bncoma invalid #ondif ) vhilo (falao)T
delete opt delete pb->SoNamePtrT
delete pbT
) /W
taa****~**aaat*rr**rraa*****rraaa**re.r*aaaaarrr*r.aaaaa**rrrrraaaa***r~***aa rr PROTECTED CheckRenamo as as Called by our _Rename patch. schedules an oparatlon that checks to a* sea if any iibrary files vors renamed.
a**x***raa*****rraaaa***r**taa****r.r.aaaar*rrrrraaaa***rr*araa****r****aaaa*rr r/
void TMaeoSLibraryFiloManaqer::CheckRename(Parm8lkPtz pb) ( /*
*/
son if the file is a library file sre know about TLIbraryFilePriva theLibrarysiie - NULLt #if qUaoFileIDs f! (GetSLMClobal()->fUseFSSpecs) ( Iendif if (pb->filoParan.ioNnmePtr(0) <- 72) TMacFileSpoc flloSpoc(pb->fLleParam.loVRofNum, pb->filcParam.ioFlNum.
pb->filcParan.loNamePtr)T
thoLibraryFilo ~ LookupLibraryFile(fileSpec)t if (theLibraryFi)e == HULL) rcturnt ) else rCturnJ // ignore if file namn includes path #ii qUseFiloIDs else roturnt // no need to do anything when using filaiD~s Iendii SchodulePatchOperation(StringPtr(pb->ioParam.loHisc), pb->fi)eParam.loNamePtr.
pb->iilcraram.ivFlHUm, c pb->LIleF~aram.loVKefHum, YroccasCheckRenamo)t ) /raa***r*aa**r*aaa***rraa**r*.aaa*rr.*r.ar~rr.r..rw ..er~~w aarrerr..Aara*rwrwaarr.
rr PROTECTED Prore~ssChoakAennmc ~~ Check to aoo at nny librery files vero renamed.

WO 95/01598 ~ PCT/US94/0742 <wexaaax**<*xrwaaaa**<x.xxxaaaar<errxxxaaaaa*<waxr.aaaaw<a<*..r.xxwaaaaae*wxxrx x/
Vold TMacDSLibraryFiloManager::ProcossCheckROname(TOperation* op) ( /a Renamo the library file , */
FileInfoR~c* pb ~ (FilelnfoRac*)op->GetCroatorPtr()J
TMscoSLibreryFileManagor* mgz ~ pb->aqrt do ( if (*FSBv=y) ( DabuyBreak(wProceaaChockllelete: nsync HFS coils ere still queued")t GetGlobalTaskScheduioz()->Schedulo(op)t // zaschedulo the aperaLion rotuznJ
) it (GCtSIliGlobal () ->fShuLDOttn) break) // t'irst lookup the iilo ~rith its old name Lo makes Burn it~s a library file TMacElleSpuo iilcSpre(pb->IoVRefNUm, pb->ieDirID, pb->loOldtiaMCPtr)t TLibraryFiloYzlvr thcLibraryFilc - mgr->LOOkupLibraryFila(filespac)J
/x If our lookup failed it'a probably becauso some snit Fatch~d ranamo so it'a called ttrica. It's only renamod once, but if our first operation already fired then tre already renamed our copy so tJO don't need to do anything.
./
if (thaLibratyFile Q~ NULL) breakr // make auro the old file name no longer exists FInto fndrlnio:
!f (HCOtFlnfo(pb->icVnefNUrt, pb->ioDirID. pb->ioOldNamcPtr, cfndrlnfo) ~=
noLrr) brook: // looks likes the file never moVOd ' !/ make aura the notr file nerve does exist - !t's really bad netrs if !t do~sn'tti if (HCutFlnfo(pb->loVReiNUm, pb->ioDirlb, pb->SotinmtPtr, cfndrlnfo) !< notrr) bebuqsroak("ProcossCheekRBnnme - HGOt:finfo failed on nev file name'~)J
if (thaLibraryFilv->Gatopencount() ~= 0) delete (TLibrsryFilePriVr)thcLibraryFileJ // if not deleted it will fail to open next pit break: // looks like ve lost tzack of the =uckcr somahoY
).
J/ Givo the file Sts new name by creating r now file spCC. we need a nev // one because Lho old ono maY not bC b3q enough. Since the file // no longer will hash Lo the servo Value, Wo also need to remavc // and then ru-add it Lo the hash list ao 1t trill bo in the right // hash bucket for it~s TFilospec.
mgr->GetLibraryFiios()->Remova(theLibrnryFile).J
TFiloSpecr fileSpec2 - theLibraryFile->FastCeLFileCpec()J
del~eta fileSpec2t ' fila6pcc2 ~ nCw (pb->IoNamertr[0), GeLLOCeIPoo1()) TMacFiloSpec(pb->loVReINUro, pb->iot)irID, pb->ioNemePtr)J
if (lfiloSpec2) i DebvgRraak("ProcessCheeKROnrme - could not creaLO a neN file spoe")r if (theLibrrrYFile->GetOpenCount() ~- 0) ( deiotQ theLibraryFilet thC:LlbraryFilo->SatFilaSpoc(NULL)t ) br~akJ // if not daloted !t will rail to open asxt time ) thuLibraryFii~->sotFllaspoc(fileSpec2)J
mgr->GetLibraryilsi()->Add(thnLibrnryFile)t !/ mako tho insptcLor update~itsolf unreQistorDynnm(cobjoct(thcT.ibraryFile)t CotGlobalClnssCataiog()->RngiatsrDynemlcObjQOt(thnIJ braryFtlo, true)J
~ while (falaolt dolete opt dolote pb->loNnmePtrt dolotv pb->So0ldNaiooPtrJ
dolote pbt r

Claims (52)

The embodiments of the invention in which an exclusive property or privilege is claimed are defined as follows:
1. A computer, comprising a central processing unit;
non-volatile memory;
high-speed memory;
a library of function sets, each function set including at least one member function, embodied in the high-speed memory;
computer readable program code comprising one or more client applications embodied in the non-volatile memory and capable of utilizing and residing in the high-speed memory; and computer readable program code means, embodied in the non-volatile memory, for managing use of functions by said one or more client applications, the computer readable program code means comprising:
computer readable program code means for causing the computer to store a dispatch record for said one or more client applications, each said dispatch record for said one or more client applications including a function set ID for each of said plurality of function sets used by said client application;
computer readable program dispatch code means responsive to a call by the client application of a particular member function and to the dispatch record for causing the computer to supply a request for a link to a function set having the particular member function; and computer readable program link code means, responsive to the request for the link to the function set and to the function set ID in the dispatch record, for causing the computer to link the particular member function to the client application wherein the link code means includes computer readable program code means for causing said computer to create a resource set catalog, the resource set catalog identifying function sets in the library by respective function set IDs, and storing a plurality of set records which characterize member functions within respective sets;

computer readable program lookup code means for causing the computer to look up a set record for the function set in the resource set catalog based on the corresponding function set ID; and programmable code means, responsive to the set record, for causing the computer to return the particular member function to the client application.
2. The computer of claim 1, wherein the library of function sets includes at least one function set which characterizes a class.
3. The apparatus of claim 2, wherein the at least one function set which characterizes a class includes a constructor function and a destructor function.
4. The apparatus of claim 2, wherein the at least one function set which characterizes a class includes a virtual function.
5. The apparatus of claim 2, wherein the at least one function set which characterizes a class includes at least the following functions: a constructor function, a destructor function, a virtual function and a non-virtual function.
6. The computer of claim 1, wherein the computer readable dispatch code means includes:
a first level dispatch code segment linked to the client application and to a global variable in the high speed memory; and a second level dispatch code segment linked to the global variable and the link code means.
7. The computer of claim 1, wherein the code means directing the computer to create a dispatch record includes code means causing the computer to create a function link cache with said dispatch record to store the function link to the particular member function;

the link code means further includes code means for causing the computer to supply the function link to the function link cache in response to the return of the particular member function to the client application; and the dispatch code means further includes code means for causing the computer to query the function link cache for a cached link to the particular member function, and to jump to the particular member function in response to the cached link.
8. The computer of claim 1, wherein the dispatch record includes code means directing a set link cache to store a set link to the function set including the particular member function;
the link code means includes code means for causing the computer to supply the set link to the set link cache in response to the return of the particular member function to the client application; and the dispatch code means includes a code means for causing the computer to query the set link cache for a cached link to the function set, and return the cached link to the link code means upon a call to a member function in the function set of the particular member function.
9. The computer of claim 8, wherein the function sets are assigned version numbers according to a standard protocol, and the dispatch record further includes version information linked with one of the client applications indicating a minimum version number supported by said one of the client applications for the function set of the particular member function;
the library includes a version number for the corresponding function sets; and the link code means further includes code means, responsive to the version information in the dispatch record and the version number in the library, for ensuring that the client application supports a version of the function set of the particular member function.
10. The computer of claim 8, further including computer readable code means for causing the computer to load the function sets into high speed memory, to assign the function sets in the library serial numbers when the function sets are loaded in high speed memory, and to assign a serial number in the dispatch record, indicating the serial number corresponding to each function set when the set link cache is filled with set links, the set link cache stores a pointer to a link structure in high speed memory, and the link structure includes a pointer for linking to the function set, and the link code means further includes code means, responsive to the serial number in the library of the function set and the serial number in the dispatch record, for ensuring validity of the set link cache entry, and code means for clearing the link structure when the corresponding function set is unloaded from internal memory.
11. The computer of claim 8, wherein the library of function sets further includes use count records for function sets in the library and the link code means further includes code means for causing the computer to increment the use count record when the function set is returned to the client application, and to decrement the use count when the client application frees the function set.
12. The computer of claim 2, wherein the at least one function set which characterizes a class includes a constructor function and a destructor function and the library further includes use count records for function sets in the library;
the link code means further includes code means for directing the computer to increment the use count record for a particular function set when a client application calls a constructor function for a class characterized by the function set, and to decrement the use count record when a client application calls a destructor function for the class;
and further including programmable code means, responsive to the use count records in the library, for causing the computer to free corresponding function sets from internal memory when the use count record goes to zero.
13. The computer of claim 1, including programmable code means embodied in the non-volatile memory for causing the computer to create a plurality of link structures in high-speed memory, and wherein a subset of the function sets are stored in non-volatile memory and may be loaded into high-speed memory by the link code means, the link code means causing the computer to assign serial numbers to the function sets when loaded in high-speed memory;
the dispatch record further includes a set link cache to store a pointer to one of the plurality of link structures and to store a serial number indicating a serial number of the corresponding function set when the set link cache is filled;
the link structure includes a pointer for linking to the function set;
the link code means further includes code means for causing the computer to supply the link to the function set, to return a particular member function to the client application, and to supply the serial number to the set link cache in response to the return of the particular member function to the client application; and the dispatch code means further includes programmable code means for causing the computer to query the set link cache for a cached link, and if the serial number in the set link cache matches the serial number in the library, to return the cached link to the link code means upon a call to a member function in the function set of the particular member function.
14. The computer of claim 1, wherein the link code means includes:
means for causing the computer to create a catalog in the internal memory which lists function sets available for linking; and programmable registration code means, in the high-speed memory, for causing the computer to insert function sets in the library in the catalog in response to a request by an operating system to make the library available for linking, and to remove the function sets in the library from the catalog in response to a request by the operating system to make the library unavailable for linking.
15. The computer of claim 1, wherein the link code means includes:
means for causing the computer to create a catalog in the internal memory which lists function sets available for linking; and programmmable registration code means, executable during runtime of the client application and in the high-speed memory, for causing the computer to insert function sets in the library in the catalog in response to a request by an operating system to make the library available for linking, and removes the function sets in the library from the catalog in response to a request by the operating system to make the library unavailable for linking.
16. A computer, comprising:
an input;
a central processing unit;
non-volatile memory;
internal memory;
at least one client application embodied in internal memory; and programmable code means for managing code resources for use by client applications in the computer, the programmable code means, comprising:
a resource set catalog stored in the internal memory, the resource set catalog identifying a plurality of function sets of member functions by respective function set IDs, and storing a plurality of set records which characterize member functions within respective sets;
dispatch code means, in the internal memory linked with a client application, for causing the computer to supply a particular function set ID in response to a call by a client application of a particular member function which is a member of a function set identified by the particular function set ID in the resource set catalog;
lookup code means, in the internal memory, for causing the computer to identify, based upon the resource set catalog and responsive to the dispatch code means, one of said plurality of set records for the corresponding function set in the resource set catalog; and link code means, in the internal memory and responsive to the dispatch code means, for causing the computer to return the particular member function to the client application in response to the set record.
17. The computer of claim 16, wherein the dispatch code means comprises:
a dispatch record, linked with the client application, which stores the particular function set ID; and dispatch linked to the dispatch record and the lookup code means, responsive to the call to supply the particular function set ID to the lookup code means.
18. The computer of claim 17, wherein the dispatch record includes a set link cache to store a link to the set record for the set of functions including the particular member function;
the link code means further includes code means for causing the computer to supply the link to the set link cache in response to the return of the particular member function to the client; and the dispatch code means further includes code means for causing the computer to query the set link cache for a stored link to the set record, and to return the set record to the link code means in response to the cached link upon a call to a member function in the function set of the particular member function.
19. The computer of claim 18, wherein the set records for function sets are assigned serial numbers when the function sets are loaded in internal memory, and the dispatch record further includes a serial number, linked with the client, indicating a serial number of the corresponding function set when the set link cache is filled;
wherein the set link cache stores a pointer to a link structure in internal memory, and the link structure includes a pointer to the set record having the particular function set ID of the set record, and wherein the link code means further includes code means, responsive to the serial number in the set record and the serial number in the dispatch record, for causing the computer to insure validity of the set link cache entry, and to clear the link structure when the corresponding function set is unloaded.
20. The computer of claim 16, wherein the set record further includes a use count record and the link code means further includes code means for causing the computer to increment the use count when a client application binds with the function set corresponding to the set record, and to decrement the use count when a client application frees the function set corresponding to the set record.
21. The computer of claim 16, wherein the at least one function set which characterizes a class includes a constructor function and a destructor function, and the set record further includes a use count field;
wherein the link code means further includes code means for causing the computer to increment the use count when a client application calls a constructor function for a class corresponding to the set record, and to decrement the use count when a client application calls a destructor function for a class corresponding to the set record; and further including code means, responsive to the use counts in the set records, for causing the computer to free corresponding function sets from internal memory when the use count goes to zero.
22. The computer of claim 20, including a plurality of link structures in internal memory, and wherein the function sets are loaded into internal memory and are assigned serial numbers when loaded in internal memory;
the dispatch record includes a set link cache to store a pointer to one of the plurality of link structures and to store a serial number indicating a serial number of a corresponding function set when the set link cache is filled;
the link structure includes a pointer to the set record; and the link code means further includes code means for causing the computer to supply the link and the serial number to the set link cache in response to the return of the particular function to the client;
the dispatch code means further includes code means for causing the computer to query the set link cache for a stored link to the set record, and, if the serial number in the set link cache matches the serial number in the set record, to return the set record to the link code means in response to the cached link upon a call to a member function in the function set of the particular member function.
23. The computer of claim 16, further including:
registration code means in the internal memory for causing the computer to insert a library of function sets in the resource set catalog in response to a request to make the library available for linking, and to remove the function sets in the library from the resource catalog in response to a request to make the library unavailable for linking.
24. The computer of claim 16, further including:
registration code means, executable during runtime of the client application and in the internal memory, for causing the computer to insert a library of function sets in the resource set catalog in response to a request to make the library available for linking, and to remove the function sets in the library from the resource set catalog in response to a request to make the library unavailable for linking.
25. An article of manufacture, comprising:
a computer usable medium having computer readable program code means embodied therein for managing code resources used by client applications in a computer, said program code means comprising:
code resources comprising a library of function sets stored on the computer usable medium, the function sets in the library having function set IDs, and the function sets including member functions;
program code means for causing the computer to create a resource set catalog, the resource set catalog identifying function sets in the library by respective function set IDs, and to store a plurality of set records which characterize member functions within respective sets;
dispatch code means, linked with a client application, for causing the computer to supply a particular function set ID in response to a call by the client application of a particular member function which is a member of a corresponding function set identified by the particular function set ID;
program lookup code means, responsive to the particular function set ID, for causing the computer to query the resource set catalog to look up a set record for the corresponding function set in the resource set catalog; and program link code means, for causing the computer to return the particular member function from the library to the client application in response to the set record, and to write valid links in the function link cache and the set link cache, wherein the dispatch code means includes:
a dispatch record linked with the client application which stores the particular function set ID, a function link cache, linked with the client application, to store a link to the particular member function, a set link cache, linked with the client application to store a link to the set record for the set of functions including the particular member function, a dispatch code means linked to the dispatch record, the function link cache, the set link cache and the lookup code means, responsive to the call to supply the particular member function if the function link cache is valid, for causing the computer to supply the set record if the set link cache is valid and to supply the particular function set ID if neither the function link cache nor set link cache is valid.
26. The article of manufacture of claim 25, wherein the library comprises at least one function set which characterizes a class.
27. The article of manufacture of claim 26, wherein the at least one function set which characterizes a class includes a constructor function and a destructor function.
28. The article of manufacture of claim 26, wherein the at least one function set which characterizes a class includes a virtual function in the class.
29. The article of manufacture of claim 26, wherein the at least one function set which characterizes a class includes a constructor function, a destructor function, a virtual function and a non-virtual function.
30. The article of manufacture of claim 25, wherein the function sets in the library are assigned version numbers according to a standard protocol, and dispatch record further includes version information linked with the client indicating a minimum version number supported by the client for the function set of which the particular function is a member, the set record includes a version number for the corresponding function set, and the link code means includes means, responsive to the version information in the dispatch record and the version number in the set record, for causing the computer to insure that the client supports a version of the particular function in the function set.
31. The article of manufacture of claim 25, wherein the set records for function sets are assigned serial numbers when the function sets are loaded in internal memory, and the dispatch record further includes a serial number linked with the client indicating a serial number of the corresponding function set when the set link cache is filled, the set link cache stores a pointer to a link structure in internal memory, and the link structure includes a pointer to the set record having the particular function set ID of the set record, and the link code means further includes means, responsive to the serial number in the set record and the serial number in the dispatch record, for causing the computer to insure validity of the set link cache entry, and means for clearing the link structure when the corresponding function set is unloaded.
32. The article of manufacture of claim 25, wherein the set record includes a use count record and the link means includes means for causing the computer to increment the use count when a client application binds with the function set corresponding to the set record, and to decrement the use count when a client application frees the function set corresponding to the set record.
33. The article of manufacture of claim 26, wherein the at least one function set which characterizes a class includes a constructor function and a destructor function and the set record further includes a use count field;

the link means includes means for causing the computer to increment the use count when a client application calls a constructor function for a class corresponding to the set record, and to decrement the use count when a client application calls a destructor function for a class corresponding to the set record; and further including means, responsive to the use counts in the set records, to free corresponding function sets from internal memory when the use count goes to zero.
34. The article of manufacture of claim 25, including a plurality of link structures in internal memory, and wherein the function sets are assigned serial numbers when loaded in internal memory;
the set link cache stores a pointer to one of the plurality of link structures and a serial number indicating a serial number of the corresponding function set when the set link cache is filled;
the link structure includes a pointer to the set record; and the link means includes means causing the computer to supply the link and the serial number to the set link cache in response to the return of the particular member function to the client;
the dispatch means includes means to insure the validity of a cached link to the set record in response to the serial number in the set link cache and the serial number in the set record.
35. The article of manufacture of claim 25, further including:
a registration routine in the memory which inserts a library of function sets in the resource set catalog in response to a request to make the library available for linking, and removes the function sets in the library from the resource catalog in response to a request to make the library unavailable for linking.
36. The article of manufacture of claim 25, further including:
a registration routine executable during runtime of the client application and in the memory, which inserts a library of function sets in the resource set catalog in response to a request to make the library available for linking, and removes the function sets in the library from the resource set catalog in response to a request to make the library unavailable for linking.
37. In a computer, a computer readable memory having code means for managing functions for use by client applications in the computer, the computer having internal memory storing at least one client application and non-volatile memory, the code means comprising:
a resource catalog stored in the internal memory, the resource catalog including records identifying a plurality of functions available for dynamic linking with the client application;
dispatch code, in the internal memory linked with a client application, causing the computer to supply a request to link with a particular function in response to a call by the client application of the particular function;
lookup code in the internal memory, coupled with the resource catalog and the dispatch engine, causing the computer to look up a record for the particular function in the resource catalog in response to the request;
link code, in the internal memory and coupled with the dispatch code, causing the computer to return the particular function to the client application in response to the record; and registration code in the internal memory executable during runtime of the client application, which inserts records for a library of functions in the resource catalog in response to a request to make the library available for linking, and removes the records for the library from the resource catalog in response to a request to make the library unavailable for linking.
38. A computer, including at least one central processing unit, non-volatile memory, high-speed memory, code means for managing code resources for use by client applications, the volatile memory storing at least one client application, the code means comprising:
a class catalog stored in the internal memory, the class catalog identifying a plurality of classes by respective class IDs, and storing class records which characterize derived classes, each derived class having at least one corresponding class in the plurality of classes from which the derived class is derived;
dispatch code in the internal memory linked with a client application, to supply a particular class ID in response to a call by the client application of a function of a particular class identified by the particular class ID;
lookup code in the internal memory, coupled with the class catalog and the dispatch code, responsive to the particular class ID, causing the computer to look up a class record for the corresponding class in the class catalog;
link code in the internal memory and coupled with the dispatch code, causing the computer to return the function of the particular class to the client application in response to the class record; and library management code, coupled with the class catalog, causing the computer to provide information about a class in the class catalog to the client application in response to the class ID.
39. The computer of claim 38, wherein the class records identify classes from which the corresponding class is derived, and the library manager includes a verify class routine to verify that a particular class is derived from another class.
40. The computer of claim 38, wherein the class records identify parent classes of the corresponding class, and the library manager includes a cast object routine to return offsets within an object of a particular class to elements within the object of a parent class of the particular class.
41. The computer of claim 38, wherein the library manager includes a new object routine to provide parameters to the client application for calling a function of a class in response to the class ID.
42. The computer of claim 38, wherein the library manager includes a get class information routine to provide information to the client application about classes derived from a particular class in response to the class ID of the particular class.
43. A process for managing code resources used by a client application in a computer and dynamically installing client applications, the computer having internal memory storing at least one said client application, comprising:
providing a class identifier and link pointer in the client application;
providing a class catalog in the internal memory, the class catalog identifying a plurality of classes by respective class identifiers;
providing class records which contain information regarding each class and table records which characterize corresponding classes; and updating the class catalog by generating a new object for inclusion in the class catalog, wherein said generating comprises means for:
querying the class identifier;
querying a memory pool;
determining, based on the class identified and memory allocation data, whether the memory pool allocation has been allocated to an object;
if the memory location has not been allocated, allocating the memory pool location to the new object;
determining the class record by querying one of the plurality of classes to determine whether the new object is supported by the class;
if the class is associated with a library other than a root library, then loading the library and incrementing a use counter in the table record;
retrieving the table record using the class record;
determining whether the new object is supported by the class based on the table record;

determining the size of the new object based on the object record;
placing the object in the allocated memory pool; and incrementing the use counter.
44. A process executable in a computer, the computer including client applications in the computer, comprising the steps of:
providing a class identifier and link pointer in the client application;
providing a class catalog, the catalog stored in the internal memory, the class catalog identifying a plurality of classes by respective class identifiers, and storing class records which characterize corresponding classes, including at least one parent class having at least one class, each class comprising at least one object;
providing at least one operating system designated folder holding a register library;
determining whether new files are copied to or removed from the folder by the client application; and updating the class catalog to include new library resources copied into the folder and deleting library resources which have been moved from the folder subsequent to use.
45. The process of claim 44 wherein the step of providing further includes the step of providing at least one client application designated folder.
46. The process of claim 45 wherein the step of determining further includes intercepting operating system calls indicating whether a file has been copied or moved, and means for determining whether the file is located in the operating system designated folder or the client application designated folder.
47. The process of claim 45 further including the step of determining whether the new file is a shared library resource prior to the step of updating the class catalog.
48. A computer readable memory for managing code resources for use by client applications in a computer, the computer having internal memory storing at least one client application, comprising:
a class catalog stored in the internal memory, the class catalog identifying a plurality of classes by respective class identifiers, and storing class records which characterize corresponding classes;
link code means, in the internal memory, for causing the computer to return the particular function to the client application in response to the class record;
library management code means, coupled with the class catalog, causing the computer to provide information about a class in the class catalog to the client application in response to a request to make the library unavailable for linking; and a registration code means causing the computer to insert a library of function sets in the class catalog in response to a request to make the library available for linking, and to remove the function sets in the library from the class catalog in response to a request to make the library unavailable for linking.
49. The system of claim 48 further including:
cast object code means coupled to the client applications, allowing the client to cast an object as a parent class, the cast object routine comprising:
code means for determining the location of the object and an identifier of the parent class;
code means for determining the class of the object based on a required structure for the object;
code means for verifying the class of the object using the class identification of the object and the parent class identifier;
code means for determining whether a single or multiple inheritance of the class is found; and code means for determining offsets necessary for multiply inherent objects based on a hierarchy of parent classes.
50. The system of claim 48, wherein the catalogs are assigned version numbers according to a standard protocol, and including version information linked with the client application indicating a minimum version number supported by the client application for the function set of the particular member function, the library includes a version number for the corresponding function sets, and the link code further includes code, responsive to the version information in the dispatch record and the version number in the library, for causing the computer to insure that the client application supports a version of the function set of the particular member function.
51. A computer including internal memory storing at least one client application and non-volatile memory storing programmable code, the code comprising:
a class identifier and link pointer in the client application, upon compiling the client application;
a class catalog, the catalog stored in the internal memory, the class catalog identifying a plurality of classes by respective class identifiers, and storing class records which characterize corresponding classes, including at least one parent class including at least one class, each class comprising at least one object;
at least one operating system designated folder holding a register library;
means for determining whether new files are copied to or removed from the folder by the client application; and update code means for including new library resources copied into the folder in the class catalog and deleting library resources which have been moved from the folder subsequent to use from the class catalog.
52. A computer including a central processing unit, volatile internal memory and non-volatile memory means for managing code resources for use by client applications in the computer, the computer having internal memory storing at least one client application, said means for managing code comprising:
means for providing a class identifier and link pointer in the client application;

means for providing a class catalog stored in the internal memory, the class catalog identifying a plurality of classes by respective class identifiers, and storing class records which characterize corresponding classes, including at least one parent class having at least one class, each class comprising at least one object;
means for providing at least one operating system designated folder and at least one client application designated folder, each holding at least one register library;
means for determining whether new files are copied to or removed from the folder by the client application;
means for determining whether the new file is a shared library resource; and means for updating the class catalog to include new library resources copied into the folder and deleting library resources which have been moved from the folder subsequent to use.
CA002166302A 1993-06-30 1994-06-30 System for object oriented dynamic linking based upon a catalog of registered function set or class identifiers Expired - Lifetime CA2166302C (en)

Applications Claiming Priority (3)

Application Number Priority Date Filing Date Title
US08/085,187 US5615400A (en) 1993-06-30 1993-06-30 System for object oriented dynamic linking based upon a catalog of registered function set or class identifiers
US08/085,187 1993-06-30
PCT/US1994/007424 WO1995001598A1 (en) 1993-06-30 1994-06-30 System for object oriented dynamic linking based upon a catalog of registered function set or class identifiers

Publications (2)

Publication Number Publication Date
CA2166302A1 CA2166302A1 (en) 1995-01-12
CA2166302C true CA2166302C (en) 2004-12-07

Family

ID=22190014

Family Applications (1)

Application Number Title Priority Date Filing Date
CA002166302A Expired - Lifetime CA2166302C (en) 1993-06-30 1994-06-30 System for object oriented dynamic linking based upon a catalog of registered function set or class identifiers

Country Status (6)

Country Link
US (1) US5615400A (en)
EP (1) EP0706684B1 (en)
AU (1) AU7253894A (en)
CA (1) CA2166302C (en)
DE (1) DE69414387T2 (en)
WO (1) WO1995001598A1 (en)

Cited By (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US11675593B2 (en) 2021-08-31 2023-06-13 International Business Machines Corporation Dynamically updating a dynamic library

Families Citing this family (104)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5379432A (en) * 1993-07-19 1995-01-03 Taligent, Inc. Object-oriented interface for a procedural operating system
FR2717280B1 (en) * 1994-03-10 1996-04-05 Bull Sa Method for managing the multiple inheritance of persistent and shared objects.
US5831606A (en) 1994-12-13 1998-11-03 Microsoft Corporation Shell extensions for an operating system
US5956715A (en) * 1994-12-13 1999-09-21 Microsoft Corporation Method and system for controlling user access to a resource in a networked computing environment
CA2143488C (en) * 1995-02-27 2000-01-11 Robert Paul Duncan Dynamic link libraries without linker or loader support
US6519767B1 (en) * 1995-06-07 2003-02-11 Microsoft Corporation Compiler and method for automatically building version compatible object applications
US5764991A (en) * 1995-06-30 1998-06-09 Canon Kabushiki Kaisha Processing object oriented code and virtual function code
JPH09231156A (en) * 1996-02-28 1997-09-05 Nec Corp Remote execution device with program receiving function
US5805796A (en) * 1996-03-27 1998-09-08 Dell Usa, Lp System architecture for implementing modular diagnostics
US6704802B1 (en) * 1996-03-27 2004-03-09 Dell Usa, Lp Method and system for communicating between independent software modules
US6052778A (en) * 1997-01-13 2000-04-18 International Business Machines Corporation Embedded system having dynamically linked dynamic loader and method for linking dynamic loader shared libraries and application programs
US5930795A (en) * 1997-01-21 1999-07-27 International Business Machines Corporation Supporting dynamic tables in SQL query compilers
US6363436B1 (en) 1997-01-27 2002-03-26 International Business Machines Corporation Method and system for loading libraries into embedded systems
US6055562A (en) * 1997-05-01 2000-04-25 International Business Machines Corporation Dynamic mobile agents
US6442753B1 (en) * 1997-08-28 2002-08-27 International Business Machines Corporation Apparatus and method for checking dependencies among classes in an object-oriented program
US6078889A (en) * 1997-09-30 2000-06-20 Pitney Bowes Inc. Method and system of implementing a carrier manager librarian
US6910047B1 (en) 1997-10-01 2005-06-21 Pitney Bowes Inc. Method and system for changing rating data via internet or modem in a carrier management system
US6873978B1 (en) 1997-10-01 2005-03-29 Pitney Bowes Inc. Event interface for a carrier manager system
US6292843B1 (en) 1998-01-16 2001-09-18 International Business Machines Corporation Quick loading of run time dynamic link library for OS/2
JP3284956B2 (en) * 1998-01-26 2002-05-27 日本電気株式会社 Program conversion method, program conversion device, and storage medium storing program conversion program
DE19810675A1 (en) * 1998-03-12 1999-10-14 Giesecke & Devrient Gmbh Disk
US6061520A (en) * 1998-04-07 2000-05-09 Sun Microsystems, Inc. Method and system for performing static initialization
US6182277B1 (en) * 1998-04-15 2001-01-30 Oracle Corporation Methods and apparatus for declarative programming techniques in an object oriented environment
US6079015A (en) * 1998-04-20 2000-06-20 Motorola, Inc. Data processing system having selectable exception table relocation and method therefor
AUPP365798A0 (en) * 1998-05-22 1998-06-18 Ladd, James Christian Architecture for the execution of program code
US6314566B1 (en) * 1998-09-29 2001-11-06 Apple Computer, Inc. Method and apparatus for “Just-in-Time” dynamic loading and unloading of computer software libraries
JP3837244B2 (en) 1998-10-23 2006-10-25 松下電器産業株式会社 Program linking apparatus and method
US6343294B1 (en) * 1998-12-15 2002-01-29 International Business Machines Corporation Data file editor for multiple data subsets
US6286010B1 (en) * 1999-02-19 2001-09-04 Novell, Inc. Methods and apparatuses for interaction between schemata
US6393491B1 (en) 1999-04-26 2002-05-21 Sun Microsystems, Inc. Method and apparatus for dispatch table construction
US7171673B1 (en) * 1999-08-06 2007-01-30 Honeywell International Inc. System and method for validating interfaces of dynamically linkable components and real-time process control system incorporating the same
US6457170B1 (en) * 1999-08-13 2002-09-24 Intrinsity, Inc. Software system build method and apparatus that supports multiple users in a software development environment
GB9921720D0 (en) * 1999-09-14 1999-11-17 Tao Group Ltd Loading object-oriented computer programs
US7080370B1 (en) * 1999-11-05 2006-07-18 Sun Microsystems, Inc. Method and apparatus for compiling source programs using one or more libraries
US6385722B1 (en) 2000-01-27 2002-05-07 Sun Microsystems, Inc. Method, system, and article of manufacture for limiting access to program files in a shared library file
US7343421B1 (en) * 2000-02-14 2008-03-11 Digital Asset Enterprises Llc Restricting communication of selected processes to a set of specific network addresses
US7089242B1 (en) * 2000-02-29 2006-08-08 International Business Machines Corporation Method, system, program, and data structure for controlling access to sensitive functions
US6658657B1 (en) * 2000-03-31 2003-12-02 Intel Corporation Method and apparatus for reducing the overhead of virtual method invocations
US6907421B1 (en) 2000-05-16 2005-06-14 Ensim Corporation Regulating file access rates according to file type
US7143024B1 (en) * 2000-07-07 2006-11-28 Ensim Corporation Associating identifiers with virtual processes
US6505123B1 (en) 2000-07-24 2003-01-07 Weatherbank, Inc. Interactive weather advisory system
US6877162B1 (en) * 2000-07-31 2005-04-05 Hewlett-Packard Company Method and system for extendable class-based shared data-types
US6625703B2 (en) 2000-11-02 2003-09-23 International Business Machines Corporation Verifying primary and backup copies of vital information for a processing system employing a pseudo-fixed reference identifier
US7219354B1 (en) 2000-12-22 2007-05-15 Ensim Corporation Virtualizing super-user privileges for multiple virtual processes
JP2002373077A (en) * 2001-06-14 2002-12-26 Nec Corp Method and device for retrieving execution time library, dynamic linker and program
US6986148B2 (en) * 2001-07-17 2006-01-10 Appforge, Inc. Methods and systems for providing platform-independent shared software components for mobile devices
US6934943B2 (en) * 2001-10-18 2005-08-23 Hewlett-Packard Development Company Optimization of control transfers to dynamically loaded modules
US7007273B2 (en) * 2001-10-29 2006-02-28 Lenovo (Singapore) Pte Ltd. Object oriented model of preloading software
US6981268B2 (en) * 2001-12-05 2005-12-27 Microsoft Corporation System and method for persisting and resolving application assembly binds
US20030182361A1 (en) * 2002-03-22 2003-09-25 Sun Microsystems, Inc. Business-model agnostic service deployment management service
US7644411B1 (en) * 2002-06-06 2010-01-05 Unisys Corporation Mechanism for implementing different types of services within the same two-phase commit transaction
CN100407728C (en) * 2002-08-02 2008-07-30 中兴通讯股份有限公司 Board to board communication between distribution system objects
US7451458B2 (en) * 2002-08-02 2008-11-11 Tuchow Jonathan A Software methods of an optical networking apparatus with multiple multi-protocol optical networking modules having packet filtering resources
US7844734B2 (en) * 2002-11-18 2010-11-30 Innopath Software, Inc. Dynamic addressing (DA) using a centralized DA manager
US20050091259A1 (en) * 2003-10-24 2005-04-28 Microsoft Corporation Redmond Wa. Framework to build, deploy, service, and manage customizable and configurable re-usable applications
US7155726B2 (en) * 2003-10-29 2006-12-26 Qualcomm Inc. System for dynamic registration of privileged mode hooks in a device
CN1898615B (en) * 2004-06-28 2012-11-14 西门子工业公司 Method and apparatus for representing a building system enabling facility viewing for maintenance purposes
US7865701B1 (en) * 2004-09-14 2011-01-04 Azul Systems, Inc. Concurrent atomic execution
US8037482B1 (en) * 2004-09-14 2011-10-11 Azul Systems, Inc. Accelerated class check
US20060161469A1 (en) 2005-01-14 2006-07-20 Weatherbank, Inc. Interactive advisory system
US8832121B2 (en) * 2005-02-02 2014-09-09 Accuweather, Inc. Location-based data communications system and method
US7644416B2 (en) * 2005-02-10 2010-01-05 Google Inc. Access to a target object with desired functionality
US7743379B2 (en) * 2005-07-14 2010-06-22 International Business Machines Corporation Variable resource sets
US20070169026A1 (en) * 2005-11-28 2007-07-19 Davis Alan H Software program with alternative function libraries
US8229467B2 (en) 2006-01-19 2012-07-24 Locator IP, L.P. Interactive advisory system
US8291395B2 (en) * 2006-03-31 2012-10-16 Apple Inc. Fast function call dispatching
US8549544B1 (en) * 2006-04-07 2013-10-01 Intel Corporation System, method and computer program product for preventing the execution of unwanted code
GB0609843D0 (en) * 2006-05-18 2006-06-28 Ibm Launcher for software applications
US8634814B2 (en) 2007-02-23 2014-01-21 Locator IP, L.P. Interactive advisory system for prioritizing content
US20080222611A1 (en) * 2007-03-09 2008-09-11 Microsoft Corporation Generic validation layer for object properties
US8539480B2 (en) * 2007-04-09 2013-09-17 Sugarcrm Inc. Multi-instance “shadow” system and method for automated resource redundancy reduction across dynamic language applications utilizing application of dynamically generated templates
GB0712654D0 (en) * 2007-06-28 2007-08-08 Symbian Software Ltd Computing device having an embedded rom image
US20090259999A1 (en) * 2008-04-11 2009-10-15 Oracle International Corporation Method and system for applying a patch during application execution
US8327323B2 (en) * 2008-12-08 2012-12-04 International Business Machines Corporation Automatic copying by ancestor in object-oriented languages
US8190587B1 (en) * 2008-12-11 2012-05-29 Network Appliance, Inc. In-place image promotion
KR100892882B1 (en) * 2008-12-24 2009-04-15 고혜선 Management method of article
US9811353B1 (en) * 2010-07-29 2017-11-07 Crimson Corporation Remotely invoking dynamic classes on a computing device
JP5682220B2 (en) * 2010-10-14 2015-03-11 株式会社リコー Information processing apparatus, information processing method, and information processing program
US8321480B2 (en) * 2010-11-24 2012-11-27 Bmc Software, Inc. Full-function to high availability large database conversion
US9665601B1 (en) 2010-12-16 2017-05-30 Crimson Corporation Using a member attribute to perform a database operation on a computing device
US8438532B2 (en) 2011-04-19 2013-05-07 Sonatype, Inc. Method and system for scoring a software artifact for a user
US8612936B2 (en) 2011-06-02 2013-12-17 Sonatype, Inc. System and method for recommending software artifacts
US9015661B1 (en) * 2011-06-23 2015-04-21 The Mathworks, Inc. Restricting class inheritance relationships
US8627270B2 (en) 2011-09-13 2014-01-07 Sonatype, Inc. Method and system for monitoring a software artifact
US8473894B2 (en) 2011-09-13 2013-06-25 Sonatype, Inc. Method and system for monitoring metadata related to software artifacts
US9141378B2 (en) 2011-09-15 2015-09-22 Sonatype, Inc. Method and system for evaluating a software artifact based on issue tracking and source control information
US8656343B2 (en) 2012-02-09 2014-02-18 Sonatype, Inc. System and method of providing real-time updates related to in-use artifacts in a software development environment
US8825689B2 (en) 2012-05-21 2014-09-02 Sonatype, Inc. Method and system for matching unknown software component to known software component
US9141408B2 (en) * 2012-07-20 2015-09-22 Sonatype, Inc. Method and system for correcting portion of software application
US8984542B2 (en) * 2012-11-30 2015-03-17 Facebook, Inc. Method and system for binding objects in dynamic programming languages using caching techniques
US9135263B2 (en) 2013-01-18 2015-09-15 Sonatype, Inc. Method and system that routes requests for electronic files
US9830135B2 (en) 2014-01-29 2017-11-28 Dell Products L.P. Declarative and pluggable business logic for systems management
US10656971B2 (en) 2014-01-31 2020-05-19 Dell Products L.P. Agile framework for vertical application development and delivery
US9626251B2 (en) 2014-01-31 2017-04-18 Dell Products L.P. Undo configuration transactional compensation
US9459859B2 (en) 2014-01-31 2016-10-04 Dell Products L.P. Template derivation for configuration object management
US10114861B2 (en) 2014-01-31 2018-10-30 Dell Products L.P. Expandable ad hoc domain specific query for system management
JP6409514B2 (en) * 2014-11-10 2018-10-24 日本電気株式会社 Information processing apparatus, library loading method, and computer program
US9519468B2 (en) 2015-02-13 2016-12-13 Oracle International Corporation Modular co-versioning in a dynamically linked runtime environment
US9971594B2 (en) 2016-08-16 2018-05-15 Sonatype, Inc. Method and system for authoritative name analysis of true origin of a file
US11113180B2 (en) * 2020-01-31 2021-09-07 Salesforce.Com, Inc. Efficiently tracking code location of run-time events in system software
CN113625995A (en) * 2020-05-07 2021-11-09 武汉斗鱼网络科技有限公司 Method and device for self-adaptively acquiring data
US11347523B2 (en) 2020-11-05 2022-05-31 International Business Machines Corporation Updated shared library reloading without stopping the execution of an application
US11681520B2 (en) * 2021-04-20 2023-06-20 International Business Machines Corporation Software upgrading using dynamic link library injection
CN115794260B (en) * 2023-02-06 2023-05-05 湖南高至科技有限公司 Simple dynamic loading method for DSP software library

Family Cites Families (18)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
DE3788877T2 (en) * 1987-03-24 1994-06-23 Insignia Solutions Ltd DEVICE FOR SOFTWARE EMULATION.
JPH01503181A (en) * 1987-03-24 1989-10-26 インシグニア・ソリューションズ・リミテッド Computer
US5261080A (en) * 1987-08-21 1993-11-09 Wang Laboratories, Inc. Matchmaker for assisting and executing the providing and conversion of data between objects in a data processing system storing data in typed objects having different data formats
JP2569092B2 (en) * 1987-12-11 1997-01-08 株式会社日立製作所 Address resolution method for I / O device control program
US5247678A (en) * 1989-10-12 1993-09-21 Texas Instruments Incorporated Load time linker for software used with a multiprocessor system
US5269021A (en) * 1989-10-12 1993-12-07 Texas Instruments Incorporated Multiprocessor software interface for a graphics processor subsystem employing partially linked dynamic load modules which are downloaded and fully linked at run time
GB2242293A (en) * 1990-01-05 1991-09-25 Apple Computer Apparatus and method for dynamic linking of computer software components
US5297279A (en) * 1990-05-30 1994-03-22 Texas Instruments Incorporated System and method for database management supporting object-oriented programming
US5317703A (en) * 1990-06-29 1994-05-31 Hitachi, Ltd. Information processing apparatus using an advanced pipeline control method
US5297249A (en) * 1990-10-31 1994-03-22 International Business Machines Corporation Hypermedia link marker abstract and search services
US5204947A (en) * 1990-10-31 1993-04-20 International Business Machines Corporation Application independent (open) hypermedia enablement services
US5247681A (en) * 1990-12-18 1993-09-21 International Business Machines Corporation Dynamic link libraries system and method
EP0546682A3 (en) * 1991-12-12 1993-12-08 Ibm Parent class shadowing
US5421016A (en) * 1991-12-12 1995-05-30 International Business Machines Corporation System and method for dynamically invoking object methods from an application designed for static method invocation
US5359721A (en) * 1991-12-18 1994-10-25 Sun Microsystems, Inc. Non-supervisor mode cross address space dynamic linking
US5339430A (en) * 1992-07-01 1994-08-16 Telefonaktiebolaget L M Ericsson System for dynamic run-time binding of software modules in a computer system
US5375241A (en) * 1992-12-21 1994-12-20 Microsoft Corporation Method and system for dynamic-link library
US5315703A (en) * 1992-12-23 1994-05-24 Taligent, Inc. Object-oriented notification framework system

Cited By (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US11675593B2 (en) 2021-08-31 2023-06-13 International Business Machines Corporation Dynamically updating a dynamic library

Also Published As

Publication number Publication date
WO1995001598A1 (en) 1995-01-12
US5615400A (en) 1997-03-25
EP0706684B1 (en) 1998-11-04
DE69414387D1 (en) 1998-12-10
DE69414387T2 (en) 1999-07-15
EP0706684A1 (en) 1996-04-17
CA2166302A1 (en) 1995-01-12
AU7253894A (en) 1995-01-24

Similar Documents

Publication Publication Date Title
CA2166302C (en) System for object oriented dynamic linking based upon a catalog of registered function set or class identifiers
US6415435B1 (en) Method and apparatus for determining compatibility of parent classes in an object oriented environment using versioning
EP0546683B1 (en) Language neutral objects
EP0664903B1 (en) Loader system
US7225438B2 (en) Lazy compilation of template-generated classes in dynamic compilation execution environments
US5421016A (en) System and method for dynamically invoking object methods from an application designed for static method invocation
US6658421B1 (en) System and method for detecting release-to-release binary compatibility in compiled object code
US6745385B1 (en) Fixing incompatible applications by providing stubs for APIs
US5339438A (en) Version independence for object oriented programs
AU777773B2 (en) Translating and executing object-oriented computer programs
EP0546809A2 (en) Computer with object oriented environment
JPH05274151A (en) System and method for determining new class object
US20040268301A1 (en) Adding new compiler methods to an integrated development environment
JPH10505693A (en) System and method for providing interoperability between heterogeneous object systems
JPH06103075A (en) Operation for object-oriented application
US11726810B2 (en) Systemic extensible blockchain object model comprising a first-class object model and a distributed ledger technology
US7007198B2 (en) Method for handling exceptions of applications
Hamilton Language integration in the common language runtime
US20050071809A1 (en) System and method for serializing objects in a compiled programming language
JP2005063449A (en) Method and apparatus for object-to-object java native interface mapping
WO2011042228A1 (en) Method and system to handle java class versioning
US20030014555A1 (en) System and method for efficient dispatch of interface calls
US6748503B1 (en) System and method facilitating unmanaged code participation in garbage collection
EP0803801A1 (en) Method and apparatus for mixing objective-C and C++ objects
Hamilton Montana Smart Pointers: They're Smart, and They're Pointers.

Legal Events

Date Code Title Description
EEER Examination request
MKEX Expiry

Effective date: 20140630