Annotatable.h

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #ifndef __ANNOTATABLE_H__
00032 #define __ANNOTATABLE_H__
00033 
00034 #if defined (MSC_VER)
00035 #define DYN_DETAIL_BOOST_NO_INTRINSIC_WCHAR_T 1
00036 #endif
00037 #include "dyntypes.h"
00038 #include <vector>
00039 #include <map>
00040 #include <typeinfo>
00041 #include <string>
00042 #include <string.h> // for strrchr()
00043 #include <assert.h>
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include "Serialization.h"
00047 #include "util.h"
00048 
00049 namespace Dyninst
00050 {
00051 
00052 
00053 class SerializerBase;
00054 class Serializable;
00055 typedef Serializable * (*ser_func_t) (void *, SerializerBase *, const char *);
00056 
00057 #if !defined(SERIALIZATION_DISABLED)
00058 #define serialize_printf serializer_printf
00059 COMMON_EXPORT int serializer_printf(const char *format, ...);
00060 COMMON_EXPORT Serializable * ser_func_wrapper(void *it, SerializerBase *sb,  const char *tag);
00061 #endif
00062 COMMON_EXPORT bool annotation_debug_flag();
00063 COMMON_EXPORT int annotatable_printf(const char *format, ...);
00064 
00065 typedef unsigned short AnnotationClassID;
00066 typedef bool (*anno_cmp_func_t)(void *, void*);
00067 
00068 extern int newAnnotationClass();
00069 extern bool void_ptr_cmp_func(void *, void *);
00070 
00071 class AnnotationClassBase
00072 {
00073     friend class Serializable;
00074    private:
00075       static std::vector<AnnotationClassBase *> *annotation_types;
00076       static dyn_hash_map<std::string, AnnotationClassID> *annotation_ids_by_name;
00077 #if 0
00078       COMMON_EXPORT static void clearAnnotationIDMap();
00079 #endif
00080       anno_cmp_func_t cmp_func;
00081       AnnotationClassID id;
00082       std::string name;
00083 
00084    protected:
00085 
00086       ser_func_t serialize_func;
00087 
00088      COMMON_EXPORT AnnotationClassBase(std::string n, 
00089                                        anno_cmp_func_t cmp_func_ = NULL, 
00090                                        ser_func_t sf_ = NULL);
00091 
00092       COMMON_EXPORT virtual ~AnnotationClassBase(); 
00093 
00094    public:
00095 
00096       COMMON_EXPORT static AnnotationClassBase *findAnnotationClass(unsigned int id);
00097       COMMON_EXPORT static void dumpAnnotationClasses();
00098 
00099       COMMON_EXPORT AnnotationClassID getID() { return id; }
00100       COMMON_EXPORT std::string &getName() {return name;}
00101       COMMON_EXPORT anno_cmp_func_t getCmpFunc() {return cmp_func;}
00102       COMMON_EXPORT ser_func_t getSerializeFunc() {return serialize_func;}
00103       COMMON_EXPORT virtual const char *getTypeName() = 0;
00104       COMMON_EXPORT virtual void *allocate() = 0;
00105 };
00106 
00107 template <class T> 
00108 class AnnotationClass : public AnnotationClassBase {
00109    public:
00110 
00111       AnnotationClass(std::string n, 
00112               anno_cmp_func_t cmp_func_ = NULL, 
00113               ser_func_t s = NULL) :
00114           AnnotationClassBase(n, cmp_func_, s)
00115       {
00116 #if !defined(SERIALIZATION_DISABLED)
00117         if (NULL == s)
00118         {
00119             //  if the type is Serializable, use its serialization function
00120             //  otherwise, leave it NULL so we don't accidentally dereference
00121             //  a random pointer as if it were automatcally descended from
00122             //  Serializable
00123             if (boost::is_base_of<Serializable, T>::value)
00124             {
00125                 serialize_func = ser_func_wrapper;
00126             } else
00127          if (boost::is_pointer<T>::value)
00128             {
00129                 if (boost::is_base_of<Serializable, 
00130                         typename boost::remove_pointer<T>::type>::value)
00131                 {
00132                     serialize_func = ser_func_wrapper;
00133                 }
00134             }
00135         }
00136 #endif
00137       }
00138 
00139       const char *getTypeName() { return typeid(T).name();}
00140       void *allocate() 
00141       {
00142           return (void *) new T();
00143       }
00144 
00145       size_t size() {return sizeof(T);}
00146 #if 0
00147       bool isSparselyAnnotatable(); 
00148       bool isDenselyAnnotatable(); 
00149 #endif
00150 };
00151 
00152 
00153 typedef enum {
00154         sparse,
00155         dense
00156 } sparse_or_dense_anno_t;
00157 
00158 typedef struct {
00159     AnnotationClassBase *acb;
00160     void *data;
00161     void *parent_id;
00162     sparse_or_dense_anno_t sod;
00163 } ser_rec_t;
00164 
00165 typedef enum {
00166     sp_add_anno = 2,
00167     sp_rem_anno = 3,
00168     sp_add_cont_item = 4,
00169     sp_rem_cont_item = 5
00170 } ser_post_op_t;
00171 
00172 COMMON_EXPORT const char *serPostOp2Str(ser_post_op_t);
00173 
00174 
00175 class AnnotatableDense;
00176 class AnnotatableSparse;
00177 COMMON_EXPORT bool is_input(SerializerBase *sb);
00178 COMMON_EXPORT bool is_output(SerializerBase *sb);
00179 COMMON_EXPORT unsigned short get_serializer_index(SerializerBase *sb);
00180 COMMON_EXPORT bool ser_operation(SerializerBase *, ser_post_op_t &, const char *);
00181 COMMON_EXPORT bool add_annotations(SerializerBase *, AnnotatableDense *, std::vector<ser_rec_t> &);
00182 COMMON_EXPORT bool add_annotations(SerializerBase *, AnnotatableSparse *, std::vector<ser_rec_t> &);
00183 #if !defined(SERIALIZATION_DISABLED)
00184 COMMON_EXPORT bool serialize_annotation_list(void *, std::vector<ser_rec_t> &, SerializerBase *sb, const char *);
00185 COMMON_EXPORT SerializerBase *getExistingOutputSB(unsigned short);
00186 COMMON_EXPORT bool serialize_post_annotation(void *, void *, SerializerBase *, AnnotationClassBase *acb, sparse_or_dense_anno_t, const char *);
00187 #endif
00188 
00189 class COMMON_EXPORT AnnotatableDense
00190 {
00191     friend COMMON_EXPORT bool add_annotations(SerializerBase *, AnnotatableDense *, std::vector<ser_rec_t> &);
00192     friend class SerializerBase;
00193     friend class Serializable;
00194     typedef void *anno_list_t;
00195 
00196     /**
00197     * Inheriting from this class adds a pointer to each object.  Multiple
00198     * types of annotations are stored under this pointer in a 
00199     * annotation_type -> anno_list_t map.
00200     **/
00201 
00202    private:
00203 
00204       typedef anno_list_t anno_map_t;
00205 
00206       struct aInfo {
00207          anno_map_t *data;
00208          AnnotationClassID max;
00209          unsigned short serializer_index;
00210       };
00211 
00212       aInfo *annotations;
00213 
00214       //  private version of addAnnotation exists for deserialize functions
00215       //  to reconstruct annotations without explicit type info -- don't use in 
00216       //  other contexts
00217 
00218       bool addAnnotation(const void *a, AnnotationClassID id) 
00219       {
00220           if (annotation_debug_flag())
00221           {
00222               fprintf(stderr, "%s[%d]:  Dense(%p) add %s-%d\n", FILE__, __LINE__, this, 
00223                       AnnotationClassBase::findAnnotationClass(id) 
00224                       ? AnnotationClassBase::findAnnotationClass(id)->getName().c_str() 
00225                       : "bad_anno_id", id);
00226           }
00227 
00228          unsigned size = id + 1;
00229          if (!annotations)
00230          {
00231             annotations = (aInfo *) malloc(sizeof(aInfo));
00232             annotations->data = NULL;
00233             annotations->serializer_index = (unsigned short) -1;
00234          }
00235 
00236          //  can have case where we have allocated annotations struct but not the
00237          //  actual annotations data array in case where we have performed serialization
00238 
00239          if (annotations->data == NULL) 
00240          {
00241             annotations->data = (anno_list_t *) calloc(sizeof(anno_list_t *), (size));
00242             annotations->max = size;
00243             for (unsigned i=0; i<size; i++)
00244                 annotations->data[i] = NULL;
00245          } 
00246          else if (id >= annotations->max) 
00247          {
00248              int old_max = annotations->max;
00249              size = annotations->max * 2;
00250              annotations->max = size;
00251              annotations->data = (anno_list_t *) realloc(annotations->data, sizeof(anno_list_t *) * size);
00252              for (unsigned i=old_max; i<size; i++)
00253                  annotations->data[i] = NULL;
00254          }
00255 
00256          annotations->data[id] = const_cast<void *>(a);
00257 
00258          return true;
00259       }
00260    public:
00261       AnnotatableDense() : annotations(NULL)
00262       {
00263       }
00264 
00265       ~AnnotatableDense()
00266       {
00267           if (annotations)
00268           {
00269               if (annotations->data)
00270                   free(annotations->data);
00271               free(annotations);
00272           }
00273       }
00274 
00275       template<class T> 
00276       bool addAnnotation(const T *a, AnnotationClass<T> &a_id) 
00277       {
00278           if (annotation_debug_flag())
00279           {
00280               fprintf(stderr, "%s[%d]:  Dense(%p):  Add %s-%d, %s\n", FILE__, __LINE__, 
00281                       this, a_id.getName().c_str(), a_id.getID(), typeid(T).name());
00282           }
00283 
00284          int id = a_id.getID();
00285          T *a_noconst = const_cast<T *>(a);
00286          bool ret = addAnnotation((void *)a_noconst, id);
00287          if (!ret)
00288          {
00289              fprintf(stderr, "%s[%d]:  failed to add annotation\n", FILE__, __LINE__);
00290              return ret;
00291          }
00292 
00293 
00294 #if !defined(SERIALIZATION_DISABLED)
00295          //  If serialization is not enabled, there will be no serializer specified,
00296          //  so none of the below code will be executed.
00297 
00298          serialize_printf("%s[%d]:  %p addAnnotation:  serializer_index = %d\n", 
00299                  FILE__, __LINE__, this, annotations->serializer_index);
00300 
00301          if (annotations && ( (unsigned short) -1 != annotations->serializer_index))
00302          {
00303              SerializerBase *sb = getExistingOutputSB(annotations->serializer_index);
00304              if (!sb)
00305              {
00306                  //  definitely should have a serializer since we have an index
00307                  fprintf(stderr, "%s[%d]:  FIXME:  no existing serializer!\n", FILE__, __LINE__);
00308                  return false;
00309              }
00310              ser_func_t sf = a_id.getSerializeFunc();
00311              if (sf)
00312              {
00313                  //  FIXME:  for xml support, ser_operation should have a corresponding 
00314                  //  "ser_operation_end()" routine to close out the xml field.
00315                  ser_post_op_t op = sp_add_anno;
00316                  ser_operation(sb, op, "AnnotationAdd");
00317                  void * aa = (void *) const_cast<T *>(a);
00318                  serialize_post_annotation(this, aa, sb, &a_id, dense, "PostAnnotation");
00319              }
00320          }
00321 #endif
00322 
00323          return true;
00324       }
00325 
00326 
00327       template<class T> 
00328       inline bool getAnnotation(T *&a, AnnotationClass<T> &a_id) const
00329       {
00330          if (!annotations)
00331             return false;
00332 
00333          int id = a_id.getID();
00334 
00335          if (id > annotations->max) 
00336          {
00337             return false;
00338          }
00339 
00340          a = (T *) annotations->data[id];
00341          if (!a) return false;
00342 
00343          return true;
00344       }
00345 
00346       template<class T> 
00347       inline bool removeAnnotation(AnnotationClass<T> &a_id)
00348       {
00349           if (annotation_debug_flag())
00350           {
00351               fprintf(stderr, "%s[%d]:  Dense(%p) remove %s-%d, %s\n", FILE__, __LINE__, 
00352                       this, a_id.getName().c_str(), a_id.getID(), a_id.getTypeName());
00353           }
00354 
00355          if (!annotations) return false;
00356 
00357          int id = a_id.getID();
00358          if (id > annotations->max) 
00359          {
00360             return false;
00361          }
00362 
00363          if (!annotations->data[id]) 
00364             return false;
00365 
00366          annotations->data[id] = NULL;
00367 
00368          return true;
00369       }
00370 
00371 #if !defined(SERIALIZATION_DISABLED)
00372      void serializeAnnotations(SerializerBase *sb, const char *tag)
00373       {
00374           serialize_printf("%s[%d]:  welcome to serializeAnotations:\n", FILE__, __LINE__);
00375           //  iterator over possible annotation types
00376           //  if we have any, lookup the serialization function and call it
00377 
00378           std::vector<ser_rec_t> my_sers;
00379           if (is_output(sb))
00380           {
00381               //  need to figure out how many annotations will be serialized apriori
00382               //  so we can output the size of the list as a header.
00383               //  To avoid iterating over the full list twice, make a local copy
00384               //  of all serializations/deserializations that need to be performed
00385               //  as we go, and do them in bulk afterwards.
00386 
00387               if (annotations)
00388               {
00389                   for (AnnotationClassID id = 0; id < annotations->max; ++id)
00390                   {
00391                       void *anno = annotations->data[id];
00392                       if (anno)
00393                       {
00394                           AnnotationClassBase *acb = AnnotationClassBase::findAnnotationClass(id);
00395 
00396                           if (!acb)
00397                           {
00398                               fprintf(stderr, "%s[%d]:  FIXME:  no annotation class for id %d\n", 
00399                                       FILE__, __LINE__, id);
00400                               continue;
00401                           }
00402 
00403                           ser_func_t sf = acb->getSerializeFunc();
00404 
00405                           if (NULL != sf)
00406                           {
00407                               ser_rec_t sr;
00408                               sr.data = anno;
00409                               sr.acb = acb;
00410                               sr.parent_id = (void *) this;
00411                               sr.sod = dense;
00412                               my_sers.push_back(sr);
00413                           }
00414                       }
00415                   }
00416 
00417                   annotations->serializer_index = get_serializer_index(sb);
00418                   serialize_printf("%s[%d]:  %p set serializer index to %d\n", 
00419                           FILE__, __LINE__, this, annotations->serializer_index);
00420               }
00421               else
00422               {
00423                   //  need to alloc struct to store serializer index
00424                   annotations = (aInfo *) malloc(sizeof(aInfo));
00425                   annotations->data = NULL;
00426                   annotations->max = 0;
00427                   annotations->serializer_index = get_serializer_index(sb);
00428                   serialize_printf("%s[%d]:  %p set serializer index to %d\n", 
00429                           FILE__, __LINE__, this, annotations->serializer_index);
00430               }
00431           }
00432 
00433           if (!serialize_annotation_list(this, my_sers, sb, tag))
00434           {
00435               fprintf(stderr, "%s[%d]:  FIXME:  failed to serialize annotation list\n", 
00436                       FILE__, __LINE__);
00437           }
00438           if (!add_annotations(sb, this, my_sers))
00439           {
00440               fprintf(stderr, "%s[%d]:  failed to update annotation list after deserialize\n", 
00441                       FILE__, __LINE__);
00442           }
00443       }
00444 #else
00445       void serializeAnnotations(SerializerBase *, const char *) {
00446      }
00447 #endif
00448       void annotationsReport()
00449       {
00450           std::vector<AnnotationClassBase *> atypes;
00451           if (annotations && annotations->data)
00452           {
00453               for (unsigned int i = 0; i < annotations->max; ++i)
00454               {
00455                   if (NULL != annotations->data[i])
00456                   {
00457                       AnnotationClassBase *acb = AnnotationClassBase::findAnnotationClass(i);
00458                       if (!acb)
00459                       {
00460                           fprintf(stderr, "%s[%d]:  ERROR:  failed to find acb for %d\n", 
00461                                   FILE__, __LINE__, i);
00462                           continue;
00463                       }
00464                       else
00465                           atypes.push_back(acb);
00466                   }
00467               }
00468 
00469               fprintf(stderr, "%s[%d]:  Dense(%p):  have %lu annotations\n", 
00470                   FILE__, __LINE__, this, (unsigned long) atypes.size());
00471 
00472               for (unsigned int i = 0; i < atypes.size(); ++i)
00473               {
00474                   fprintf(stderr, "\t%s-%d, %s\n", atypes[i]->getName().c_str(), 
00475                           atypes[i]->getID(), atypes[i]->getTypeName());
00476               }
00477           }
00478       }
00479 };
00480 
00481 #define NON_STATIC_SPARSE_MAP 1
00482 #define AN_INLINE inline
00483 
00484 class COMMON_EXPORT AnnotatableSparse
00485 {
00486     friend class SerializerBase;
00487     friend class Serializable;
00488     friend COMMON_EXPORT bool add_annotations(SerializerBase *, 
00489             AnnotatableSparse *, std::vector<ser_rec_t> &);
00490 
00491    public:
00492       struct void_ptr_hasher
00493       {
00494          size_t operator()(const void* a) const
00495          {
00496             return (size_t) a;
00497          }
00498       };
00499 
00500 #if defined (_MSC_VER)
00501       typedef dyn_hash_map<void *, void *> annos_by_type_t;
00502 #pragma warning (push)
00503 #pragma warning (disable:4251)
00504 #else
00505       typedef dyn_hash_map<void *, void *, void_ptr_hasher> annos_by_type_t;
00506 #endif
00507 
00508       typedef std::vector<annos_by_type_t *> annos_t;
00509 
00510       ~AnnotatableSparse()
00511       {
00512           //  We need to remove annotations from the static map when objects
00513           //  are destroyed:  (1)  memory may be reclaimed and reused at the same
00514           //  place, and (2) regardless of 1, the map can possibly explode to 
00515           //  unmanageable sizes, with a lot of unused junk in it if a lot of i
00516           //  annotatable objects are created and destroyed.
00517 
00518           //  Alas this is kinda expensive right now, but the data structure is
00519           //  set up to minimize search time, not deletion time.  It could
00520           //  be changed if this becomes a significant time drain.
00521 
00522           unsigned int n = 0;
00523           for (unsigned int i = 0; i < getAnnos()->size(); ++i)
00524           {
00525               annos_by_type_t *abt = (*getAnnos())[i];
00526               if (!abt) continue;
00527 
00528               annos_by_type_t::iterator iter = abt->find(this);
00529               if (iter != abt->end())
00530               {
00531                   if (annotation_debug_flag())
00532                   {
00533                       fprintf(stderr, "%s[%d]:  Sparse(%p) dtor remove %s-%d\n", FILE__, __LINE__,  
00534                               this, AnnotationClassBase::findAnnotationClass(i) 
00535                               ? AnnotationClassBase::findAnnotationClass(i)->getName().c_str() 
00536                               : "bad_anno_id", i);
00537                   }
00538 
00539                   abt->erase(iter);
00540                   n++;
00541 
00542                   //  get rid of this check...  just making sure that erase is behaving as
00543                   //  expected...
00544                   annos_by_type_t::iterator iter2 = abt->find(this);
00545                   if (iter2 != abt->end())
00546                       fprintf(stderr, "%s[%d]:  FIXME:  REMOVE FAILED\n", FILE__, __LINE__);
00547               }
00548           }
00549       }
00550 
00551    private:
00552 
00553 #if defined (NON_STATIC_SPARSE_MAP)
00554       //COMMON_EXPORT static annos_t *annos;
00555 #else
00556       static annos_t annos;
00557 #endif
00558       annos_t *getAnnos() const;
00559       static dyn_hash_map<void *, unsigned short> ser_ndx_map;
00560 
00561       annos_by_type_t *getAnnosOfType(AnnotationClassID aid, bool do_create =false) const
00562       {
00563           annos_t &l_annos = *getAnnos();
00564          long nelems_to_create = aid - l_annos.size() + 1;
00565 
00566          if (nelems_to_create > 0)
00567          {
00568             if (!do_create)
00569             {
00570                return NULL;
00571             }
00572 
00573             while (nelems_to_create)
00574             {
00575                annos_by_type_t *newl = new annos_by_type_t();
00576                l_annos.push_back(newl);
00577                nelems_to_create--;
00578             }
00579          }
00580 
00581          annos_by_type_t *abt = l_annos[aid];
00582 
00583          return abt;
00584       }
00585 
00586       template <class T>
00587       AN_INLINE annos_by_type_t *getAnnosOfType(AnnotationClass<T> &a_id, bool do_create =false) const
00588       {
00589          AnnotationClassID aid = a_id.getID();
00590 
00591          return getAnnosOfType(aid, do_create);
00592       }
00593 
00594 
00595       void *getAnnosForObject(annos_by_type_t *abt,
00596             void *obj, bool do_create = false) const 
00597       {
00598          assert(abt);
00599          assert(obj);
00600 
00601          void  *target = NULL;
00602 
00603          annos_by_type_t::iterator iter = abt->find(obj);
00604 
00605          if (iter == abt->end())
00606          {
00607             if (!do_create)
00608             {
00609                return NULL;
00610             }
00611 
00612             (*abt)[obj] = target;
00613          }
00614          else
00615          {
00616             target = iter->second;
00617          }
00618 
00619          return target;
00620       }
00621 
00622       //  private version of addAnnotation used by deserialize function to restore
00623       //  annotation set without explicitly specifying types
00624       AN_INLINE bool addAnnotation(const void *a, AnnotationClassID aid)
00625       {
00626           if (annotation_debug_flag())
00627           {
00628               fprintf(stderr, "%s[%d]:  Sparse(%p) add %s-%d void\n", FILE__, __LINE__, this, 
00629                       AnnotationClassBase::findAnnotationClass(aid) 
00630                       ? AnnotationClassBase::findAnnotationClass(aid)->getName().c_str() 
00631                       : "bad_anno_id", aid);
00632           }
00633 
00634           void *obj = this;
00635           annos_by_type_t *abt = getAnnosOfType(aid, true /*do create if needed*/);
00636           assert(abt);
00637 
00638           annos_by_type_t::iterator iter = abt->find(obj);
00639           if (iter == abt->end())
00640           {
00641               (*abt)[obj] = const_cast<void *>(a);
00642           }
00643           else
00644           {
00645               //  do silent replacement -- this case can arise if an annotatable object
00646               //  is destroyed and then reallocated as a new object at the same address.
00647               //  Given the sparse map data structure, it would be rather expensive to 
00648               //  go through the map in the dtor to eliminate references to the 
00649               //  destroyed object.
00650 
00651               //  Added annotation removal in dtor...  so this case should _not_ arise,
00652               //  do the replacement, but make some noise:
00653 
00654               if (a != iter->second)
00655               {
00656                   annotatable_printf("%s[%d]:  WEIRD:  already have annotation of this type: %p, replacing with %p\n", FILE__, __LINE__, iter->second, a);
00657                   iter->second = const_cast<void *>(a);
00658               }
00659 
00660               return true;
00661           }
00662 
00663           return true;
00664       }
00665 
00666    public:
00667 
00668       bool operator==(AnnotatableSparse &cmp)
00669       {
00670           annos_t &l_annos = *getAnnos();
00671           unsigned this_ntypes = l_annos.size();
00672          unsigned cmp_ntypes = cmp.getAnnos()->size();
00673          unsigned ntypes = (cmp_ntypes > this_ntypes) ? cmp_ntypes : this_ntypes;
00674 
00675          for (unsigned int i = 0; i < ntypes; ++i) 
00676          {
00677             if ((i >= cmp_ntypes) || (i >= this_ntypes)) 
00678             {
00679                //  compare is done since at least one set of annotations
00680                //  has been exhausted
00681                break;
00682             }
00683 
00684             annos_by_type_t *this_abt = l_annos[i];
00685             annos_by_type_t *cmp_abt = (*cmp.getAnnos())[i];
00686 
00687             if (!this_abt) 
00688             {
00689                fprintf(stderr, "%s[%d]:  WEIRD: FIXME\n", FILE__, __LINE__);
00690                continue;
00691             }
00692 
00693             if (!cmp_abt) 
00694             {
00695                fprintf(stderr, "%s[%d]:  WEIRD: FIXME\n", FILE__, __LINE__);
00696                continue;
00697             }
00698 
00699             annos_by_type_t::iterator this_abt_iter = this_abt->find(this);
00700             annos_by_type_t::iterator cmp_abt_iter = cmp_abt->find(&cmp);
00701 
00702             //  if one has annotations of this particular type and other other
00703             //  doesn't, then we are def. not equal, so fail:
00704 
00705             if (this_abt_iter == this_abt->end())
00706             {
00707                if (cmp_abt_iter != cmp_abt->end())
00708                {
00709                   return false;
00710                }
00711 
00712                //  both are at end()
00713                continue;
00714             }
00715 
00716             if (   (cmp_abt_iter == cmp_abt->end())
00717                   && (this_abt_iter != this_abt->end()))
00718             {
00719                return false;
00720             }
00721 
00722             AnnotationClassBase *acb = AnnotationClassBase::findAnnotationClass(i);
00723 
00724             if (!acb)
00725             {
00726                return false;
00727             }
00728 
00729             //  both have annotation -- do the compare
00730             anno_cmp_func_t cmpfunc = acb->getCmpFunc();
00731 
00732             if (!cmpfunc)
00733             {
00734                //  even if not explicitly specified, a default pointer-compare
00735                //  function should be returned here.
00736 
00737                fprintf(stderr, "%s[%d]:  no cmp func for anno id %d\n", 
00738                      FILE__, __LINE__, i);
00739                return false;
00740             }
00741 
00742             void *arg1 = cmp_abt_iter->second;
00743             void *arg2 = this_abt_iter->second;
00744 
00745             bool ret = (*cmpfunc)(arg1, arg2);
00746 
00747             return ret;
00748          }
00749 
00750          return true;
00751       }
00752 
00753       template<class T>
00754       AN_INLINE bool addAnnotation(const T *a, AnnotationClass<T> &a_id)
00755          {
00756           annotatable_printf("%s[%d]:  Sparse(%p):  Add %s-%d, %s\n", FILE__, __LINE__, 
00757                   this, a_id.getName().c_str(), a_id.getID(), typeid(T).name());
00758             void *obj = this;
00759             annos_by_type_t *abt = getAnnosOfType(a_id, true /*do create if needed*/);
00760             assert(abt);
00761 
00762             annos_by_type_t::iterator iter = abt->find(obj);
00763             if (iter == abt->end())
00764             {
00765                (*abt)[obj] = (void *) const_cast<T *>(a);
00766             }
00767             else
00768             {
00769                 //  do silent replacement -- this case can arise if an annotatable object
00770                 //  is destroyed and then reallocated as a new object at the same address.
00771                 //  Given the sparse map data structure, it would be rather expensive to 
00772                 //  go through the map in the dtor to eliminate references to the 
00773                 //  destroyed object.
00774 
00775                 //  Added annotation removal in dtor...  so this case should _not_ arise,
00776                 //  do the replacement, but make some noise:
00777 
00778                 if (iter->second != a) 
00779                 {
00780                     //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);
00781                     iter->second = (void *)const_cast<T *>(a);
00782                 }
00783 
00784                 return true;
00785             }
00786 
00787 #if !defined(SERIALIZATION_DISABLED)
00788             dyn_hash_map<void *, unsigned short>::iterator seriter;
00789             seriter = ser_ndx_map.find(this);
00790             if (seriter != ser_ndx_map.end())
00791             {
00792                 if (seriter->second != (unsigned short) -1)
00793                 {
00794                     SerializerBase *sb = getExistingOutputSB(seriter->second);
00795                     if (!sb)
00796                     {
00797                         fprintf(stderr, "%s[%d]:  FIXME:  no existing output SB\n", 
00798                                 FILE__, __LINE__);
00799                         return false;
00800                     }
00801 
00802                     ser_func_t sf = a_id.getSerializeFunc();
00803                     if (sf)
00804                     {
00805                         ser_post_op_t op = sp_add_anno;
00806                         ser_operation(sb, op, "AnnotationAdd");
00807                         void *aa = (void *) const_cast<T *>(a);
00808                         serialize_post_annotation(this, aa, sb, &a_id, sparse, "PostAnnotation");
00809                     }
00810                 }
00811             }
00812 #endif
00813                 
00814             return true;
00815          }
00816 
00817       template<class T>
00818       AN_INLINE bool getAnnotation(T *&a, AnnotationClass<T> &a_id) const 
00819       {
00820          a = NULL;
00821 
00822          annos_by_type_t *abt = getAnnosOfType(a_id, false /*don't create if none*/);
00823 
00824          if (!abt)
00825          {
00826             return false;
00827          }
00828 
00829          AnnotatableSparse * this_noconst = const_cast<AnnotatableSparse *>(this);
00830          void *annos_for_object = getAnnosForObject(abt, (void *)this_noconst,
00831                false /*no create if none*/);
00832 
00833          if (!annos_for_object)
00834          {
00835             return false;
00836          }
00837 
00838          a = (T *)annos_for_object;
00839          return true;
00840       }
00841 
00842       template<class T>
00843       inline bool removeAnnotation(AnnotationClass<T> &a_id)
00844       {
00845           if (annotation_debug_flag())
00846           {
00847               fprintf(stderr, "%s[%d]:  Sparse(%p) remove %s-%d, %s\n", FILE__, __LINE__,
00848                       this, a_id.getName().c_str(), a_id.getID(), typeid(T).name());
00849           }
00850 
00851           void *obj = this;
00852           annos_by_type_t *abt = getAnnosOfType(a_id, false /*do create if needed*/);
00853           assert(abt);
00854 
00855           annos_by_type_t::iterator iter = abt->find(obj);
00856           if (iter == abt->end())
00857           {
00858               //  annotation does not exist, so we return false (remove failed)
00859               return false;
00860           }
00861           else
00862           {
00863               abt->erase(iter);
00864               return true;
00865           }
00866           return false;
00867       }
00868 
00869     void serializeAnnotations(SerializerBase *sb, const char *)
00870       {
00871           annos_t &l_annos = *getAnnos();
00872           std::vector<ser_rec_t> my_sers;
00873             void *obj = this;
00874             if (is_output(sb))
00875             {
00876                 for (AnnotationClassID id = 0; id < l_annos.size(); ++id)
00877                 {
00878                     annos_by_type_t *abt = getAnnosOfType(id, false /*don't do create */);
00879                     if (NULL == abt) continue;
00880 
00881                     annos_by_type_t::iterator iter = abt->find(obj);
00882 
00883                     if (iter == abt->end()) 
00884                     {
00885                         //  fprintf(stderr, "%s[%d]:  nothing for this obj\n", FILE__, __LINE__);
00886                         continue;
00887                     }
00888 
00889                     //  we have an annotation of this type for this object, find the serialization
00890                     //  function and call it (if it exists)
00891 
00892                     AnnotationClassBase *acb =  AnnotationClassBase::findAnnotationClass(id);
00893                     if (!acb)
00894                     {
00895                         fprintf(stderr, "%s[%d]:  FIXME, cannot find annotation class base for id %d, mode = %s\n", FILE__, __LINE__, id, is_input(sb) ? "deserialize" : "serialize");
00896                         continue;
00897                     }
00898 
00899                     ser_func_t sf = acb->getSerializeFunc();
00900 
00901                     if (NULL == sf)
00902                     {
00903                         continue;
00904                     }
00905 
00906                     ser_rec_t sr;
00907                     sr.acb = acb;
00908                     sr.data = iter->second;
00909                     sr.parent_id = (void *) this;
00910                     sr.sod = sparse;
00911                     my_sers.push_back(sr);
00912                 }
00913 
00914                     ser_ndx_map[this] = get_serializer_index(sb);
00915             }
00916 
00917 #if !defined(SERIALIZATION_DISABLED)
00918             if (!serialize_annotation_list(this, my_sers, sb, tag))
00919             {
00920                 fprintf(stderr, "%s[%d]:  FIXME:  failed to serialize annotation list\n", 
00921                         FILE__, __LINE__);
00922             }
00923 #endif
00924 
00925             if (!add_annotations(sb, this, my_sers))
00926             {
00927                 fprintf(stderr, "%s[%d]:  failed to update annotation list after deserialize\n", 
00928                         FILE__, __LINE__);
00929             }
00930       }
00931 
00932       void annotationsReport()
00933       {
00934           std::vector<AnnotationClassBase *> atypes;
00935           annos_t &l_annos = *getAnnos();
00936 
00937           for (AnnotationClassID id = 0; id < l_annos.size(); ++id)
00938           {
00939               annos_by_type_t *abt = getAnnosOfType(id, false /*don't do create */);
00940               if (NULL == abt) continue;
00941 
00942               annos_by_type_t::iterator iter = abt->find(this);
00943 
00944               if (iter == abt->end()) 
00945               {
00946                   //    fprintf(stderr, "%s[%d]:  nothing for this obj\n", FILE__, __LINE__);
00947                   continue;
00948               }
00949 
00950               AnnotationClassBase *acb =  AnnotationClassBase::findAnnotationClass(id);
00951               if (!acb)
00952               {
00953                   fprintf(stderr, "%s[%d]:  FIXME, cant find anno class base for id %d\n", 
00954                           FILE__, __LINE__, id);
00955                   continue;
00956               }
00957               atypes.push_back(acb);
00958           }
00959 
00960           fprintf(stderr, "%s[%d]:  Sparse(%p):  have %lu annos:\n", FILE__, __LINE__, 
00961               this, (unsigned long) atypes.size());
00962           for (unsigned int i = 0; i < atypes.size(); ++i)
00963           {
00964               fprintf(stderr, "\t%s-%d, %s\n", atypes[i]->getName().c_str(), 
00965                       atypes[i]->getID(), atypes[i]->getTypeName());
00966           }
00967       }
00968 
00969 };
00970 
00971 } // namespace
00972 
00973 #ifdef _MSC_VER
00974 #pragma warning(pop)
00975 #endif
00976 
00977 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1