Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

partition.h

Go to the documentation of this file.
00001 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00002 ////////////////////////////////////////////////////////////////////
00003 //
00004 // Filename : partition.h
00005 //
00006 // This file is a part of the UPPAAL toolkit.
00007 // Copyright (c) 1995 - 2003, Uppsala University and Aalborg University.
00008 // All right reserved.
00009 //
00010 // $Id: partition.h,v 1.9 2005/08/02 09:36:43 adavid Exp $
00011 //
00012 ///////////////////////////////////////////////////////////////////
00013 
00014 #ifndef INCLUDE_DBM_PARTITION_H
00015 #define INCLUDE_DBM_PARTITION_H
00016 
00017 #include "dbm/fed.h"
00018 #include "base/intutils.h"
00019 
00020 /**
00021  * @file The type partition_t defines a partition
00022  * of federations (fed_t) indexed by a given ID.
00023  * The federations added are kept disjoint by
00024  * definition of a partition and the decision of
00025  * where to add the intersecting parts is left to
00026  * the user.
00027  */
00028 
00029 namespace dbm
00030 {
00031     /// Type for partitions, designed to be used as a simple scalar with
00032     /// cheap copies as long as there is no need to modify a partition_t.
00033     class partition_t
00034     {
00035     public:
00036         /** Initialise an empty partition for federations
00037          * of dimension dim.
00038          */
00039         partition_t(cindex_t dim)
00040             : fedTable(dim2ptr(dim)) {}
00041 
00042         /// The copy is a reference copy only.
00043         partition_t(const partition_t& arg)
00044             : fedTable(arg.fedTable) {
00045             assert(fedTable);
00046             if (isPtr()) fedTable->incRef();
00047         }
00048 
00049         /// Copy operator is a reference copy only.
00050         partition_t& operator = (const partition_t& arg) {
00051             assert(fedTable);
00052             if (arg.isPtr()) arg.fedTable->incRef();
00053             if (isPtr()) fedTable->decRef();
00054             fedTable = arg.fedTable;
00055             return *this;
00056         }
00057 
00058         ~partition_t() {
00059             assert(fedTable);
00060             if (isPtr()) fedTable->decRef();
00061         }
00062 
00063         /// Wrappers to the federations of the partition.
00064         /// @see fed_t
00065         void intern();
00066         
00067         /** Add a federation to the partition subset
00068          * 'id'. The intersecting DBMs of fed with
00069          * the partition will be given to fed or one
00070          * subset of the partition and subtracted from
00071          * fed or the partition depending on the decision
00072          * function (@see constructor and setChooser).
00073          * @param id,fed ID of the federation fed to add
00074          * to the partition.
00075          * @pre fed.getDimension() == getDimension()
00076          * @post fed.isEmpty() and convexReduce() is
00077          * maintained on the internal federations.
00078          */
00079         void add(uintptr_t id, fed_t& fed);
00080 
00081         /** @return the federation corresponding to the
00082          * subset 'id' of the partition. If there is no
00083          * such subset, an empty federation is returned.
00084          * @param id ID of the subset to find.
00085          */
00086         fed_t get(uint32_t id) const {
00087             assert(fedTable);
00088             return isPtr() ? fedTable->get(id) : fed_t(edim());
00089         }
00090 
00091         /// @return the dimension of the federations.
00092         cindex_t getDimension() const {
00093             assert(fedTable);
00094             return isPtr() ? fedTable->getDimension() : edim();
00095         }
00096 
00097         /// @return total number of DBMs of all the federations
00098         /// (compute the number on demand).
00099         size_t getNumberOfDBMs() const {
00100             assert(fedTable);
00101             return isPtr() ? fedTable->getNumberOfDBMs() : 0;
00102         }
00103 
00104         /// An entry in the table of federations.
00105         class entry_t
00106         {
00107         public:
00108             entry_t(uint32_t i, const fed_t& f)
00109                 : id(i), fed(f) {}
00110 
00111             uint32_t id; //< ID of the federation, subset of the partition.
00112             fed_t fed;   //< Subset of partition.
00113         };
00114 
00115         /// Iterator to read the federation of the partitions. Only
00116         /// const is provided since modifying federations may destroy
00117         /// the partition.
00118         class const_iterator
00119         {
00120         public:
00121             /// Constructor should be used only by partition_t.
00122             const_iterator(const entry_t* const* start)
00123                 : current(start) {}
00124 
00125             /// Dereference returns a federation.
00126             const fed_t& operator *() {
00127                 assert(current && *current);
00128                 return (*current)->fed;
00129             }
00130             const fed_t* operator ->() {
00131                 assert(current && *current);
00132                 return &(*current)->fed;
00133             }
00134 
00135             bool isNull() const {
00136                 assert(current);
00137                 return *current == NULL;
00138             }
00139             uint32_t id() const {
00140                 assert(current && *current);
00141                 return (*current)->id;
00142             }
00143 
00144             const_iterator& operator ++() {
00145                 assert(current);
00146                 ++current;
00147                 return *this;
00148             }
00149 
00150             /// Standard == and != operators. The implementation uses ||,
00151             /// this is not a typo. The hash table may be sparse internally
00152             /// and the ++ operator stops to increment whenever there is
00153             /// nothing left.
00154             bool operator == (const const_iterator& arg) const {
00155                 return current == arg.current;
00156             }
00157             bool operator != (const const_iterator& arg) const {
00158                 return !(*this == arg);
00159             }
00160             bool operator < (const const_iterator& arg) const {
00161                 return current < arg.current;
00162             }
00163 
00164         private:
00165             const entry_t* const* current; /// Current position in the table.
00166         };
00167 
00168         /// Standard begin() and end() for const_iterator.
00169         const_iterator begin() const {
00170             assert(fedTable);
00171             return isPtr()
00172                 ? const_iterator(fedTable->getBeginTable())
00173                 : const_iterator(NULL);
00174         }
00175         const_iterator end() const {
00176             assert(fedTable);
00177             return isPtr()
00178                 ? const_iterator(fedTable->getEndTable())
00179                 : const_iterator(NULL);
00180         }
00181 
00182     private:
00183 
00184         /// The federation table (a simple hash table with chained collisions
00185         /// on the table entries) to access the subsets (fed_t) of the partition.
00186         class fedtable_t
00187         {
00188         public:
00189             static fedtable_t* create(cindex_t dim);
00190 
00191             /// @pre !isMutable() or it is stupid to call this
00192             /// @post refCounter is decremented
00193             fedtable_t* copy();
00194 
00195             void incRef() {
00196                 refCounter++;
00197             }
00198             void decRef() {
00199                 assert(refCounter > 0);
00200                 if (!--refCounter) {
00201                     remove();
00202                 }
00203             }
00204             bool isMutable() {
00205                 assert(refCounter > 0);
00206                 return refCounter == 1;
00207             }
00208 
00209             /// Access methods.
00210             entry_t** getTable() { return table; }
00211             const entry_t* const* getBeginTable() const { return table; }
00212             const entry_t* const* getEndTable()   const { return getBeginTable() + getSize(); }
00213             cindex_t getDimension() const { return all.getDimension(); }
00214             size_t getSize() const { return mask + 1; }
00215 
00216             /// Remove (deallocate) this fedTable. @pre refCounter == 0.
00217             void remove();
00218 
00219             /// @return the fed_t corresponding to the partition's subset id.
00220             /// The federation is empty if the subset id is not defined.
00221             fed_t get(uint32_t id) const;
00222 
00223             /// Add a federation to the subset 'id' of the partition.
00224             /// @return true if this table must be resized.
00225             bool add(uint32_t id, fed_t& fed);
00226 
00227             /// @return a resized table.
00228             /// @pre isMutable()
00229             /// @post this table is deallocated.
00230             fedtable_t* larger();
00231 
00232             /// @return total number of DBMs.
00233             size_t getNumberOfDBMs() const;
00234 
00235         private:
00236             /// Constants for initialization.
00237             enum {
00238                 INIT_POWER = 1,
00239                 INIT_SIZE = (1 << INIT_POWER),
00240                 INIT_MASK = (INIT_SIZE - 1)
00241             };
00242 
00243             /// Private constructors because the allocation is special.
00244             fedtable_t(cindex_t d, size_t nb, uint32_t m)
00245                 : refCounter(1), all(d), nbEntries(nb), mask(m) {
00246                 // table not initialized
00247             }
00248 
00249             /// Default initial constructor.
00250             fedtable_t(cindex_t d)
00251                 : refCounter(1), all(d), nbEntries(0), mask(INIT_MASK) {
00252                 base_resetSmall(table, INIT_SIZE);
00253             }
00254 
00255             uint32_t refCounter; //< standard reference counter
00256             fed_t all;           //< union of all federations
00257             size_t nbEntries;    //< number of non null entries
00258             uint32_t mask;       //< bit mask for access, table size = mask+1
00259             entry_t *table[];    //< the table of federations.
00260         };
00261 
00262         /// Check that the referenced fedTable is mutable (refCounter == 1)
00263         /// and make a copy if necessary.
00264         void checkMutable() {
00265             assert(fedTable);
00266             if (!fedTable->isMutable()) {
00267                 fedTable = fedTable->copy();
00268             }
00269         }
00270 
00271         static fedtable_t* dim2ptr(cindex_t dim) {
00272             return (fedtable_t*) ((dim << 1) | 1);
00273         }
00274         bool isPtr() const {
00275             return (((uintptr_t)fedTable) & 1) == 0;
00276         }
00277         cindex_t edim() const {
00278             assert(!isPtr());
00279             return ((uintptr_t)fedTable) >> 1;
00280         }
00281 
00282         fedtable_t *fedTable; //< table of federations.
00283     };
00284 }
00285 
00286 #endif // INCLUDE_DBM_PARTITION_H

Generated on Fri Jun 30 00:02:45 2006 for Module dbm by  doxygen 1.4.2