Update copyright to LGPL on all files
[dyninst.git] / dynutil / h / Annotatable.h
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #ifndef __ANNOTATABLE_H__
33 #define __ANNOTATABLE_H__
34
35 #if defined (MSC_VER)
36 #define DYN_DETAIL_BOOST_NO_INTRINSIC_WCHAR_T 1
37 #endif
38 #include <vector>
39 #include <map>
40 #include <typeinfo>
41 #include <string>
42 #include <string.h> // for strrchr()
43 #include <assert.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include "dyntypes.h"
47 #include "util.h"
48 #include "dyn_detail/boost/type_traits/is_base_of.hpp"
49 #include "dyn_detail/boost/type_traits/is_pointer.hpp"
50 #include "dyn_detail/boost/type_traits/remove_pointer.hpp"
51 #define serialize_printf serializer_printf
52
53 namespace Dyninst
54 {
55
56
57 COMMON_EXPORT int serializer_printf(const char *format, ...);
58 COMMON_EXPORT int annotatable_printf(const char *format, ...);
59 COMMON_EXPORT bool annotation_debug_flag();
60
61 typedef unsigned short AnnotationClassID;
62 typedef bool (*anno_cmp_func_t)(void *, void*);
63
64 extern int newAnnotationClass();
65 extern bool void_ptr_cmp_func(void *, void *);
66
67 class SerializerBase;
68 class Serializable;
69 typedef Serializable * (*ser_func_t) (void *, SerializerBase *, const char *);
70 COMMON_EXPORT Serializable * ser_func_wrapper(void *it, SerializerBase *sb,  const char *tag);
71
72 class AnnotationClassBase
73 {
74         friend class Serializable;
75    private:
76       static std::vector<AnnotationClassBase *> *annotation_types;
77       static dyn_hash_map<std::string, AnnotationClassID> *annotation_ids_by_name;
78 #if 0
79           COMMON_EXPORT static void clearAnnotationIDMap();
80 #endif
81       anno_cmp_func_t cmp_func;
82       AnnotationClassID id;
83       std::string name;
84
85    protected:
86
87           ser_func_t serialize_func;
88
89       COMMON_EXPORT AnnotationClassBase(std::string n, 
90             anno_cmp_func_t cmp_func_ = NULL, ser_func_t sf_ = NULL);
91
92           COMMON_EXPORT virtual ~AnnotationClassBase(); 
93
94    public:
95
96       COMMON_EXPORT static AnnotationClassBase *findAnnotationClass(unsigned int id);
97       COMMON_EXPORT static void dumpAnnotationClasses();
98
99       COMMON_EXPORT AnnotationClassID getID() { return id; }
100       COMMON_EXPORT std::string &getName() {return name;}
101       COMMON_EXPORT anno_cmp_func_t getCmpFunc() {return cmp_func;}
102           COMMON_EXPORT ser_func_t getSerializeFunc() {return serialize_func;}
103           COMMON_EXPORT virtual const char *getTypeName() = 0;
104           COMMON_EXPORT virtual void *allocate() = 0;
105 };
106
107 template <class T> 
108 class AnnotationClass : public AnnotationClassBase {
109    public:
110
111           AnnotationClass(std::string n, 
112                           anno_cmp_func_t cmp_func_ = NULL, 
113                           ser_func_t s = NULL) :
114                   AnnotationClassBase(n, cmp_func_, s)
115           {
116                 if (NULL == s)
117                 {
118                         //  if the type is Serializable, use its serialization function
119                         //  otherwise, leave it NULL so we don't accidentally dereference
120                         //  a random pointer as if it were automatcally descended from
121                         //  Serializable
122
123                         if (dyn_detail::boost::is_base_of<Serializable, T>::value)
124                         {
125                                 serialize_func = ser_func_wrapper;
126                         }
127                         else if (dyn_detail::boost::is_pointer<T>::value)
128                         {
129                                 if (dyn_detail::boost::is_base_of<Serializable, 
130                                                 typename dyn_detail::boost::remove_pointer<T>::type>::value)
131                                 {
132                                         serialize_func = ser_func_wrapper;
133                                 }
134                         }
135                 }
136           }
137
138           const char *getTypeName() { return typeid(T).name();}
139           void *allocate() 
140           {
141                   //  If T is (Serializable *) need to allocate a new object, not a new pointer
142                   //  
143
144                   if (dyn_detail::boost::is_pointer<T>::value)
145                   {
146                                 if (dyn_detail::boost::is_base_of<Serializable, 
147                                                 typename dyn_detail::boost::remove_pointer<T>::type>::value)
148                                 {
149                                         return (void *) new (typename dyn_detail::boost::remove_pointer<T>::type)();
150                                 }
151                   }
152
153                   return (void *) new T();
154           }
155
156           size_t size() {return sizeof(T);}
157 #if 0
158           bool isSparselyAnnotatable(); 
159           bool isDenselyAnnotatable(); 
160 #endif
161 };
162
163
164 typedef enum {
165             sparse,
166                 dense,
167 } sparse_or_dense_anno_t;
168
169 typedef struct {
170         AnnotationClassBase *acb;
171         void *data;
172         void *parent_id;
173         sparse_or_dense_anno_t sod;
174 } ser_rec_t;
175
176 typedef enum {
177         sp_add_anno = 2,
178         sp_rem_anno = 3,
179         sp_add_cont_item = 4,
180         sp_rem_cont_item = 5
181 } ser_post_op_t;
182
183 COMMON_EXPORT const char *serPostOp2Str(ser_post_op_t);
184
185
186 class AnnotatableDense;
187 class AnnotatableSparse;
188 COMMON_EXPORT bool is_input(SerializerBase *sb);
189 COMMON_EXPORT bool is_output(SerializerBase *sb);
190 COMMON_EXPORT unsigned short get_serializer_index(SerializerBase *sb);
191 COMMON_EXPORT bool ser_operation(SerializerBase *, ser_post_op_t &, const char *);
192 COMMON_EXPORT bool add_annotations(SerializerBase *, AnnotatableDense *, std::vector<ser_rec_t> &);
193 COMMON_EXPORT bool add_annotations(SerializerBase *, AnnotatableSparse *, std::vector<ser_rec_t> &);
194 COMMON_EXPORT bool serialize_annotation_list(void *, std::vector<ser_rec_t> &, SerializerBase *sb, const char *);
195 COMMON_EXPORT SerializerBase *getExistingOutputSB(unsigned short);
196 COMMON_EXPORT bool serialize_post_annotation(void *, void *, SerializerBase *, AnnotationClassBase *acb, sparse_or_dense_anno_t, const char *);
197
198 class AnnotatableDense
199 {
200         friend COMMON_EXPORT bool add_annotations(SerializerBase *, AnnotatableDense *, std::vector<ser_rec_t> &);
201         friend class SerializerBase;
202         friend class Serializable;
203         typedef void *anno_list_t;
204
205         /**
206     * Inheriting from this class adds a pointer to each object.  Multiple
207     * types of annotations are stored under this pointer in a 
208     * annotation_type -> anno_list_t map.
209     **/
210
211    private:
212
213       typedef anno_list_t anno_map_t;
214
215       struct aInfo {
216          anno_map_t *data;
217          AnnotationClassID max;
218                  unsigned short serializer_index;
219       };
220
221       aInfo *annotations;
222
223           //  private version of addAnnotation exists for deserialize functions
224           //  to reconstruct annotations without explicit type info -- don't use in 
225           //  other contexts
226
227       COMMON_EXPORT bool addAnnotation(const void *a, AnnotationClassID id) 
228           {
229                   if (annotation_debug_flag())
230                   {
231                           fprintf(stderr, "%s[%d]:  Dense(%p) add %s-%d\n", FILE__, __LINE__, this, 
232                                           AnnotationClassBase::findAnnotationClass(id) 
233                                           ? AnnotationClassBase::findAnnotationClass(id)->getName().c_str() 
234                                           : "bad_anno_id", id);
235                   }
236
237          unsigned size = id + 1;
238          if (!annotations)
239          {
240             annotations = (aInfo *) malloc(sizeof(aInfo));
241                         annotations->data = NULL;
242                         annotations->serializer_index = (unsigned short) -1;
243                  }
244
245                  //  can have case where we have allocated annotations struct but not the
246                  //  actual annotations data array in case where we have performed serialization
247
248                  if (annotations->data == NULL) 
249                  {
250                         annotations->data = (anno_list_t *) calloc(sizeof(anno_list_t *), (size));
251                         annotations->max = size;
252                         for (unsigned i=0; i<size; i++)
253                                 annotations->data[i] = NULL;
254                  } 
255                  else if (id >= annotations->max) 
256                  {
257                          int old_max = annotations->max;
258                          size = annotations->max * 2;
259                          annotations->max = size;
260                          annotations->data = (anno_list_t *) realloc(annotations->data, sizeof(anno_list_t *) * size);
261                          for (unsigned i=old_max; i<size; i++)
262                                  annotations->data[i] = NULL;
263                  }
264
265                  annotations->data[id] = const_cast<void *>(a);
266
267          return true;
268       }
269    public:
270       COMMON_EXPORT AnnotatableDense() : annotations(NULL)
271       {
272       }
273
274           COMMON_EXPORT ~AnnotatableDense()
275           {
276                   if (annotations)
277                   {
278                           if (annotations->data)
279                                   free(annotations->data);
280                           free(annotations);
281                   }
282           }
283
284       template<class T> 
285       bool addAnnotation(const T *a, AnnotationClass<T> &a_id) 
286       {
287                   if (annotation_debug_flag())
288                   {
289                           fprintf(stderr, "%s[%d]:  Dense(%p):  Add %s-%d, %s\n", FILE__, __LINE__, 
290                                           this, a_id.getName().c_str(), a_id.getID(), typeid(T).name());
291                   }
292
293          int id = a_id.getID();
294                  T *a_noconst = const_cast<T *>(a);
295                  bool ret = addAnnotation((void *)a_noconst, id);
296                  if (!ret)
297                  {
298                          fprintf(stderr, "%s[%d]:  failed to add annotation\n", FILE__, __LINE__);
299                          return ret;
300                  }
301
302
303                  //  If serialization is not enabled, there will be no serializer specified,
304                  //  so none of the below code will be executed.
305
306                  serialize_printf("%s[%d]:  %p addAnnotation:  serializer_index = %d\n", 
307                                  FILE__, __LINE__, this, annotations->serializer_index);
308
309                  if (annotations && ( (unsigned short) -1 != annotations->serializer_index))
310                  {
311                          SerializerBase *sb = getExistingOutputSB(annotations->serializer_index);
312                          if (!sb)
313                          {
314                                  //  definitely should have a serializer since we have an index
315                                  fprintf(stderr, "%s[%d]:  FIXME:  no existing serializer!\n", FILE__, __LINE__);
316                                  return false;
317                          }
318                          ser_func_t sf = a_id.getSerializeFunc();
319                          if (sf)
320                          {
321                                  //  FIXME:  for xml support, ser_operation should have a corresponding 
322                                  //  "ser_operation_end()" routine to close out the xml field.
323                                  ser_post_op_t op = sp_add_anno;
324                                  ser_operation(sb, op, "AnnotationAdd");
325                                  void * aa = (void *) const_cast<T *>(a);
326                                  serialize_post_annotation(this, aa, sb, &a_id, dense, "PostAnnotation");
327                          }
328                  }
329
330                  return true;
331           }
332
333
334       template<class T> 
335       inline bool getAnnotation(T *&a, AnnotationClass<T> &a_id) const
336       {
337          if (!annotations)
338             return false;
339
340          int id = a_id.getID();
341
342          if (id > annotations->max) 
343          {
344             return false;
345          }
346
347          a = (T *) annotations->data[id];
348          if (!a) return false;
349
350          return true;
351       }
352
353       template<class T> 
354       inline bool removeAnnotation(AnnotationClass<T> &a_id)
355       {
356                   if (annotation_debug_flag())
357                   {
358                           fprintf(stderr, "%s[%d]:  Dense(%p) remove %s-%d, %s\n", FILE__, __LINE__, 
359                                           this, a_id.getName().c_str(), a_id.getID(), a_id.getTypeName());
360                   }
361
362          if (!annotations) return false;
363
364          int id = a_id.getID();
365          if (id > annotations->max) 
366          {
367             return false;
368          }
369
370          if (!annotations->data[id]) 
371             return false;
372
373          annotations->data[id] = NULL;
374
375          return true;
376       }
377
378           COMMON_EXPORT void serializeAnnotations(SerializerBase *sb, const char *tag)
379           {
380                   serialize_printf("%s[%d]:  welcome to serializeAnotations:\n", FILE__, __LINE__);
381                   //  iterator over possible annotation types
382                   //  if we have any, lookup the serialization function and call it
383
384                   std::vector<ser_rec_t> my_sers;
385                   if (is_output(sb))
386                   {
387                           //  need to figure out how many annotations will be serialized apriori
388                           //  so we can output the size of the list as a header.
389                           //  To avoid iterating over the full list twice, make a local copy
390                           //  of all serializations/deserializations that need to be performed
391                           //  as we go, and do them in bulk afterwards.
392
393                           if (annotations)
394                           {
395                                   for (AnnotationClassID id = 0; id < annotations->max; ++id)
396                                   {
397                                           void *anno = annotations->data[id];
398                                           if (anno)
399                                           {
400                                                   AnnotationClassBase *acb = AnnotationClassBase::findAnnotationClass(id);
401
402                                                   if (!acb)
403                                                   {
404                                                           fprintf(stderr, "%s[%d]:  FIXME:  no annotation class for id %d\n", 
405                                                                           FILE__, __LINE__, id);
406                                                           continue;
407                                                   }
408
409                                                   ser_func_t sf = acb->getSerializeFunc();
410
411                                                   if (NULL != sf)
412                                                   {
413                                                           ser_rec_t sr;
414                                                           sr.data = anno;
415                                                           sr.acb = acb;
416                                                           sr.parent_id = (void *) this;
417                                                           sr.sod = dense;
418                                                           my_sers.push_back(sr);
419                                                   }
420                                           }
421                                   }
422
423                                   annotations->serializer_index = get_serializer_index(sb);
424                                   serialize_printf("%s[%d]:  %p set serializer index to %d\n", 
425                                                   FILE__, __LINE__, this, annotations->serializer_index);
426                           }
427                           else
428                           {
429                                   //  need to alloc struct to store serializer index
430                                   annotations = (aInfo *) malloc(sizeof(aInfo));
431                                   annotations->data = NULL;
432                                   annotations->max = 0;
433                                   annotations->serializer_index = get_serializer_index(sb);
434                                   serialize_printf("%s[%d]:  %p set serializer index to %d\n", 
435                                                   FILE__, __LINE__, this, annotations->serializer_index);
436                           }
437                   }
438
439                   if (!serialize_annotation_list(this, my_sers, sb, tag))
440                   {
441                           fprintf(stderr, "%s[%d]:  FIXME:  failed to serialize annotation list\n", 
442                                           FILE__, __LINE__);
443                   }
444                   if (!add_annotations(sb, this, my_sers))
445                   {
446                           fprintf(stderr, "%s[%d]:  failed to update annotation list after deserialize\n", 
447                                           FILE__, __LINE__);
448                   }
449           }
450
451           COMMON_EXPORT void annotationsReport()
452           {
453                   std::vector<AnnotationClassBase *> atypes;
454                   if (annotations && annotations->data)
455                   {
456                           for (unsigned int i = 0; i < annotations->max; ++i)
457                           {
458                                   if (NULL != annotations->data[i])
459                                   {
460                                           AnnotationClassBase *acb = AnnotationClassBase::findAnnotationClass(i);
461                                           if (!acb)
462                                           {
463                                                   fprintf(stderr, "%s[%d]:  ERROR:  failed to find acb for %d\n", 
464                                                                   FILE__, __LINE__, i);
465                                                   continue;
466                                           }
467                                           else
468                                                   atypes.push_back(acb);
469                                   }
470                           }
471
472                           fprintf(stderr, "%s[%d]:  Dense(%p):  have %lu annotations\n", 
473                                   FILE__, __LINE__, this, (unsigned long) atypes.size());
474
475                           for (unsigned int i = 0; i < atypes.size(); ++i)
476                           {
477                                   fprintf(stderr, "\t%s-%d, %s\n", atypes[i]->getName().c_str(), 
478                                                   atypes[i]->getID(), atypes[i]->getTypeName());
479                           }
480                   }
481           }
482 };
483
484 #define NON_STATIC_SPARSE_MAP 1
485 #define AN_INLINE inline
486
487 class AnnotatableSparse
488 {
489         friend class SerializerBase;
490         friend class Serializable;
491         friend COMMON_EXPORT bool add_annotations(SerializerBase *, 
492                         AnnotatableSparse *, std::vector<ser_rec_t> &);
493
494    public:
495       struct void_ptr_hasher
496       {
497          size_t operator()(const void* a) const
498          {
499             return (size_t) a;
500          }
501       };
502
503 #if defined (_MSC_VER)
504       typedef dyn_hash_map<void *, void *> annos_by_type_t;
505 #else
506       typedef dyn_hash_map<void *, void *, void_ptr_hasher> annos_by_type_t;
507 #endif
508
509       typedef std::vector<annos_by_type_t *> annos_t;
510
511           COMMON_EXPORT ~AnnotatableSparse()
512           {
513                   //  We need to remove annotations from the static map when objects
514                   //  are destroyed:  (1)  memory may be reclaimed and reused at the same
515                   //  place, and (2) regardless of 1, the map can possibly explode to 
516                   //  unmanageable sizes, with a lot of unused junk in it if a lot of i
517                   //  annotatable objects are created and destroyed.
518
519                   //  Alas this is kinda expensive right now, but the data structure is
520                   //  set up to minimize search time, not deletion time.  It could
521                   //  be changed if this becomes a significant time drain.
522
523                   unsigned int n = 0;
524                   for (unsigned int i = 0; i < getAnnos()->size(); ++i)
525                   {
526                           annos_by_type_t *abt = (*getAnnos())[i];
527                           if (!abt) continue;
528
529                           annos_by_type_t::iterator iter = abt->find(this);
530                           if (iter != abt->end())
531                           {
532                                   if (annotation_debug_flag())
533                                   {
534                                           fprintf(stderr, "%s[%d]:  Sparse(%p) dtor remove %s-%d\n", FILE__, __LINE__,  
535                                                           this, AnnotationClassBase::findAnnotationClass(i) 
536                                                           ? AnnotationClassBase::findAnnotationClass(i)->getName().c_str() 
537                                                           : "bad_anno_id", i);
538                                   }
539
540                                   abt->erase(iter);
541                                   n++;
542
543                                   //  get rid of this check...  just making sure that erase is behaving as
544                                   //  expected...
545                                   annos_by_type_t::iterator iter2 = abt->find(this);
546                                   if (iter2 != abt->end())
547                                           fprintf(stderr, "%s[%d]:  FIXME:  REMOVE FAILED\n", FILE__, __LINE__);
548                           }
549                   }
550           }
551
552    private:
553
554 #if defined (NON_STATIC_SPARSE_MAP)
555       //COMMON_EXPORT static annos_t *annos;
556 #else
557       COMMON_EXPORT static annos_t annos;
558 #endif
559           COMMON_EXPORT annos_t *getAnnos() const;
560           COMMON_EXPORT static dyn_hash_map<void *, unsigned short> ser_ndx_map;
561
562       COMMON_EXPORT annos_by_type_t *getAnnosOfType(AnnotationClassID aid, bool do_create =false) const
563           {
564                   annos_t &l_annos = *getAnnos();
565          long nelems_to_create = aid - l_annos.size() + 1;
566
567          if (nelems_to_create > 0)
568          {
569             if (!do_create)
570             {
571                return NULL;
572             }
573
574             while (nelems_to_create)
575             {
576                annos_by_type_t *newl = new annos_by_type_t();
577                l_annos.push_back(newl);
578                nelems_to_create--;
579             }
580          }
581
582          annos_by_type_t *abt = l_annos[aid];
583
584          return abt;
585       }
586
587       template <class T>
588       AN_INLINE annos_by_type_t *getAnnosOfType(AnnotationClass<T> &a_id, bool do_create =false) const
589       {
590          AnnotationClassID aid = a_id.getID();
591
592                  return getAnnosOfType(aid, do_create);
593           }
594
595
596       COMMON_EXPORT void *getAnnosForObject(annos_by_type_t *abt,
597             void *obj, bool do_create = false) const 
598       {
599          assert(abt);
600          assert(obj);
601
602          void  *target = NULL;
603
604          annos_by_type_t::iterator iter = abt->find(obj);
605
606          if (iter == abt->end())
607          {
608             if (!do_create)
609             {
610                return NULL;
611             }
612
613             (*abt)[obj] = target;
614          }
615          else
616          {
617             target = iter->second;
618          }
619
620          return target;
621       }
622
623           //  private version of addAnnotation used by deserialize function to restore
624           //  annotation set without explicitly specifying types
625           COMMON_EXPORT AN_INLINE bool addAnnotation(const void *a, AnnotationClassID aid)
626           {
627                   if (annotation_debug_flag())
628                   {
629                           fprintf(stderr, "%s[%d]:  Sparse(%p) add %s-%d void\n", FILE__, __LINE__, this, 
630                                           AnnotationClassBase::findAnnotationClass(aid) 
631                                           ? AnnotationClassBase::findAnnotationClass(aid)->getName().c_str() 
632                                           : "bad_anno_id", aid);
633                   }
634
635                   void *obj = this;
636                   annos_by_type_t *abt = getAnnosOfType(aid, true /*do create if needed*/);
637                   assert(abt);
638
639                   annos_by_type_t::iterator iter = abt->find(obj);
640                   if (iter == abt->end())
641                   {
642                           (*abt)[obj] = const_cast<void *>(a);
643                   }
644                   else
645                   {
646                           //  do silent replacement -- this case can arise if an annotatable object
647                           //  is destroyed and then reallocated as a new object at the same address.
648                           //  Given the sparse map data structure, it would be rather expensive to 
649                           //  go through the map in the dtor to eliminate references to the 
650                           //  destroyed object.
651
652                           //  Added annotation removal in dtor...  so this case should _not_ arise,
653                           //  do the replacement, but make some noise:
654
655                           if (a != iter->second)
656                           {
657                                   annotatable_printf("%s[%d]:  WEIRD:  already have annotation of this type: %p, replacing with %p\n", FILE__, __LINE__, iter->second, a);
658                                   iter->second = const_cast<void *>(a);
659                           }
660
661                           return true;
662                   }
663
664                   return true;
665           }
666
667    public:
668
669           COMMON_EXPORT bool operator==(AnnotatableSparse &cmp)
670           {
671                   annos_t &l_annos = *getAnnos();
672                   unsigned this_ntypes = l_annos.size();
673          unsigned cmp_ntypes = cmp.getAnnos()->size();
674          unsigned ntypes = (cmp_ntypes > this_ntypes) ? cmp_ntypes : this_ntypes;
675
676          for (unsigned int i = 0; i < ntypes; ++i) 
677          {
678             if ((i >= cmp_ntypes) || (i >= this_ntypes)) 
679             {
680                //  compare is done since at least one set of annotations
681                //  has been exhausted
682                break;
683             }
684
685             annos_by_type_t *this_abt = l_annos[i];
686             annos_by_type_t *cmp_abt = (*cmp.getAnnos())[i];
687
688             if (!this_abt) 
689             {
690                fprintf(stderr, "%s[%d]:  WEIRD: FIXME\n", FILE__, __LINE__);
691                continue;
692             }
693
694             if (!cmp_abt) 
695             {
696                fprintf(stderr, "%s[%d]:  WEIRD: FIXME\n", FILE__, __LINE__);
697                continue;
698             }
699
700             annos_by_type_t::iterator this_abt_iter = this_abt->find(this);
701             annos_by_type_t::iterator cmp_abt_iter = cmp_abt->find(&cmp);
702
703             //  if one has annotations of this particular type and other other
704             //  doesn't, then we are def. not equal, so fail:
705
706             if (this_abt_iter == this_abt->end())
707             {
708                if (cmp_abt_iter != cmp_abt->end())
709                {
710                   return false;
711                }
712
713                //  both are at end()
714                continue;
715             }
716
717             if (   (cmp_abt_iter == cmp_abt->end())
718                   && (this_abt_iter != this_abt->end()))
719             {
720                return false;
721             }
722
723             AnnotationClassBase *acb = AnnotationClassBase::findAnnotationClass(i);
724
725             if (!acb)
726             {
727                serialize_printf("%s[%d]:  cannot find annotation class for id %d\n", 
728                      FILE__, __LINE__, i);
729                return false;
730             }
731
732             //  both have annotation -- do the compare
733             anno_cmp_func_t cmpfunc = acb->getCmpFunc();
734
735             if (!cmpfunc)
736             {
737                //  even if not explicitly specified, a default pointer-compare
738                //  function should be returned here.
739
740                fprintf(stderr, "%s[%d]:  no cmp func for anno id %d\n", 
741                      FILE__, __LINE__, i);
742                return false;
743             }
744
745             void *arg1 = cmp_abt_iter->second;
746             void *arg2 = this_abt_iter->second;
747
748             bool ret = (*cmpfunc)(arg1, arg2);
749
750             return ret;
751          }
752
753          return true;
754       }
755
756       template<class T>
757       AN_INLINE bool addAnnotation(const T *a, AnnotationClass<T> &a_id)
758          {
759                   annotatable_printf("%s[%d]:  Sparse(%p):  Add %s-%d, %s\n", FILE__, __LINE__, 
760                                   this, a_id.getName().c_str(), a_id.getID(), typeid(T).name());
761             void *obj = this;
762             annos_by_type_t *abt = getAnnosOfType(a_id, true /*do create if needed*/);
763             assert(abt);
764
765             annos_by_type_t::iterator iter = abt->find(obj);
766             if (iter == abt->end())
767             {
768                (*abt)[obj] = (void *) const_cast<T *>(a);
769             }
770             else
771             {
772                                 //  do silent replacement -- this case can arise if an annotatable object
773                                 //  is destroyed and then reallocated as a new object at the same address.
774                                 //  Given the sparse map data structure, it would be rather expensive to 
775                                 //  go through the map in the dtor to eliminate references to the 
776                                 //  destroyed object.
777
778                                 //  Added annotation removal in dtor...  so this case should _not_ arise,
779                                 //  do the replacement, but make some noise:
780
781                                 if (iter->second != a) 
782                                 {
783                                         //fprintf(stderr, "%s[%d]:  WEIRD:  already have annotation of type %s: %p, replacing with %p\n", FILE__, __LINE__, a_id.getName().c_str(), iter->second, a);
784                                         iter->second = (void *)const_cast<T *>(a);
785                                 }
786
787                                 return true;
788             }
789
790                         dyn_hash_map<void *, unsigned short>::iterator seriter;
791                         seriter = ser_ndx_map.find(this);
792                         if (seriter != ser_ndx_map.end())
793                         {
794                                 if (seriter->second != (unsigned short) -1)
795                                 {
796                                         SerializerBase *sb = getExistingOutputSB(seriter->second);
797                                         if (!sb)
798                                         {
799                                                 fprintf(stderr, "%s[%d]:  FIXME:  no existing output SB\n", 
800                                                                 FILE__, __LINE__);
801                                                 return false;
802                                         }
803
804                                         ser_func_t sf = a_id.getSerializeFunc();
805                                         if (sf)
806                                         {
807                                                 ser_post_op_t op = sp_add_anno;
808                                                 ser_operation(sb, op, "AnnotationAdd");
809                                                 void *aa = (void *) const_cast<T *>(a);
810                                                 serialize_post_annotation(this, aa, sb, &a_id, sparse, "PostAnnotation");
811                                         }
812                                 }
813                         }
814                                 
815             return true;
816          }
817
818       template<class T>
819       AN_INLINE bool getAnnotation(T *&a, AnnotationClass<T> &a_id) const 
820       {
821          a = NULL;
822
823          annos_by_type_t *abt = getAnnosOfType(a_id, false /*don't create if none*/);
824
825          if (!abt)
826          {
827             return false;
828          }
829
830          AnnotatableSparse * this_noconst = const_cast<AnnotatableSparse *>(this);
831          void *annos_for_object = getAnnosForObject(abt, (void *)this_noconst,
832                false /*no create if none*/);
833
834          if (!annos_for_object)
835          {
836             return false;
837          }
838
839          a = (T *)annos_for_object;
840          return true;
841       }
842
843           template<class T>
844           inline bool removeAnnotation(AnnotationClass<T> &a_id)
845           {
846                   if (annotation_debug_flag())
847                   {
848                           fprintf(stderr, "%s[%d]:  Sparse(%p) remove %s-%d, %s\n", FILE__, __LINE__,
849                                           this, a_id.getName().c_str(), a_id.getID(), typeid(T).name());
850                   }
851
852                   void *obj = this;
853                   annos_by_type_t *abt = getAnnosOfType(a_id, false /*do create if needed*/);
854                   assert(abt);
855
856                   annos_by_type_t::iterator iter = abt->find(obj);
857                   if (iter == abt->end())
858                   {
859                           //  annotation does not exist, so we return false (remove failed)
860                           return false;
861                   }
862                   else
863                   {
864                           abt->erase(iter);
865                           return true;
866                   }
867               return false;
868           }
869
870           COMMON_EXPORT void serializeAnnotations(SerializerBase *sb, const char *tag)
871           {
872                   annos_t &l_annos = *getAnnos();
873                   std::vector<ser_rec_t> my_sers;
874             void *obj = this;
875                         if (is_output(sb))
876                         {
877                                 for (AnnotationClassID id = 0; id < l_annos.size(); ++id)
878                                 {
879                                         annos_by_type_t *abt = getAnnosOfType(id, false /*don't do create */);
880                                         if (NULL == abt) continue;
881
882                                         annos_by_type_t::iterator iter = abt->find(obj);
883
884                                         if (iter == abt->end()) 
885                                         {
886                                                 //      fprintf(stderr, "%s[%d]:  nothing for this obj\n", FILE__, __LINE__);
887                                                 continue;
888                                         }
889
890                                         //  we have an annotation of this type for this object, find the serialization
891                                         //  function and call it (if it exists)
892
893                                         AnnotationClassBase *acb =  AnnotationClassBase::findAnnotationClass(id);
894                                         if (!acb)
895                                         {
896                                                 fprintf(stderr, "%s[%d]:  FIXME, cannot find annotation class base for id %d, mode = %s\n", FILE__, __LINE__, id, is_input(sb) ? "deserialize" : "serialize");
897                                                 continue;
898                                         }
899
900                                         ser_func_t sf = acb->getSerializeFunc();
901
902                                         if (NULL == sf)
903                                         {
904                                                 serialize_printf("%s[%d]:  no serialization function for this anno: type: %s, name: %s\n", FILE__, __LINE__, acb->getTypeName(), acb->getName().c_str());
905                                                 continue;
906                                         }
907
908                                         ser_rec_t sr;
909                                         sr.acb = acb;
910                                         sr.data = iter->second;
911                                         sr.parent_id = (void *) this;
912                                         sr.sod = sparse;
913                                         my_sers.push_back(sr);
914                                 }
915
916                                 if (my_sers.size())
917                                         serialize_printf("%s[%d]:  found %lu req'd serializations for obj %p\n", 
918                                                         FILE__, __LINE__, my_sers.size(), this);
919
920                                 ser_ndx_map[this] = get_serializer_index(sb);
921                         }
922
923                         if (!serialize_annotation_list(this, my_sers, sb, tag))
924                         {
925                                 fprintf(stderr, "%s[%d]:  FIXME:  failed to serialize annotation list\n", 
926                                                 FILE__, __LINE__);
927                         }
928
929                         if (!add_annotations(sb, this, my_sers))
930                         {
931                                 fprintf(stderr, "%s[%d]:  failed to update annotation list after deserialize\n", 
932                                                 FILE__, __LINE__);
933                         }
934           }
935
936           COMMON_EXPORT void annotationsReport()
937           {
938                   std::vector<AnnotationClassBase *> atypes;
939                   annos_t &l_annos = *getAnnos();
940
941                   for (AnnotationClassID id = 0; id < l_annos.size(); ++id)
942                   {
943                           annos_by_type_t *abt = getAnnosOfType(id, false /*don't do create */);
944                           if (NULL == abt) continue;
945
946                           annos_by_type_t::iterator iter = abt->find(this);
947
948                           if (iter == abt->end()) 
949                           {
950                                   //    fprintf(stderr, "%s[%d]:  nothing for this obj\n", FILE__, __LINE__);
951                                   continue;
952                           }
953
954                           AnnotationClassBase *acb =  AnnotationClassBase::findAnnotationClass(id);
955                           if (!acb)
956                           {
957                                   fprintf(stderr, "%s[%d]:  FIXME, cant find anno class base for id %d\n", 
958                                                   FILE__, __LINE__, id);
959                                   continue;
960                           }
961                           atypes.push_back(acb);
962                   }
963
964                   fprintf(stderr, "%s[%d]:  Sparse(%p):  have %lu annos:\n", FILE__, __LINE__, 
965                           this, (unsigned long) atypes.size());
966                   for (unsigned int i = 0; i < atypes.size(); ++i)
967                   {
968                           fprintf(stderr, "\t%s-%d, %s\n", atypes[i]->getName().c_str(), 
969                                           atypes[i]->getID(), atypes[i]->getTypeName());
970                   }
971           }
972
973 };
974
975 } // namespace
976
977 #endif