problems getting william's code to compile
[IRC.git] / Robust / src / Runtime / task.c
1 #ifdef TASK
2 #include "runtime.h"
3 #include "structdefs.h"
4 #include "mem.h"
5 #include "checkpoint.h"
6 #include "Queue.h"
7 #include "SimpleHash.h"
8 #include "GenericHashtable.h"
9 #include <sys/select.h>
10 #include <sys/types.h>
11 #include <sys/mman.h>
12 #include <string.h>
13 #include <signal.h>
14
15 extern int injectfailures;
16 extern float failurechance;
17 extern int debugtask;
18 extern int instaccum;
19
20 #ifdef CONSCHECK
21 #include "instrument.h"
22 #endif
23
24 struct genhashtable * activetasks;
25 struct parameterwrapper * objectqueues[NUMCLASSES];
26 struct genhashtable * failedtasks;
27 struct taskparamdescriptor * currtpd;
28 struct RuntimeHash * forward;
29 struct RuntimeHash * reverse;
30
31 int main(int argc, char **argv) {
32 #ifdef BOEHM_GC
33   GC_init(); // Initialize the garbage collector
34 #endif
35 #ifdef CONSCHECK
36   initializemmap();
37 #endif
38   processOptions();
39   initializeexithandler();
40   /* Create table for failed tasks */
41   failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd, 
42                                    (int (*)(void *,void *)) &comparetpd);
43   /* Create queue of active tasks */
44   activetasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd, 
45                                    (int (*)(void *,void *)) &comparetpd);
46   
47   /* Process task information */
48   processtasks();
49
50   /* Create startup object */
51   createstartupobject(argc, argv);
52
53   /* Start executing the tasks */
54   executetasks();
55 }
56
57 void createstartupobject(int argc, char ** argv) {
58   int i;
59   
60   /* Allocate startup object     */
61 #ifdef PRECISE_GC
62   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
63   struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1); 
64 #else
65   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
66   struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1); 
67 #endif
68   /* Build array of strings */
69   startupobject->___parameters___=stringarray;
70   for(i=1;i<argc;i++) {
71     int length=strlen(argv[i]);
72 #ifdef PRECISE_GC
73     struct ___String___ *newstring=NewString(NULL, argv[i],length);
74 #else
75     struct ___String___ *newstring=NewString(argv[i],length);
76 #endif
77     ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;
78   }
79   
80   /* Set initialized flag for startup object */
81   flagorand(startupobject,1,0xFFFFFFFF);
82 }
83
84 int hashCodetpd(struct taskparamdescriptor *ftd) {
85   int hash=(int)ftd->task;
86   int i;                                                
87   for(i=0;i<ftd->numParameters;i++){ 
88     hash^=(int)ftd->parameterArray[i];
89   }
90   return hash;
91 }
92
93 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
94   int i;
95   if (ftd1->task!=ftd2->task)
96     return 0;
97   for(i=0;i<ftd1->numParameters;i++)
98     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
99       return 0;
100   return 1;
101 }
102
103 /* This function sets a tag. */
104 #ifdef PRECISE_GC
105 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
106 #else
107 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
108 #endif
109   struct ___Object___ * tagptr=obj->___tags___;
110   if (tagptr==NULL) {
111     obj->___tags___=(struct ___Object___ *)tagd;
112   } else {
113     /* Have to check if it is already set */
114     if (tagptr->type==TAGTYPE) {
115       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
116       if (td==tagd)
117         return;
118 #ifdef PRECISE_GC
119       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
120       struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
121       obj=(struct ___Object___ *)ptrarray[2];
122       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
123       td=(struct ___TagDescriptor___ *) obj->___tags___;
124 #else
125       struct ArrayObject * ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
126 #endif
127       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
128       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
129       obj->___tags___=(struct ___Object___ *) ao;
130       ao->___cachedCode___=2;
131     } else {
132       /* Array Case */
133       int i;
134       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
135       for(i=0;i<ao->___cachedCode___;i++) {
136         struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
137         if (td==tagd)
138           return;
139       }
140       if (ao->___cachedCode___<ao->___length___) {
141         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
142         ao->___cachedCode___++;
143       } else {
144 #ifdef PRECISE_GC
145         int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
146         struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
147         obj=(struct ___Object___ *)ptrarray[2];
148         tagd=(struct ___TagDescriptor___ *) ptrarray[3];
149         ao=(struct ArrayObject *)obj->___tags___;
150 #else
151         struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
152 #endif
153         aonew->___cachedCode___=ao->___length___+1;
154         for(i=0;i<ao->___length___;i++) {
155           ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
156         }
157         ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
158       }
159     }
160   }
161
162   {
163     struct ___Object___ * tagset=tagd->flagptr;
164     
165     if(tagset==NULL) {
166       tagd->flagptr=obj;
167     } else if (tagset->type!=OBJECTARRAYTYPE) {
168 #ifdef PRECISE_GC
169       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
170       struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
171       obj=(struct ___Object___ *)ptrarray[2];
172       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
173 #else
174       struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
175 #endif
176       ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
177       ARRAYSET(ao, struct ___Object___ *, 1, obj);
178       ao->___cachedCode___=2;
179       tagd->flagptr=(struct ___Object___ *)ao;
180     } else {
181       struct ArrayObject *ao=(struct ArrayObject *) tagset;
182       if (ao->___cachedCode___<ao->___length___) {
183         ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
184       } else {
185         int i;
186 #ifdef PRECISE_GC
187         int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
188         struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
189         obj=(struct ___Object___ *)ptrarray[2];
190         tagd=(struct ___TagDescriptor___ *)ptrarray[3];
191         ao=(struct ArrayObject *)tagd->flagptr;
192 #else
193         struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
194 #endif
195         aonew->___cachedCode___=ao->___cachedCode___+1;
196         for(i=0;i<ao->___length___;i++) {
197           ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
198         }
199         ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
200         tagd->flagptr=(struct ___Object___ *) ao;
201       }
202     }
203   }
204 }
205
206 /* This function clears a tag. */
207 #ifdef PRECISE_GC
208 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
209 #else
210 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
211 #endif
212   /* We'll assume that tag is alway there.
213      Need to statically check for this of course. */
214   struct ___Object___ * tagptr=obj->___tags___;
215
216   if (tagptr->type==TAGTYPE) {
217     if ((struct ___TagDescriptor___ *)tagptr==tagd)
218       obj->___tags___=NULL;
219     else
220       printf("ERROR 1 in tagclear\n");
221   } else {
222     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
223     int i;
224     for(i=0;i<ao->___cachedCode___;i++) {
225       struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
226       if (td==tagd) {
227         ao->___cachedCode___--;
228         if (i<ao->___cachedCode___)
229           ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
230         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
231         if (ao->___cachedCode___==0)
232           obj->___tags___=NULL;
233         goto PROCESSCLEAR;
234       }
235     }
236     printf("ERROR 2 in tagclear\n");
237   }
238  PROCESSCLEAR:
239   {
240     struct ___Object___ *tagset=tagd->flagptr;
241     if (tagset->type!=OBJECTARRAYTYPE) {
242       if (tagset==obj)
243         tagd->flagptr=NULL;
244       else
245         printf("ERROR 3 in tagclear\n");
246     } else {
247       struct ArrayObject *ao=(struct ArrayObject *) tagset;
248       int i;
249       for(i=0;i<ao->___cachedCode___;i++) {
250         struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
251         if (tobj==obj) {
252           ao->___cachedCode___--;
253           if (i<ao->___cachedCode___)
254             ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
255           ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
256           if (ao->___cachedCode___==0)
257             tagd->flagptr=NULL;
258           goto ENDCLEAR;
259         }
260       }
261       printf("ERROR 4 in tagclear\n");
262     }
263   }
264  ENDCLEAR:
265   return;
266   
267 }
268  
269 /* This function allocates a new tag. */
270 #ifdef PRECISE_GC
271 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
272   struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
273 #else
274 struct ___TagDescriptor___ * allocate_tag(int index) {
275   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
276 #endif
277   v->type=TAGTYPE;
278   v->flag=index;
279   return v;
280
281
282
283
284 /* This function updates the flag for object ptr.  It or's the flag
285    with the or mask and and's it with the andmask. */
286
287 void flagbody(struct ___Object___ *ptr, int flag);
288 #ifdef OPTIONAL
289 void enqueueoptional(struct ___Object___ * currobj);
290
291 struct optionaltaskdescriptor *** makeintersectionotd(int num, struct fsanalysiswrapper ** wrapperarray, int *result){
292   int i,j,k;
293   (*result)=0;
294   struct optionaltaskdescriptor *** bigtmparray = RUNMALLOC(sizeof(struct optionaltaskdescriptor **)*maxotd);
295   struct fsanalysiswrapper * tmpwrapper;
296   struct fsanalysiswrapper * firstwrapper = wrapperarray[0];/*we are sure that num>0*/
297   /*we check if the otd of the first wrapper is contained in all others*/
298   for(i=0; i<firstwrapper->numoptionaltaskdescriptors; i++){
299     struct optionaltaskdescriptor ** tmparray = RUNMALLOC(sizeof(struct optionaltaskdescriptor *) * num);
300     struct optionaltaskdescriptor * otd = firstwrapper->optionaltaskdescriptorarray[i];
301     tmparray[0]=otd;
302     for(j=1; j<num; j++){
303       tmpwrapper = wrapperarray[j];
304       for(k=0; k<tmpwrapper->numoptionaltaskdescriptors; k++){
305         struct optionaltaskdescriptor * tmpotd=tmpwrapper->optionaltaskdescriptorarray[k];
306         if(otd->task->name == tmpotd->task->name){
307           tmparray[j]=tmpotd;
308           goto nextwrapper;
309         }
310         RUNFREE(tmparray);
311         goto nextotd;
312       }
313     nextwrapper:
314       ;
315     }
316     bigtmparray[(*result)]=tmparray;
317     (*result)++;          
318   nextotd:
319     ;
320   }
321   
322   {/*now allocate the good size for otdarray and put the otds*/
323     struct optionaltaskdescriptor *** otdarray = RUNMALLOC(sizeof(struct optionaltaskdescriptor *) * (*result));
324     for(i=0; i<(*result); i++)     
325       otdarray[i]=bigtmparray[i];
326     
327     RUNFREE(bigtmparray);
328     return otdarray;
329   }
330 }
331 #endif
332  
333
334 void flagorand(void * ptr, int ormask, int andmask) {
335   int oldflag=((int *)ptr)[1];
336   int flag=ormask|oldflag;
337 #ifdef OPTIONAL
338   struct ___Object___ * obj = (struct ___Object___ *)ptr;
339   if(obj->failedstatus==1){/*store the information about exitfses*/
340     int i,j,counter=0, offset=0;
341     for(i=0; i<obj->numotds; i++){
342       counter+=obj->otds[i]->numenterflags;
343     }
344     obj->numexitfses=counter;
345     if(obj->exitfses!=NULL) RUNFREE(obj->exitfses);
346     obj->exitfses= RUNMALLOC(sizeof(int) * counter);
347     for(i=0; i<obj->numotds; i++){
348       for(j=0; j<obj->otds[i]->numenterflags; j++){
349         oldflag=obj->otds[i]->enterflags[j];
350         flag=ormask|oldflag;
351         flag&=andmask;
352         obj->exitfses[j+offset]=flag;
353       }
354       offset+=obj->otds[i]->numenterflags;
355     }
356     enqueueoptional(ptr);
357   }
358   else
359 #endif
360     {
361     flag&=andmask;
362     flagbody(ptr, flag);
363     }
364 }
365  
366 void intflagorand(void * ptr, int ormask, int andmask) {
367   int oldflag=((int *)ptr)[1];
368   int flag=ormask|oldflag;
369 #ifdef OPTIONAL
370   struct ___Object___ * obj = (struct ___Object___ *)ptr;
371   if(obj->failedstatus==1) {/*store the information about exitfses*/
372     int i,j,counter=0, offset=0;
373     for(i=0; i<obj->numotds; i++) {
374       counter+=obj->otds[i]->numenterflags;
375     }
376     obj->numexitfses=counter;
377     if(obj->exitfses!=NULL) 
378       RUNFREE(obj->exitfses);
379     obj->exitfses= RUNMALLOC(sizeof(int) * counter);
380     for(i=0; i<obj->numotds; i++) {
381       for(j=0; j<obj->otds[i]->numenterflags; j++){
382         oldflag=obj->otds[i]->enterflags[j];
383         flag=ormask|oldflag;
384         flag&=andmask;
385         obj->exitfses[j+offset]=flag;
386       }
387       offset+=obj->otds[i]->numenterflags;
388     }
389     enqueueoptional(ptr);
390   }
391   else
392 #endif
393     {
394     flag&=andmask;
395     if (flag==oldflag) /* Don't do anything */
396       return;
397     else flagbody(ptr, flag);
398     }
399 }
400
401 void flagorandinit(void * ptr, int ormask, int andmask) {
402   int oldflag=((int *)ptr)[1];
403   int flag=ormask|oldflag;
404 #ifdef OPTIONAL
405   struct ___Object___ * obj = (struct ___Object___ *)ptr;
406   if(obj->failedstatus==1){/*store the information about exitfses*/
407     int i,j,counter=0, offset=0;
408     for(i=0; i<obj->numotds; i++){
409       counter+=obj->otds[i]->numenterflags;
410     }
411     obj->numexitfses=counter;
412     if(obj->exitfses!=NULL) RUNFREE(obj->exitfses);
413     obj->exitfses= RUNMALLOC(sizeof(int) * counter);
414     for(i=0; i<obj->numotds; i++){
415       for(j=0; j<obj->otds[i]->numenterflags; j++){
416         oldflag=obj->otds[i]->enterflags[j];
417         flag=ormask|oldflag;
418         flag&=andmask;
419         obj->exitfses[j+offset]=flag;
420       }
421       offset+=obj->otds[i]->numenterflags;
422     }
423     enqueueoptional(ptr);
424   }
425   else
426 #endif
427     {
428     flag&=andmask;
429     flagbody(ptr,flag);
430     }
431 }
432
433 #ifdef OPTIONAL
434  removeoptionalfromqueues(int hashcode, struct ___Object___ * currobj, struct parameterwrapper * flagptr){/*find a better way to free the useless instances of the object*/
435    while(flagptr!=NULL) {
436      struct ___Object___ *temp=NULL;
437      struct parameterwrapper *ptr;
438      struct ObjectNode * node = flagptr->objectset->listhead;
439      while(node!=NULL){
440        temp=(struct ___Object___ *)node->key;
441        if(temp->failedstatus==1 && temp->hashcode==currobj->hashcode){
442          if(temp!=currobj){
443            ObjectHashremove(flagptr->objectset, (int)temp);//remove from wrapper
444            //delete the fields that wont be removed by the GC.
445            if(temp->exitfses!=NULL) RUNFREE(temp->exitfses);
446            if(temp->otds!=NULL) RUNFREE(temp->otds);
447            goto nextwrapper;
448          }
449          else{
450            //remove from wrapper
451            ObjectHashremove(flagptr->objectset, (int)temp);
452            goto nextwrapper;
453          }
454        }
455        node=node->next;
456      }
457    nextwrapper:
458      ;
459      flagptr=flagptr->next;
460    }
461  } 
462 #endif
463  
464  void flagbody(struct ___Object___ *ptr, int flag) {
465    struct parameterwrapper *flagptr=(struct parameterwrapper *)ptr->flagptr;
466    ptr->flag=flag;
467    
468    /*Remove object from all queues */
469    while(flagptr!=NULL) {
470      struct parameterwrapper *next;
471      struct ___Object___ * tag=ptr->___tags___;
472      int FIXME;
473      ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, &FIXME);
474      ObjectHashremove(flagptr->objectset, (int)ptr);
475      flagptr=next;
476    }
477    
478    {
479      struct QueueItem *tmpptr;
480      struct parameterwrapper * parameter=objectqueues[ptr->type];
481      int i;
482      struct parameterwrapper * prevptr=NULL;
483      struct ___Object___ *tagptr=ptr->___tags___;
484      
485      /* Outer loop iterates through all parameter queues an object of
486         this type could be in.  */
487      
488      while(parameter!=NULL) {
489        /* Check tags */
490        if (parameter->numbertags>0) {
491          if (tagptr==NULL)
492            goto nextloop;//that means the object has no tag but that param needs tag
493          else if(tagptr->type==TAGTYPE) {//one tag
494            struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
495            for(i=0;i<parameter->numbertags;i++) {
496              //slotid is parameter->tagarray[2*i];
497              int tagid=parameter->tagarray[2*i+1];
498              if (tagid!=tagptr->flag)
499                goto nextloop; /*We don't have this tag */         
500            }
501          } else {//multiple tags
502            struct ArrayObject * ao=(struct ArrayObject *) tagptr;
503            for(i=0;i<parameter->numbertags;i++) {
504              //slotid is parameter->tagarray[2*i];
505              int tagid=parameter->tagarray[2*i+1];
506              int j;
507              for(j=0;j<ao->___cachedCode___;j++) {
508                if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, i)->flag)
509                  goto foundtag;
510              }
511              goto nextloop;
512            foundtag:
513              ;
514            }
515          }
516        }
517        
518        /* Check flags */
519        for(i=0;i<parameter->numberofterms;i++) {
520          int andmask=parameter->intarray[i*2];
521          int checkmask=parameter->intarray[i*2+1];
522          if ((flag&andmask)==checkmask) {
523            enqueuetasks(parameter, prevptr, ptr);
524            prevptr=parameter;
525            break;
526          }
527        }
528      nextloop:
529        parameter=parameter->next;
530      }
531      ptr->flagptr=prevptr;
532    }
533  }
534  
535 #ifdef OPTIONAL
536  
537  void enqueueoptional(struct ___Object___ * currobj){
538    
539    struct classanalysiswrapper * classwrapper=NULL; 
540    struct fsanalysiswrapper * fswrapper=NULL;
541    int counter=0;
542    int numoptionaltaskdescriptors=0;
543    struct optionaltaskdescriptor *** optionaltaskdescriptorarray=NULL;
544    struct fsanalysiswrapper ** goodfswrappersarray=NULL;
545    int numgoodfswrappers=0;
546 #ifdef DEBUG
547    if(currobj->numexitfses==0)
548      printf("Handling failed object\nType : %i\nFlag : 0x%x\n", currobj->type, currobj->flag);
549    else{
550      printf("Handling failed object\nType : %i\n", currobj->type);
551      int fscount=0;
552      for(fscount=0; fscount<currobj->numexitfses; fscount++)
553        printf("Flag : 0x%x\n", currobj->exitfses[fscount]);
554    }
555    struct ___Object___ * tagptr = currobj->___tags___;
556    if(tagptr!=NULL){
557      if(tagptr->type==TAGTYPE) {
558        printf("Tag : %i\n", tagptr->flag);}
559      else {
560        struct ArrayObject * ao=(struct ArrayObject *) tagptr;
561        int numbertags = ao->___length___;
562        for(counter=0; counter<numbertags; counter++){
563          printf("Tag : %i\n", ao[counter].flag);
564        } 
565      }
566    }
567 #endif    
568    /*set the object as failed*/
569    currobj->failedstatus = 1;
570    
571    /*test what optionaltaskdescriptors are available,
572      find the class corresponding*/
573    
574    for(counter = 0; counter<numclasses; counter++){
575      classwrapper = classanalysiswrapperarray[counter];
576      if(classwrapper == NULL){
577        fprintf(stderr, "ERROR : \"struct classanalysiswrapper * classwraper\" is a NULL pointer\n, Analysis has been skipped, check Runtime/task.c, function enqueueoptional\n");
578        goto nothingtodo;
579      }
580      /*check object type*/
581      if( currobj->type == classwrapper->type)
582        goto classchecked;
583    }
584 #ifdef DEBUG
585    printf("No task will use this parameter as optional\n");
586 #endif
587    removeoptionalfromqueues(currobj->hashcode,currobj, objectqueues[currobj->type]);
588    goto nothingtodo;
589  classchecked:
590    ;
591 #ifdef DEBUG
592    printf("Found the class, search through fses\n");
593 #endif        
594    /*search through fses*/
595    goodfswrappersarray = RUNMALLOC(sizeof(struct fsanalysiswrapper *) * classwrapper->numfsanalysiswrappers); /*max number of good fswrappers*/
596    if(goodfswrappersarray == NULL){
597      fprintf(stderr, "ERROR : \"struct fsanalysiswrapper ** goodfswrappersarray\" is a NULL pointer\n, Analysis has been skipped, check Runtime/task.c, function enqueueoptional\n");
598      removeoptionalfromqueues(currobj->hashcode,currobj, objectqueues[currobj->type]);
599      goto nothingtodo;
600    }
601    for(counter = 0; counter<classwrapper->numfsanalysiswrappers; counter++){
602      /*test the FS of the object (include flags and tags)*/
603      fswrapper = classwrapper->fsanalysiswrapperarray[counter];
604      if(fswrapper == NULL){
605        fprintf(stderr, "ERROR : struct fsanalysiswrapper * is a NULL pointer\n, Analysis has been skipped, check Runtime/task.c, function enqueueoptional\n");
606        removeoptionalfromqueues(currobj->hashcode,currobj, objectqueues[currobj->type]);
607        goto nothingtodo;
608      }
609      /*check tags*/
610      struct ___Object___ * tagptr = currobj->___tags___;
611      if(fswrapper->numtags>0){
612        if (tagptr==NULL)
613          goto nextloop;//that means the object has no tag but that param needs tag
614        else if(tagptr->type==TAGTYPE) {//one tag
615          if(fswrapper->numtags!=1) goto nextloop;//we don't have the right number of tags
616          struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
617          if (fswrapper->tags[0]!=tagptr->flag)
618            goto nextloop; 
619        }          
620        else {//multiple tags
621          struct ArrayObject * ao=(struct ArrayObject *) tagptr;
622          int tag_counter=0;
623          if(ao->___length___!=fswrapper->numtags) goto nextloop;//we don't have the right number of tags
624          for(tag_counter=0;tag_counter<fswrapper->numtags;tag_counter++) {
625            int tagid=fswrapper->tags[tag_counter];
626            int j;
627            for(j=0;j<ao->___cachedCode___;j++) {
628              if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, tag_counter)->flag)
629                goto foundtag;
630            }
631            goto nextloop;
632          foundtag:
633            ;                  ;
634          }
635        }
636      }
637      
638      //check flags
639      if(currobj->numexitfses==0){/*first time the method is invoqued*/
640        if( currobj->flag == fswrapper->flags){
641          int otdc;
642          optionaltaskdescriptorarray = RUNMALLOC(sizeof(struct optionaltaskdescriptor **) * fswrapper->numoptionaltaskdescriptors);
643          numoptionaltaskdescriptors = fswrapper->numoptionaltaskdescriptors;
644          for(otdc = 0; otdc<fswrapper->numoptionaltaskdescriptors; otdc++){
645            struct optionaltaskdescriptor ** tmpptr = RUNMALLOC(sizeof(struct optionaltaskdescriptor *));
646            tmpptr[0] = fswrapper->optionaltaskdescriptorarray[otdc];
647            optionaltaskdescriptorarray[otdc] = tmpptr;
648          }
649          numgoodfswrappers=1;
650          goto fschecked;
651        }
652      }
653      else if(currobj->numexitfses==1){/*one fs exit*/
654        if(currobj->exitfses[0] == fswrapper->flags){
655          int otdc;
656          optionaltaskdescriptorarray = RUNMALLOC(sizeof(struct optionaltaskdescriptor **) * fswrapper->numoptionaltaskdescriptors);
657          numoptionaltaskdescriptors = fswrapper->numoptionaltaskdescriptors;
658          for(otdc = 0; otdc<fswrapper->numoptionaltaskdescriptors; otdc++){
659            struct optionaltaskdescriptor ** tmpptr = RUNMALLOC(sizeof(struct optionaltaskdescriptor *));
660            tmpptr[0] = fswrapper->optionaltaskdescriptorarray[otdc];
661            optionaltaskdescriptorarray[otdc] = tmpptr;
662          }
663          numgoodfswrappers=1;
664          goto fschecked;
665        }
666      }
667      else{
668        int fscount=0;
669        for(fscount=0; fscount<currobj->numexitfses; fscount++){
670          
671          if( currobj->exitfses[fscount] == fswrapper->flags ){/*see if the fswraper correspond to one of the fses*/
672            goodfswrappersarray[numgoodfswrappers]=fswrapper;
673            numgoodfswrappers++;
674          }
675        }
676        if(counter==classwrapper->numfsanalysiswrappers-1) goto makeintersection; /*last fswrapper*/
677      }
678    nextloop:
679      ;
680    }
681  nofs:
682    ;
683 #ifdef DEBUG
684    printf("FS not found, Nothing more to do\n");
685 #endif
686    removeoptionalfromqueues(currobj->hashcode,currobj, objectqueues[currobj->type]);
687    goto nothingtodo;
688  makeintersection:
689    ;
690    if(numgoodfswrappers==0 || numgoodfswrappers==1) goto nofs; /*nothing has been found, we expect more than one wrapper for multiple flags*/
691    optionaltaskdescriptorarray = makeintersectionotd(numgoodfswrappers, goodfswrappersarray, &numoptionaltaskdescriptors);
692    if(optionaltaskdescriptorarray==NULL){
693      fprintf(stderr, "ERROR : struct optionaltaskdescriptor ** is a NULL pointer\n, Analysis has been skipped, check Runtime/task.c, function enqueueoptional\n");
694      goto nothingtodo;
695    }
696    
697   fschecked:
698    ;
699 #ifdef DEBUG
700    printf("FS(es) found, intersection created, %i potential tasks :\n", numoptionaltaskdescriptors);
701    
702    
703    /*find the parameterwrapper corresponding to the potential task*/
704    for(counter = 0; counter<numoptionaltaskdescriptors; counter++){
705      struct optionaltaskdescriptor ** tmpptr = optionaltaskdescriptorarray[counter];
706      printf("Task %s\n", tmpptr[0]->task->name);
707    }
708    
709 #endif
710    {            
711      struct parameterwrapper * prevptr = NULL;
712      struct parameterwrapper * flagptr = objectqueues[currobj->type];
713      removeoptionalfromqueues(currobj->hashcode,currobj, flagptr);
714      /*process for each otd*/
715      for(counter = 0; counter<numoptionaltaskdescriptors; counter++){
716        struct parameterwrapper * parameter = objectqueues[currobj->type];
717        struct optionaltaskdescriptor ** tmpptr = optionaltaskdescriptorarray[counter];
718        struct optionaltaskdescriptor * currotd = tmpptr[0];
719        int otd_counter=0;
720        while(parameter->task != currotd->task)
721          parameter=parameter->next;
722 #ifdef DEBUG
723        printf("found parameterwrapper for task : %s\n", parameter->task->name);
724 #endif
725        
726        struct ___Object___ * newobj = RUNMALLOC(sizeof(struct ___Object___));
727        (*newobj)=(*currobj);
728        newobj->numotds=numgoodfswrappers;
729        newobj->otds=RUNMALLOC(sizeof(struct optionaltaskdescriptor *) * numgoodfswrappers);
730        for(otd_counter=0; otd_counter<numgoodfswrappers; otd_counter++){
731          newobj->otds[otd_counter]=tmpptr[otd_counter];
732        }
733        enqueuetasks(parameter, prevptr, newobj);
734        prevptr = parameter;
735        
736      nextotd:
737        ;
738      }
739      
740    }
741  nothingtodo:
742    
743    /*if(currobj->exitfses!=NULL) RUNFREE(currobj->exitfses);
744      if(currobj->otds!=NULL) RUNFREE(currobj->otds);*///there has been a problem just before the program exit, maybe due to the GC ?
745    RUNFREE(optionaltaskdescriptorarray);
746    ;
747  }
748
749  /*we need to check if the object is optional, in this case, test the predicate*/
750  /*here is the code for predicate checking*/
751  /*The code has not been tested. I don't even know if it is working or efficient but it is a lead...
752    if(currotd->numpredicatemembers == 0){
753    printf("this task can be fired\n");
754    goto enqueuetask;
755    }
756    else{
757    int pred_counter;
758    int predicatetrue = 0;
759    for(pred_counter = 0; pred_counter<currotd->numpredicatemembers; pred_counter++){
760    struct predicatemember * currpred = currotd->predicatememberarray[pred_counter];
761    printf("predicate type : %i\n", currpred->type);
762    
763    //test if the predicate member is true
764    struct parameterwrapper * paramwrapper = objectqueues[currpred->type];
765    while(paramwrapper!=NULL){
766    struct ObjectIterator * it = allocateObjectIterator(paramwrapper->objectset->listhead);
767    do{
768    struct ___Object___ * obj = (struct ___Object___ *)Objkey(it);
769    printf("obj type : %i\n", obj->type);
770    if(obj->type == currpred->type){
771    //test the predicate
772    printf("predicate to test\n");
773    //only if good
774    goto enqueuetask;
775    }
776    Objnext(it);
777    }while(ObjhasNext(it));
778    paramwrapper=paramwrapper->next;
779    }
780    printf("not the good predicate");
781    //goto endanalysis
782    }
783    //the predicate members have to be all true
784    }*/
785  
786 #endif
787  
788  void enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr) {
789   void * taskpointerarray[MAXTASKPARAMS];
790   int j;
791   int numparams=parameter->task->numParameters;
792   int numiterators=parameter->task->numTotal-1;
793
794   struct taskdescriptor * task=parameter->task;
795   
796   ObjectHashadd(parameter->objectset, (int) ptr, (int) prevptr, 0);//this add the object to parameterwrapper
797   
798   /* Add enqueued object to parameter vector */
799   taskpointerarray[parameter->slot]=ptr;
800
801   /* Reset iterators */
802   for(j=0;j<numiterators;j++) {
803     toiReset(&parameter->iterators[j]);
804   }
805
806   /* Find initial state */
807   for(j=0;j<numiterators;j++) {
808   backtrackinit:
809     if(toiHasNext(&parameter->iterators[j], taskpointerarray))
810       toiNext(&parameter->iterators[j], taskpointerarray);
811     else if (j>0) {
812       /* Need to backtrack */
813       toiReset(&parameter->iterators[j]);
814       j--;
815       goto backtrackinit;
816     } else {
817       /* Nothing to enqueue */
818       return;
819     }
820   }
821
822   
823   while(1) {
824     /* Enqueue current state */
825     int launch = 0;
826     struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
827     tpd->task=task;
828     tpd->numParameters=numiterators+1;
829     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
830     for(j=0;j<=numiterators;j++){
831 #ifdef OPTIONAL
832 #ifdef DEBUG
833       struct ___Object___ * obj = (struct ___Object___ *)taskpointerarray[j];
834       if(obj->failedstatus==1)
835         printf("parameter %i used as optional for task %s\n", obj->type, task->name);
836 #endif
837 #endif
838       tpd->parameterArray[j]=taskpointerarray[j];//store the actual parameters
839     }
840     /* Enqueue task */
841     if ((!gencontains(failedtasks, tpd)&&!gencontains(activetasks,tpd))) {
842       genputtable(activetasks, tpd, tpd);
843     } else {
844       RUNFREE(tpd->parameterArray);
845       RUNFREE(tpd);
846     }
847     
848     /* This loop iterates to the next parameter combination */
849     if (numiterators==0)
850       return;
851
852     for(j=numiterators-1; j<numiterators;j++) {
853     backtrackinc:
854       if(toiHasNext(&parameter->iterators[j], taskpointerarray))
855         toiNext(&parameter->iterators[j], taskpointerarray);
856       else if (j>0) {
857         /* Need to backtrack */
858         toiReset(&parameter->iterators[j]);
859         j--;
860         goto backtrackinc;
861       } else {
862         /* Nothing more to enqueue */
863         return;
864       }
865     }
866   }
867 }
868  
869 /* Handler for signals. The signals catch null pointer errors and
870    arithmatic errors. */
871
872 void myhandler(int sig, siginfo_t *info, void *uap) {
873   sigset_t toclear;
874 #ifdef DEBUG
875   printf("sig=%d\n",sig);
876   printf("signal\n");
877 #endif
878   sigemptyset(&toclear);
879   sigaddset(&toclear, sig);
880   sigprocmask(SIG_UNBLOCK, &toclear,NULL); 
881   longjmp(error_handler,1);
882 }
883
884 fd_set readfds;
885 int maxreadfd;
886 struct RuntimeHash *fdtoobject;
887
888 void addreadfd(int fd) {
889   if (fd>=maxreadfd)
890     maxreadfd=fd+1;
891   FD_SET(fd, &readfds);
892 }
893
894 void removereadfd(int fd) {
895   FD_CLR(fd, &readfds);
896   if (maxreadfd==(fd+1)) {
897     maxreadfd--;
898     while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
899       maxreadfd--;
900   }
901 }
902
903 #ifdef PRECISE_GC
904 #define OFFSET 2
905 #else
906 #define OFFSET 0
907 #endif
908
909 void executetasks() {
910   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
911
912   /* Set up signal handlers */
913   struct sigaction sig;
914   sig.sa_sigaction=&myhandler;
915   sig.sa_flags=SA_SIGINFO;
916   sigemptyset(&sig.sa_mask);
917
918   /* Catch bus errors, segmentation faults, and floating point exceptions*/
919   sigaction(SIGBUS,&sig,0);
920   sigaction(SIGSEGV,&sig,0);
921   sigaction(SIGFPE,&sig,0);
922   sigaction(SIGPIPE,&sig,0);
923
924   /* Zero fd set */
925   FD_ZERO(&readfds);
926   maxreadfd=0;
927   fdtoobject=allocateRuntimeHash(100);
928
929   /* Map first block of memory to protected, anonymous page */
930   mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
931
932   newtask:
933   while((hashsize(activetasks)>0)||(maxreadfd>0)) {
934
935     /* Check if any filedescriptors have IO pending */
936     if (maxreadfd>0) {
937       int i;
938       struct timeval timeout={0,0};
939       fd_set tmpreadfds;
940       int numselect;
941       tmpreadfds=readfds;
942       numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
943       if (numselect>0) {
944         /* Process ready fd's */
945         int fd;
946         for(fd=0;fd<maxreadfd;fd++) {
947           if (FD_ISSET(fd, &tmpreadfds)) {
948             /* Set ready flag on object */
949             void * objptr;
950             //      printf("Setting fd %d\n",fd);
951             if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
952               intflagorand(objptr,1,0xFFFFFFFF); /* Set the first flag to 1 */
953             }
954           }
955         }
956       }
957     }
958
959     /* See if there are any active tasks */
960     if (hashsize(activetasks)>0) {
961       int i;
962       currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
963       genfreekey(activetasks, currtpd);
964       
965       /* Check if this task has failed, allow a task that contains optional objects to fire */
966       if (gencontains(failedtasks, currtpd)) {
967         // Free up task parameter descriptor
968         RUNFREE(currtpd->parameterArray);
969         RUNFREE(currtpd);
970         goto newtask;
971       }
972       int numparams=currtpd->task->numParameters;
973       int numtotal=currtpd->task->numTotal;
974       
975       /* Make sure that the parameters are still in the queues */
976       for(i=0;i<numparams;i++) {
977         void * parameter=currtpd->parameterArray[i];
978         struct parameterdescriptor * pd=currtpd->task->descriptorarray[i];
979         struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
980         int j;
981         /* Check that object is still in queue */
982 #ifdef OPTIONAL
983         struct ___Object___ * obj = (struct ___Object___ *)parameter;
984         if(obj->failedstatus==1){
985           struct ___Object___ *temp=NULL;
986           struct parameterwrapper * ptr;
987           struct ObjectNode * node = pw->objectset->listhead;
988           while(node!=NULL){
989             temp=(struct ___Object___ *)node->key;
990             if(temp->failedstatus==1 && temp->hashcode==obj->hashcode){
991               if(temp==obj)
992                 goto parameterpresent;
993             }
994             node=node->next;
995           }
996           RUNFREE(currtpd->parameterArray);
997           RUNFREE(currtpd);
998           goto newtask;
999         }
1000         else
1001 #endif
1002         {
1003           if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
1004             RUNFREE(currtpd->parameterArray);
1005             RUNFREE(currtpd);
1006             goto newtask;
1007           }
1008         }
1009       parameterpresent:
1010         ;
1011         /* Check that object still has necessary tags */
1012         for(j=0;j<pd->numbertags;j++) {
1013           int slotid=pd->tagarray[2*j]+numparams;
1014           struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
1015           if (!containstag(parameter, tagd)) {
1016             RUNFREE(currtpd->parameterArray);
1017             RUNFREE(currtpd);
1018             goto newtask;
1019           }
1020         }
1021         
1022         taskpointerarray[i+OFFSET]=parameter;
1023       }
1024       /* Copy the tags */
1025       for(;i<numtotal;i++) {
1026         taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
1027       }
1028
1029       {
1030         /* Checkpoint the state */
1031         forward=allocateRuntimeHash(100);
1032         reverse=allocateRuntimeHash(100);
1033         void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
1034         int x;
1035         if (x=setjmp(error_handler)) {
1036           int counter;
1037           /* Recover */
1038 #ifdef DEBUG
1039           printf("Fatal Error=%d, Recovering!\n",x);
1040 #endif
1041           genputtable(failedtasks,currtpd,currtpd);
1042           restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
1043
1044 #ifdef OPTIONAL
1045 #ifdef DEBUG      
1046           printf("%i object(s) restored\n", currtpd->task->numParameters);
1047 #endif 
1048           
1049           for(counter=0; counter<currtpd->task->numParameters; counter++){
1050             //remove the object from the previous parameterwrapper (maybe not necessary)
1051             //do a new instance of the object. It allows the restored object to be used by other tasks as a non optional arg.
1052             struct ___Object___ * currobj = RUNMALLOC(sizeof(struct ___Object___));
1053             (*currobj)=(*(struct ___Object___ *)currtpd->parameterArray[counter]);
1054             currobj->numexitfses = 0;
1055             currobj->exitfses = NULL;
1056             currobj->otds=NULL;
1057             currobj->hashcode=(int)currobj;
1058             enqueueoptional( currobj );
1059           }
1060 #endif
1061           freeRuntimeHash(forward);
1062           freeRuntimeHash(reverse);
1063           freemalloc();
1064           forward=NULL;
1065           reverse=NULL;
1066         } else {
1067           if (injectfailures) {
1068             if ((((double)random())/RAND_MAX)<failurechance) {
1069               printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
1070               longjmp(error_handler,10);
1071             }
1072           }
1073           /* Actually call task */
1074 #ifdef PRECISE_GC
1075           ((int *)taskpointerarray)[0]=currtpd->task->numParameters;
1076           taskpointerarray[1]=NULL;
1077 #endif
1078           if(debugtask){
1079             printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
1080             ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
1081             printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
1082           } else
1083             ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
1084             
1085           freeRuntimeHash(forward);
1086           freeRuntimeHash(reverse);
1087           freemalloc();
1088           // Free up task parameter descriptor
1089           RUNFREE(currtpd->parameterArray);
1090           RUNFREE(currtpd);
1091           forward=NULL;
1092           reverse=NULL;
1093         }
1094       }
1095     }
1096   }
1097 }
1098  
1099 /* This function processes an objects tags */
1100 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
1101   int i;
1102   
1103   for(i=0;i<pd->numbertags;i++) {
1104     int slotid=pd->tagarray[2*i];
1105     int tagid=pd->tagarray[2*i+1];
1106     
1107     if (statusarray[slotid+numparams]==0) {
1108       parameter->iterators[*iteratorcount].istag=1;
1109       parameter->iterators[*iteratorcount].tagid=tagid;
1110       parameter->iterators[*iteratorcount].slot=slotid+numparams;
1111       parameter->iterators[*iteratorcount].tagobjectslot=index;
1112       statusarray[slotid+numparams]=1;
1113       (*iteratorcount)++;
1114     }
1115   }
1116 }
1117
1118
1119 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
1120   int i;
1121   int tagcount=0;
1122   struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
1123
1124   parameter->iterators[*iteratorcount].istag=0;
1125   parameter->iterators[*iteratorcount].slot=index;
1126   parameter->iterators[*iteratorcount].objectset=objectset;
1127   statusarray[index]=1;
1128
1129   for(i=0;i<pd->numbertags;i++) {
1130     int slotid=pd->tagarray[2*i];
1131     int tagid=pd->tagarray[2*i+1];
1132     if (statusarray[slotid+numparams]!=0) {
1133       /* This tag has already been enqueued, use it to narrow search */
1134       parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
1135       tagcount++;
1136     }
1137   }
1138   parameter->iterators[*iteratorcount].numtags=tagcount;
1139
1140   (*iteratorcount)++;
1141 }
1142
1143 /* This function builds the iterators for a task & parameter */
1144
1145 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
1146   int statusarray[MAXTASKPARAMS];
1147   int i;
1148   int numparams=task->numParameters;
1149   int iteratorcount=0;
1150   for(i=0;i<MAXTASKPARAMS;i++) statusarray[i]=0;
1151
1152   statusarray[index]=1; /* Initial parameter */
1153   /* Process tags for initial iterator */
1154   
1155   processtags(task->descriptorarray[index], index, parameter, & iteratorcount, statusarray, numparams);
1156   
1157   while(1) {
1158   loopstart:
1159     /* Check for objects with existing tags */
1160     for(i=0;i<numparams;i++) {
1161       if (statusarray[i]==0) {
1162         struct parameterdescriptor *pd=task->descriptorarray[i];
1163         int j;
1164         for(j=0;j<pd->numbertags;j++) {
1165           int slotid=pd->tagarray[2*j];
1166           if(statusarray[slotid+numparams]!=0) {
1167             processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
1168             processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
1169             goto loopstart;
1170           }
1171         }
1172       }
1173     }
1174
1175     /* Next do objects w/ unbound tags*/
1176
1177     for(i=0;i<numparams;i++) {
1178       if (statusarray[i]==0) {
1179         struct parameterdescriptor *pd=task->descriptorarray[i];
1180         if (pd->numbertags>0) {
1181           processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
1182           processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
1183           goto loopstart;
1184         }
1185       }
1186     }
1187
1188     /* Nothing with a tag enqueued */
1189
1190     for(i=0;i<numparams;i++) {
1191       if (statusarray[i]==0) {
1192         struct parameterdescriptor *pd=task->descriptorarray[i];
1193         processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
1194         processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
1195         goto loopstart;
1196       }
1197     }
1198
1199     /* Nothing left */
1200     return;
1201   }
1202 }
1203
1204
1205  
1206
1207 /* This function processes the task information to create queues for
1208    each parameter type. */
1209
1210 void processtasks() {
1211   int i;
1212   for(i=0;i<numtasks;i++) {
1213     struct taskdescriptor * task=taskarray[i];
1214     int j;
1215
1216     for(j=0;j<task->numParameters;j++) {
1217       struct parameterdescriptor *param=task->descriptorarray[j];
1218       struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
1219       struct parameterwrapper ** ptr=&objectqueues[param->type];
1220
1221       param->queue=parameter;
1222       parameter->objectset=allocateObjectHash(10);
1223       parameter->numberofterms=param->numberterms;
1224       parameter->intarray=param->intarray;
1225       parameter->numbertags=param->numbertags;
1226       parameter->tagarray=param->tagarray;
1227       parameter->task=task;
1228       /* Link new queue in */
1229       while((*ptr)!=NULL)
1230         ptr=&((*ptr)->next);
1231       (*ptr)=parameter;
1232     }
1233
1234     /* Build iterators for parameters */
1235     for(j=0;j<task->numParameters;j++) {
1236       struct parameterdescriptor *param=task->descriptorarray[j];
1237       struct parameterwrapper *parameter=param->queue;      
1238       parameter->slot=j;
1239       builditerators(task, j, parameter);
1240     }
1241   }
1242 }
1243
1244 void toiReset(struct tagobjectiterator * it) {
1245   if (it->istag) {
1246     it->tagobjindex=0;
1247   } else if (it->numtags>0) {
1248     it->tagobjindex=0;
1249   } else {
1250     ObjectHashiterator(it->objectset, &it->it);
1251   }
1252 }
1253
1254 int toiHasNext(struct tagobjectiterator *it, void ** objectarray) {
1255   if (it->istag) {
1256     /* Iterate tag */
1257     /* Get object with tags */
1258     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1259     struct ___Object___ *tagptr=obj->___tags___;
1260     if (tagptr->type==TAGTYPE) {
1261       if ((it->tagobjindex==0)&& /* First object */
1262           (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
1263         return 1;
1264       else
1265         return 0;
1266     } else {
1267       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1268       int tagindex=it->tagobjindex;
1269       for(;tagindex<ao->___cachedCode___;tagindex++) {
1270         struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
1271         if (td->flag==it->tagid) {
1272           it->tagobjindex=tagindex; /* Found right type of tag */
1273           return 1;
1274         }
1275       }
1276       return 0;
1277     }
1278   } else if (it->numtags>0) {
1279     /* Use tags to locate appropriate objects */
1280     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1281     struct ___Object___ *objptr=tag->flagptr;
1282     int i;
1283     if (objptr->type!=OBJECTARRAYTYPE) {
1284       if (it->tagobjindex>0)
1285         return 0;
1286       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1287         return 0;
1288       for(i=1;i<it->numtags;i++) {
1289         struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1290         if (!containstag(objptr,tag2))
1291           return 0;
1292       }
1293       return 1;
1294     } else {
1295       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1296       int tagindex;
1297       int i;
1298       for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
1299         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
1300         if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1301           continue;
1302         for(i=1;i<it->numtags;i++) {
1303           struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1304           if (!containstag(objptr,tag2))
1305             goto nexttag;
1306         }
1307         return 1;
1308       nexttag:
1309         ;
1310       }
1311       it->tagobjindex=tagindex;
1312       return 0;
1313     }
1314   } else {
1315     return ObjhasNext(&it->it);
1316   }
1317 }
1318
1319 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
1320   int j;
1321   struct ___Object___ * objptr=tag->flagptr;
1322   if (objptr->type==OBJECTARRAYTYPE) {
1323     struct ArrayObject *ao=(struct ArrayObject *)objptr;
1324     for(j=0;j<ao->___cachedCode___;j++) {
1325       if (ptr==ARRAYGET(ao, struct ___Object___*, j))
1326         return 1;
1327     }
1328     return 0;
1329   } else
1330     return objptr==ptr;
1331 }
1332
1333 void toiNext(struct tagobjectiterator *it , void ** objectarray) {
1334   /* hasNext has all of the intelligence */
1335   if(it->istag) {
1336     /* Iterate tag */
1337     /* Get object with tags */
1338     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1339     struct ___Object___ *tagptr=obj->___tags___;
1340     if (tagptr->type==TAGTYPE) {
1341       it->tagobjindex++;
1342       objectarray[it->slot]=tagptr;
1343     } else {
1344       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1345       objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
1346     }
1347   } else if (it->numtags>0) {
1348     /* Use tags to locate appropriate objects */
1349     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1350     struct ___Object___ *objptr=tag->flagptr;
1351     if (objptr->type!=OBJECTARRAYTYPE) {
1352       it->tagobjindex++;
1353       objectarray[it->slot]=objptr;
1354     } else {
1355       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1356       objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
1357     }
1358   } else {
1359     /* Iterate object */
1360     objectarray[it->slot]=(void *)Objkey(&it->it);
1361     Objnext(&it->it);
1362   }
1363 }
1364
1365
1366 #endif