1CPOOL(3)                   Common Library Functions                   CPOOL(3)
2
3
4

NAME

6       Cpool - LCG Pool inferface
7

SYNOPSIS

9       #include <Cpool_api.h>
10
11       int Cpool_create(int nbwanted, int * nbget);
12
13       int  Cpool_assign(int poolid, void *(*startroutine)(void *), void *arg,
14       int timeout);
15
16       int Cpool_next_index(int poolid);
17
18       int Cpool_next_index_timeout(int poolid, int timeout);
19
20

ERRORS

22       See Cthread corresponding section.
23
24

DESCRIPTION

26       (Please read the NOTE section)
27
28       Cpool is a layer built upon  Cthread,  the  LCG  Thread  interface.  It
29       allows the user to create dedicated pools, and then to assign to one of
30       them a given routine to execute.
31
32       The created processes or threads will remain alive, unless the routines
33       assigned to are crashing, or explicitly calling an exit statement, like
34       exit() or pthread_exit().
35
36       Typical use might be writing a server, with a bunch of pre-created pro‐
37       cesses  or  pools  (depending on the environment with which Cthread has
38       been compiled), and assign to a given pool a routine  with  the  socket
39       file descriptor as argument address.
40
41       In principle Cpool should be compiled with the same relevant flags with
42       which Cthread has been.
43
44       int Cpool_create(int nbwanted, int * nbget);
45
46       This method is creating a pool of nbwanted processes or threads. If the
47       second  argument,  nbget  ,  is not NULL, its location will contain the
48       number of effectively created threads or processes.
49
50       Return value is the pool ID, a number greater or equal to zero,  or  -1
51       in case of error.
52
53       int  Cpool_assign(int poolid, void *(*startroutine)(void *), void *arg,
54       int timeout);
55
56       This method is assigning a routine to poolid as returned by  Cpool_cre‐
57       ate,  whose  address  is startroutine , that have the same prototype as
58       every typical routine in multithread programming. This  means  that  it
59       returns a pointer, and it gets as entry a pointer identified by the arg
60       parameter. The last argument is a possible timeout , in seconds,  which
61       will  apply  if  it is greater than zero. If it is lower than zero, the
62       assignment will wait forever until a thread  is  available.  If  it  is
63       equal  to  zero,  the  method  will  return immediately if no thread is
64       available.
65
66       Return value is 0 if success, or -1 in case of error.
67
68       int Cpool_next_index(int poolid);
69
70       int Cpool_next_index_timeout(int poolid, int timeout);
71
72       Those methods returns that next available thread number  that  will  be
73       assigned  if you ever call Cpool_assign immediately after. If you spec‐
74       ify a timeout lower or equal than zero, then this is a blocking  method
75       until  one  thread  is available at least. Those methods, so, returns a
76       number greater or equal than zero, and -1 if there is an error.
77
78

NOTE

80              Arguments passing in a non-thread environment
81
82              Since a forked process can only address its namespace data  seg‐
83              ment, the address of the arguments, if any, valid in its parent,
84              will not be directly accessible for the  child  we  are  talking
85              about.
86
87              This  means  that  Cpool,  in  a non-thread environment, have to
88              trace-back all the memory allocation  visible  for  the  parent.
89              Then, Cpool is not passing the address of the arguments, but its
90              content to the child through a child-parent communication, moni‐
91              tored with a simple protocol.
92
93              There are four cases:
94                         1.The address is NULL: nothing will be transmitted to
95                     the child
96                         2.The address is exactly a pointer returned  by  mal‐
97                     loc()  or realloc(): the full malloced area will be tran‐
98                     mitted.
99                         3.The address  is  somewhere  in  a  memory  allocate
100                     block: the remaining memory block, e.g. starting from the
101                     address up to its end, will be transmitted.
102                         4.the address do not point to  any  memory  allocated
103                     area:  Cpool  will  assume it is a pointer-like argument,
104                     probably to some static variables, visible for  all  pro‐
105                     cesses,  and  will  transmit  the  content  of the memory
106                     pointed by the address, assuming it is coded on 64-bits.
107              In any case, the user is passing a pointer, and the routine will
108              see  a  pointer,  pointing  to  a  (hopefully, see the point 4.,
109              listed upper) same-content area.
110
111              Arguments design to work on both thread and non-thread  environ‐
112              ments
113
114              The thread and non-thread arguments can have conceptually a dif‐
115              ferent design when dealing with arguments;
116
117              In a thread environment, the routined passed to Cpool_assign, is
118              sharing  memory,  so  is allowed to free() the argument, because
119              memory is then shared.  On the contrary, in a  non-thread  envi‐
120              ronment, this may be a segmentation fault.
121
122              This  means that it is recommended to use static variables, con‐
123              taining simple value, like an integer  (for  example:  a  socket
124              file descriptor), and not allocated memory. If, neverthless, you
125              persist to use free() in your routine, you can use the following
126              trick:
127
128              /* ------------------------ */
129              /* In the Caller Routine    */
130              /* ------------------------ */
131
132              arg = malloc(...);
133
134              if (! Cpool_assign(...)) {
135                if (Cthread_environment() != CTHREAD_TRUE_THREAD) {
136                  /* Non-Thread environment */
137                  free(arg);
138                } else {
139                  /* Thread environment     */
140                  /* ... do nothing         */
141                }
142              } else {
143                  /* In cany case it is OK  */
144                  free(arg);
145              }
146
147              /* ------------------------ */
148              /* In the Execution Routine */
149              /* ------------------------ */
150
151              void *routine(void *arg) {
152                ./..
153                if (Cthread_environment() == CTHREAD_TRUE_THREAD) {
154                  /* Thread environment */
155                  free(arg);
156                } else {
157                  /* Non-Thread environment */
158                  /* ... do nothing         */
159                }
160                ./..
161              }
162

EXAMPLE

164       #include <Cpool_api.h>
165       #include <stdio.h>
166       #include <errno.h>
167
168       #define NPOOL 2
169       #define PROCS_PER_POOL 2
170       #define TIMEOUT 2
171       void *testit(void *);
172
173       int main() {
174         int pid;
175         int i, j;
176         int ipool[NPOOL];
177         int npool[NPOOL];
178         int *arg;
179
180         pid = getpid();
181
182         printf("... Defining %d pools with %d elements each\n",
183                NPOOL,PROCS_PER_POOL);
184
185         for (i=0; i < NPOOL; i++) {
186           if ((ipool[i] = Cpool_create(PROCS_PER_POOL,&(npool[i]))) < 0) {
187             printf("### Error No %d creating pool (%s)\n",
188                    errno,strerror(errno));
189           } else {
190             printf("... Pool No %d created with %d processes\n",
191                    ipool[i],npool[i]);
192           }
193         }
194
195         for (i=0; i < NPOOL; i++) {
196           /* Loop on the number of processes + 1 ... */
197           for (j=0; j <= npool[i]; j++) {
198             if ((arg = malloc(sizeof(int))) == NULL) {
199               printf("### Malloc error, errno = %d (%s)\n",
200                      errno,strerror(errno));
201               continue;
202             }
203             *arg = i*10+j;
204             printf("... Assign to pool %d (timeout=%d) the %d-th routine 0x%x(%d)\n",
205                    ipool[i],TIMEOUT,j+1,(unsigned int) testit,*arg);
206             if (Cpool_assign(ipool[i], testit, arg, TIMEOUT)) {
207               printf("### Can't assign to pool No %d (errno=%d [%s]) the %d-th routine\n",
208                      ipool[i],errno,strerror(errno),j);
209               free(arg);
210             } else {
211               printf("... Okay for assign to pool No %d of the %d-th routine\n",
212                      ipool[i],j);
213               If (Cthread_environment() != CTHREAD_TRUE_THREAD) {
214                 /* Non-thread environment: the child is in principle not allowed */
215                 /* to do free himself                                            */
216                 free(arg);
217               }
218             }
219           }
220         }
221
222         /* We wait enough time for our threads to terminate... */
223         sleep(TIMEOUT*NPOOL*PROCS_PER_POOL);
224
225         exit(EXIT_SUCCESS);
226       }
227
228       void *testit(void *arg) {
229         int caller_pid, my_pid;
230
231         my_pid = getpid();
232
233         caller_pid = (int) * (int *) arg;
234
235         if (Cthread_environment() == CTHREAD_TRUE_THREAD) {
236           /* Thread environment : we free the memory */
237           free(arg);
238         }
239
240         printf("... I am PID=%d called by pool %d, try No %d\n",
241                my_pid,caller_pid/10,caller_pid - 10*(caller_pid/10));
242
243         /*
244          * Wait up to the timeout + 1
245          */
246         sleep(TIMEOUT*2);
247
248         return(NULL);
249       }
250
251
252
253
254

SEE ALSO

256       Cthread
257

AUTHOR

259       LCG Grid Deployment Team
260
261
262
263LCG          $Date: 2010-04-05 09:51:26 +0200 (Mon, 05 Apr 2010) $    CPOOL(3)
Impressum