summaryrefslogtreecommitdiff
path: root/trunk/glagen/dll/README
blob: 36d270e227ed181024a6fb5cc6c62012789cb7c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

	=============================
	Dynamic Library Loader Module
	=============================
	GLAGEN - 2002 - Hugues HIEGEL




	I. What is it ?


The Dynamic Library Loader Module (DLL Module) is part of the GLAGEN
Engine. It goals is to provide to the end-user a flexible usage of
external C/C++ libraries (*.so) .

At this time, only C++ libraries are supported, because the main DLL
Module is already written in C++. It should be easy to allow C-written
libraries, but du to a lack of time, it should appear.. later.


	II. How does it work ?


The DLL Engine reads all libraries, especially their Names and
Dependancies, and then builds a dependancies tree. This last would be
used by the Network module (written by lam_m), and should determine in
which order each library would be executed in the main loop.
For example:

    library A needs nobody, alike library B. Libraries AC and AD needs
    A, BE and BF need B, ACG needs AC and BFH needs BF.
    We would obtain such a tree:

      (root)
	\__________________
         |                |
	 A                B
	 \_______	  \_____
	  |    	|      	   |   |
	  AC	AD	   BE  BF
 	  \_  		       \_
	   |			|
	   ACG			BFH


    Then the execution order would be done in such an order, reading
    the tree top-to-bottom, then left-to-right:
    A-AC-ACG-AD-B-BE-BF-BFH

    Like that, we are certain that any library would be able to read
    the results of one of its dependancies.

I did a Library class that contains a lot of infos about each
library.so. For each library file, I effectively create a new Library
instance, and initialize it by opening the library, ang trying to get
infos using dlsym and some canonical symbols (See section above for
more info about libraries' symbols). If the library do answer to the
required ones, then it is stored, else it is immediately closed and
forgotten.

Along the program, we will mainly work with list of Libraries, for
this class is our swiss tool.



	III. The Library class

In this section, I will explain the main characteristics of this class
and the method used.

  III.0 Hello, Bye

First of all, we allow the user to make two functions in its library :
GLG_Hello and GLG_Bye, in which he could put an hello and bye message
to the standard out. For example. He also could wathever he wants in
them, but no initialisation. These would be desribed in the next
chapter. Hello and Bye are there just to give flexibility and a bit of
fun.

  III.1 Initialisation

Creating a new Library class and Loading it consists in giving a
library filename, trying to open it, then trying to obtain a DL
handler.
If a handler is obtained, we load some Symbols to check if it is
a real GLAGEN library : the .so must return a name as a string in
respond to the call at GLG_Name(). Then we try to get its dependancies.
These infos are finally used to generate the dependances tree ahead.
The dependancies are given under a list of string, that make the
treatment easier.

Each library is allowed to use as many properties it wants for every
3d engine's dot. Each dot has a list of properties, and this list is
created by a recursive call of every library's GLG_Init symbol. Each
library class associated with each library file retains for each
property requested its position in the global list of properties.
For example:

    Library Foo needs to use and/or share three sorts of data in the
    whole glagen process, for example a surface information, a color
    one and the age of the captain.
    Foo should have a GLG_Init() function like this :

	GLG_Init(...)
	{
	  ...
	  palloc(surface, ...);
	  palloc(color, ...);
	  palloc(captainage, ...);
	  ...
	}

     The library class linked with this library would then ask the
     server for some memory rooms, and then stores three (because of
     the three palloc()) keys in some deep owned property.
     During the main loop, the library should only ask to read or
     write its third room to obtain or modify the captainage.
     It doesn't even know the captainage is really stored in some
     42nd room in the whole 'memory'.

palloc() is a function that calls itself a method of the current
calling library, so this library can stores the global acces method on
the local machine.
For that, the initialize() method gives a pointer to (this) to the
GLG_Init of the dll. Then this dll has nothing to do qith this
pointer, just give it as a parameter to palloc(). This palloc(),
defined out of the library class, calls then the REF->_palloc() method.
I didn't found a simpliest method to do that, because I didn't want
the dll developper hav to know anything about the Library class.
If I forced him to call REF->_palloc() instead of palloc(REF), he
would have to know the REF* prototype for its GLG_Init definition,
then he would have to use the libraryclass header.
My goal is to provide him a 'totally' independant code. So, I choose
to make him take a void* REF in its GLG_Init(), and then give this 
void* REF to palloc, which takes it as a Libary*.
See code for more details : ./dll/classes/libclass.hh and a sample
library code.


  III.2 Global properties accesses

Two functions allow libraries to access dots properties, in read or
write mode. 
For example:

    Library17 has 3 dots properties, declared in order (the 1st in
    first place, the 2nd in second place and the 3rd in last). 
    The library's user know what is the first property, what is the
    second, and what is the third. For example, he decides the first
    property is the color, the second the height, and
    god-know-whatever is the third. When he wants to access the color
    property, he would only call a GLG_read(2, ...) function.
    This function will then call a method of the current class to get
    the REAL position of this 2nd element in the whole list of
    properties, shared by many other libraries..
    And then, the access of the '2nd' element would be transparent to
    the user.

There is also a GLG_write function based on same principle. They both
looks like read and write standard C functions, which is absolutely
natural.

The main difficulty of these functions were that I didn't know in
which level the efficient read and write should be done. In the
library engine ? In which level ? Client-side ? Server-side ? If
ti is in Client-side, how would the server know ? If it is in
Server-side, how would the Client know ??

So, we decided to keep one dot property tab in each computer (clients
and server), make all inits, reads and writes in the local computer.
A first initialisation is made in the server, to know the global size
of a dot property tab. Then a second is done in each client, which
returns to the server the total size found. Then the server knows what
it will allocate for each client.
Example:

    The server loads libraries A, AC and B. A needs 4 bytes, AC needs
    3, and B needs 5. The server knows that A and AC will be sent to
    the client1. Then he allocates 4+3 then 7 bytes to client1, and
    the 5 last bytes to client2. Client1 receives A and AC, reads them
    and finds 7 bytes to allocate locally. Client2 will find 5 bytes
    to allocate locally. After each main loop, client1 will send its 7
    bytes to the server, who will put them in right place. Client2
    sends its 5 bytes, and the server puts them in back of the 7 first
    bytes.

That is trivial. Although this is the network part, I did the routine
to make that. The source code can be found in
create_dotproperty_init.cc file. It has to be included in right place
in the clients and server main functions.


  III.3 Main loop

Not yet fully implemented.
The main loop call is called GLG_Main, and would take as argument a
Dot* pointer. Then the user has to include the dot.hh header, found in
the 3d engine directory or in the ./classes folder.
In this main loop, the user just has to read and write properties in
the given Dot. The time and other dot-independant informations should
be given in a method that has not really been specified at this time.
The read function calls should be done specifiying a library name, and
the result will be given only if the current library has read access
to the given one. There, the dependancies takes all its meaning. 
But why would we do more processing by checking the permissions ? This
permitts Glagen to be a clean processus.
However, a library could read its dependancies properties and
recursively the dependancies of its dependancies. That would look more
natural in this way.
Note that there are two 'system' properties, such as primary color and
primary height of the dot. 'Primary', because one 'dot' should
represent superposed surfaces' dots.
Finally, some Perlin noise functions should have been given in this
level, allowing the user to make realistic world renderings.
Just see the sun example in our website to be convinced ;)


       IV. Conclusion

This part is not yet finished, due to some difficulties to understand
how would my module work in the global project. The mainloop call
is not realy finished, but some minor changes have to be done. 
The main squeletton is already the module itself, so I am globally
satisfied about my work, although I would be more satisfied if it were
really included in the final project.
Since it is under GPL, I would not abandon it. I spent too much time
on it to give forfeit. Without the pressure of the school, I would
certainly end my module and best it in great state of spirit.

The main reason, I think, that I didn't finish my part in time, is
that I spent to much time on making a clean code. A program that
doesn't bug without reason. This is the most important to me.
If I made a code in the only goal to make a finished product, I would
certainly hav missed lots of bugs, and the final result code would
have been so awful I would never continue it.
did