Previous: Access to data
Up: Tutorial
Next: Using calculator
Previous Page: Access to data
Next Page: Using calculator
Subroutine fill_points (page ) could be simply called from our program. However, a more general way of using it is to install it as a part of a class driver - this way it will be called automatically - when needed.
The entry routine for the class driver is shown below. It is called with a message and some information about the object.
point class driver routine - point_class.f
subroutine point_class(msg,ivdsn,instr,idone) * * ******************************************************************** * * * *$$ * subroutine point_class Driver of 'point' class * * * * * ******************************************************************** * structure/instr_t/ character*80 name integer class integer type integer lun integer pnt end structure record/instr_t/ instr character*(*) msg integer ivdsn,idone character*5 cid pointer (cid_p,cid) saveif( msg.eq.'FILL' .or. msg.eq.'REFILL' ) then if( instr.name(:7).ne.'point_t' ) then idone = 0 else call fill_points(ierr) if( ierr.eq.0 ) then idone = 1 else idone = 0 endif endif else if( msg.eq.'INIT' ) then idone = 1 else if( msg.eq.'LIST' ) then write(instr.lun,'(''Point Class (CLASS=2000,IDENT=point)'')') idone = 1 else if( msg.eq.'IDENT' ) then cid_p = instr.pnt cid = 'point' idone = 1 else if( msg.eq.'NEW' ) then idone = 1 else if( msg.eq.'PUT' ) then idone = 1 else idone = 0 endif
end
This subroutine will be called when a message is sent to an object of class point. It calls fill_points independently whether the object has data or not when the message is sent (REFILL and FILL message). Just in case there is another object defined in the same class - there is a simple check whether the object in question is the one fill_points knows about. Other messages handled by the driver are the 'automatic' messages which DSPACK sends. A more general driver could react to other messages which the user can send to an object.
The driver has to be installed. This means that we have to pass the address of the driver's entry point to DSPACK. If our data description file is to be read on initialization, then the driver should be installed before DSPACK is initialized.
Example 2 - installing a class - file example_2.f
program example_2 * * ******************************************************************** * * * *$$ * program example_2 DSPACK tutorial example_2 * * * * * * Ryszard Zybert Jul 1 12:58:10 1994 * * ******************************************************************** * parameter ( IPCLASS=2000 ) external point_class* Install point class
ipc = IPCLASS call ds_install(ipc,point_class)
* Initialise DSPACK, local mode, 2MB memory
call dsinit(0,'example_2',6,500000,50000,ierr)
* Call ds_examine and do the rest interactively
call ds_examine(' ')
end
This program will use it's own settings from dspackrc_2 file (page ) because the name passed to dsinit changed to example_2.
The program is made using the same Makefile:
make example_2
The file dspack_tut_4.d should be used instead of dspack_tut_2.d. This can be done by using a different 'pilot' file.
dspack_tut_5.d file
* * ******************************************************************** * * * *$$ * dspack_tut_5.d DSPACK tutorial - example 2 * * * * * ******************************************************************** * INCLUDE dspack_tut_1.d INCLUDE dspack_tut_4.d
Now everything is ready to run it. First we can look at the constants which were initialized in dspack_tut_4.d
Example 2 session
examples> example_2 tut_file=dspack_tut_5.d dspackrc_2 file in $DSPACK_HOME/doc/tutorial ********************* * This is Example 2 * ********************* DSPACK 1.130, 5 Jul 1994 dsdb> {\bf ls -l} Name Type Id Sect Size Items Nent Bytes V3 R 18 0 3 3 0 0 track_t S 19 1 20 11 0 0 point_t S 20 1 9 4 0 0 vertex_t S 21 1 10 5 0 0 POINT_C_T R 22 2 4 4 2 32dsdb> {\bf *POINT_C_T} Data set: POINT_C_T Entry: 1 Type: Real (at: 7583408) 1 A Y slope : 1.00000E-02 2 B Y intercept : 1.00000 3 C X slope : 2.00000E-02 4 D X intercept : 0.500000 Entry: 2 Type: Real (at: 7583424) 1 A Y slope : 3.00000E-02 2 B Y intercept : 3.00000 3 C X slope : 2.00000E-02 4 D X intercept : 2.50000 dsdb>
The ls -l command produces a long catalogue of objects. The first five columns deal with the definition of the object, the last two, with the data. POINT_C_T has two entries, taking 32 bytes of memory, other objects are empty. (V3 will always be empty - templates cannot keep data).
Although everything needed to fill point_t is in place, the object is still empty. Our program will be called as soon as a request for the data of point_t is made.
To start with - we can check if the driver was installed correctly.
Listing drivers
dsdb> drivers Point Class (CLASS=2000,IDENT=point) Calculator Class (CLASS=10,IDENT=calc) Environment Class (CLASS=20,IDENT=env) Hepdb Class (CLASS=40,IDENT=hepdb) Exec Class (CLASS=50,IDENT=exec) dsdb>
Now we can trigger the driver's action by just looking at point_t data.
Class driver in action
dsdb> ls -l Name Type Id Sect Size Items Nent Bytes V3 R 18 0 3 3 0 0 track_t S 19 1 20 11 0 0 point_t S 20 1 9 4 0 0 vertex_t S 21 1 10 5 0 0 POINT_C_T R 22 2 4 4 2 32dsdb> *point_t(3:5) Data set: point_t(3:5) Entry: 3 Type: Structure (at: 5704996) 1 pos V3 Type: Real (at: 5704996) 1 x X component : 0.520000 2 y Y component : 1.01000 3 z Z component : 1.00000 2 d V3 Type: Real (at: 5705008) 1 x X component : 5.20000E-03 2 y Y component : 1.01000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Pointer : 5705068 Entry: 4 Type: Structure (at: 5705032) 1 pos V3 Type: Real (at: 5705032) 1 x X component : 2.52000 2 y Y component : 3.03000 3 z Z component : 1.00000 2 d V3 Type: Real (at: 5705044) 1 x X component : 2.52000E-02 2 y Y component : 3.03000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Pointer : 5705104 Entry: 5 Type: Structure (at: 5705068) 1 pos V3 Type: Real (at: 5705068) 1 x X component : 0.540000 2 y Y component : 1.02000 3 z Z component : 2.00000 2 d V3 Type: Real (at: 5705080) 1 x X component : 5.40000E-03 2 y Y component : 1.02000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Pointer : 5705140 dsdb> ls -l Name Type Id Sect Size Items Nent Bytes V3 R 18 0 3 3 0 0 track_t S 19 1 20 11 0 0 point_t S 20 1 9 4 10 360 vertex_t S 21 1 10 5 0 0 POINT_C_T R 22 2 4 4 2 32
dsdb>
The first ls -l shows no entries for point_t. However, the request for display of data causes a FILL message to be sent to the object - our driver is called and fills the object with data. It can be seen that our link-list seems to be contructed properly - point_t(3) has a pointer which agrees with the address of point_t(5). This can be seen easily by asking DSPACK to return indexes rather than pointers:
dsdb> indexes Showing indexes dsdb> *point_t(3:5) Data set: point_t(3:5) Entry: 3 Type: Structure (at: 5704996) 1 pos V3 Type: Real (at: 5704996) 1 x X component : 0.520000 2 y Y component : 1.01000 3 z Z component : 1.00000 2 d V3 Type: Real (at: 5705008) 1 x X component : 5.20000E-03 2 y Y component : 1.01000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Index : 5 Entry: 4 Type: Structure (at: 5705032) 1 pos V3 Type: Real (at: 5705032) 1 x X component : 2.52000 2 y Y component : 3.03000 3 z Z component : 1.00000 2 d V3 Type: Real (at: 5705044) 1 x X component : 2.52000E-02 2 y Y component : 3.03000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Index : 6 Entry: 5 Type: Structure (at: 5705068) 1 pos V3 Type: Real (at: 5705068) 1 x X component : 0.540000 2 y Y component : 1.02000 3 z Z component : 2.00000 2 d V3 Type: Real (at: 5705080) 1 x X component : 5.40000E-03 2 y Y component : 1.02000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Index : 7 dsdb>
There is also a special syntax which can be used to display a link list. One has to specify the pointer to the list and the name of follow-up pointer, separated by a double colon:
The link-list must be terminated by a NULL pointer.
Displaying link-lists
dsdb> pointers Showing pointers dsdb> *point_t(2).*next::*next Data set: point_t(2).*next::*next, Entry: 2 Link-list entry: 1 Entry: 4 out of 10 Type: Structure (at: 5705032) 1 pos V3 Type: Real (at: 5705032) 1 x X component : 2.52000 2 y Y component : 3.03000 3 z Z component : 1.00000 2 d V3 Type: Real (at: 5705044) 1 x X component : 2.52000E-02 2 y Y component : 3.03000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Pointer : 5705104 Link-list entry: 2 Entry: 6 out of 10 Type: Structure (at: 5705104) 1 pos V3 Type: Real (at: 5705104) 1 x X component : 2.54000 2 y Y component : 3.06000 3 z Z component : 2.00000 2 d V3 Type: Real (at: 5705116) 1 x X component : 2.54000E-02 2 y Y component : 3.06000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Pointer : 5705176 Link-list entry: 3 Entry: 8 out of 10 Type: Structure (at: 5705176) 1 pos V3 Type: Real (at: 5705176) 1 x X component : 2.56000 2 y Y component : 3.09000 3 z Z component : 3.00000 2 d V3 Type: Real (at: 5705188) 1 x X component : 2.56000E-02 2 y Y component : 3.09000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Pointer : 5705248 Link-list entry: 4 Entry: 10 out of 10 Type: Structure (at: 5705248) 1 pos V3 Type: Real (at: 5705248) 1 x X component : 2.58000 2 y Y component : 3.12000 3 z Z component : 4.00000 2 d V3 Type: Real (at: 5705260) 1 x X component : 2.58000E-02 2 y Y component : 3.12000E-02 3 z Z component : 1.00000E-02 3 flags(1) Integer : 1 3 flags(2) Integer : 2 4 *next Pointer : 0 dsdb>
Note that the list above starts from point_t(4) which is the second element of the real list. In order to display the complete list we would need a pointer to the first element of the list - we don't have it yet, so we use the pointer stored in point_t(2) which points to point_t(4).