Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
b35c3f7c63ae3842ca780007620ca6edb90c63aa
[simgrid.git] / doc / gtut-tour-05-globals.doc
1 /**
2 @page GRAS_tut_tour_globals Lesson 5: Using globals in processes
3
4 \section GRAS_tut_tour_globals_toc Table of Contents
5  - \ref GRAS_tut_tour_globals_intro
6  - \ref GRAS_tut_tour_globals_use
7  - \ref GRAS_tut_tour_callback_pitfall
8  - \ref GRAS_tut_tour_callback_recap
9     
10 <hr>
11
12 \section GRAS_tut_tour_globals_intro Introduction
13
14 Callbacks are great to express your processes as state machines, but they
15 pose another problem: callbacks don't have acces to the variable declared
16 within the scope of the process' main function (of course). You should
17 however resist to the temptation to declare globals outside of the scope of
18 the functions, or you won't be able to use more than one process of each
19 type in the simulation. Remember, all gras processes run as thread
20 within the same naming space in SG so your globals will be shared between
21 the several instances of your process, leading to bad problems.
22
23 Instead, you you have to put all globals in a structure, and let GRAS handle
24 it with the gras_userdata_* functions (there is only 3 of them ;). 
25
26 \section GRAS_tut_tour_globals_use Putting globals into action
27
28 We will now modify the example to add a "kill" message, and let the server
29 loop on incoming messages until it gets such a message. We only need a
30 boolean, so the structure is quite simple: 
31 \dontinclude 05-globals.c
32 \skip struct
33 \until server_data
34  
35 Then, we need to create this structure in the process main function. We
36 could use either gras_userdata_new() or gras_userdata_set(). The former is an
37 helper macro mallocing the space needed by the structure and passing it to
38 gras using the latter function. If you go for gras_userdata_set(), you
39 should pass it a pointer to your data you want to retrieve afterward.
40
41 \dontinclude 05-globals.c
42 \skip userdata_new
43 \until userdata_new
44
45 BEWARE, the gras_userdata_new expects the pointed type, not the
46 pointer type. As you can see, in our example, you should pass
47 server_data_t to the macro, even if the global variable is later
48 defined as being of type server_data_t*.
49
50 Once you declared a global that way, retriving this (for example in a
51 callback) is really easy:
52 \dontinclude 05-globals.c
53 \skip userdata_get
54 \until userdata_get
55
56 We can now write the callback, which simply retrive the globals and change
57 the value of the <tt>kileld</tt> field.
58 \dontinclude 05-globals.c
59 \skip kill_cb
60 \until end_of_kill_callback
61
62 And we replace the single gras_msg_handle() of the server main function by a
63 loop:
64 \skip while
65 \until }
66
67 \section GRAS_tut_tour_callback_pitfall Common pitfall of globals
68
69 There is an error that I do myself every other day using globals in GRAS.
70 This is to write something like:
71 \verbatim int server(int argc, char *argv[]) {
72   server_data_t globals=gras_user_new(server_data_t);
73   /* other variable definition */
74   
75   gras_init(&argc, argv);
76   
77   /* rest of the code */
78 }\endverbatim
79
80 The problem is that you call gras_userdata_new() before gras_init(). Doing so,
81 embarass GRAS since it does not have its internal buffer initialized yet,
82 and cannot store your data anywhere. That is why doing so triggers an error
83 at run time.
84
85 \section GRAS_tut_tour_callback_recap Recaping everything together
86
87 The whole program now reads:
88 \include 05-globals.c
89
90 And here is the output (unchanged wrt previous version):
91 \include 05-globals.output
92
93 That's it, we're done. We have a server able to handle any number of
94 messages, which the client can stop remotely properly. That's already
95 something, hu?
96
97 Go to \ref GRAS_tut_tour_logs
98
99 */