obslist.h

Go to the documentation of this file.
00001 /**
00002  * \file obslist.h <mi32/obslist.h>
00003  * \brief Define OBSERVABLE_LIST template
00004  *
00005  * \if NODOC
00006  * $Id: obslist.h_v 1.7 2003/09/15 13:49:56 fileserver!dwilliss Exp $
00007  *
00008  * $Log: obslist.h_v $
00009  * Revision 1.7  2003/09/15 13:49:56  fileserver!dwilliss
00010  * Doxygen
00011  *
00012  * Revision 1.6  2003/01/30 17:43:16  mju
00013  * Use container class name for iterator so get the one we want.
00014  *
00015  * Revision 1.5  2002/06/25 16:35:16  mju
00016  * Make NotifyChanged() non-const as calls non-const method on member.
00017  *
00018  * Revision 1.4  2001/01/24 20:39:36  mju
00019  * Fix member access.
00020  *
00021  * Revision 1.3  2001/01/24 13:53:23  mju
00022  * OBSERVER is now our friend.
00023  *
00024  * Revision 1.2  2001/01/23 23:01:59  mju
00025  * Add NotifyChange.
00026  *
00027  * Revision 1.1  2001/01/23 15:42:29  mju
00028  * Initial revision
00029  *
00030  * \endif
00031 **/
00032 
00033 #ifndef INC_MI32_OBSLIST_H
00034 #define INC_MI32_OBSLIST_H
00035 
00036 #ifndef  INC_MI32_STDDEFNS_H
00037    #include <mi32/stddefns.h>
00038 #endif
00039 
00040 #ifndef  INC_MI32_STDANSIC_H
00041    #include <mi32/stdansic.h>
00042 #endif
00043 
00044 #ifndef  INC_MI32_MIODEFNS_H
00045    #include <mi32/miodefns.h>
00046 #endif
00047 
00048 #ifndef  INC_MI32_OBSERVER_H
00049    #include <mi32/observer.h>
00050 #endif
00051 
00052 // When modifying this template consider making similar modifications to MILIST<>.
00053 
00054 //! Template for a list container which supports the OBSERVER pattern (see observer.h).
00055 //! An observer is defined by inheriting from OBSERVABLE_LIST<type>::OBSERVER and overriding
00056 //! the desired virtual methods.  Each list may have as many OBSERVERs as desired, however,
00057 //! a particular OBSERVER may only be associated with one list at a time.
00058 //! Notification when items are added, removed, reordered or sorted is automatic.  However,
00059 //! if an item is changed (through a non-const reference) then notification is the responsibility
00060 //! of the programmer.  NotifyChanged() should be called after the change is made so that all
00061 //! observers are notified of the change.
00062 template <class _LIT> class OBSERVABLE_LIST {
00063 
00064    private:
00065       #ifndef GENERATING_DOXYGEN_OUTPUT
00066 
00067       //! Internal list item holder structure
00068       struct LISTITEM {
00069          _LIT m_Item;                  //!< Actual template item
00070          LISTITEM *m_Next, *m_Prev;
00071 
00072          LISTITEM (                 //! Constructor
00073             const _LIT& item
00074             ) : m_Item(item), m_Prev(0), m_Next(0) {}
00075 
00076          void Swap (                //! Efficient swap method that does not call template's methods
00077             LISTITEM& other
00078             ) {
00079             UINT8 buffer[sizeof(LISTITEM)];
00080             memcpy(buffer, this, sizeof(LISTITEM));
00081             memcpy(this, &other, sizeof(LISTITEM));
00082             memcpy(&other, buffer, sizeof(LISTITEM));
00083             return;
00084             }
00085          };
00086 
00087       #endif //!< GENERATING_DOXYGEN_OUTPUT
00088 
00089    public:
00090 
00091       class OBSERVER;
00092       friend class OBSERVER;
00093 
00094       //! Base class for observers of this list to inherit from.
00095       class OBSERVER : public OBSERVER_BASE {
00096          public:
00097 
00098             //! Constructor.
00099             OBSERVER (
00100                OBSERVABLE_LIST<_LIT>& list
00101                ): OBSERVER_BASE(list.m_ObserverMgr) { }
00102 
00103             //! Called when item has been changed through non-const reference.
00104             virtual void OnChanged (
00105                const _LIT& item              //!< Reference to item which was changed
00106                ) { }
00107 
00108             //! Called before item is repositioned in list.
00109             virtual void OnChangeOrderBegin (
00110                const _LIT& item              //!< Reference to item before position changed
00111                ) { }
00112 
00113             //! Called after item is repositioned in list.
00114             virtual void OnChangeOrderEnd (
00115                const _LIT& item              //!< Reference to item after position changed
00116                ) { }
00117 
00118             //! Called after list has been cleared.
00119             virtual void OnClear (
00120                ) { }
00121 
00122             //! Called after item inserted into list.
00123             virtual void OnInsert (
00124                const _LIT& item              //!< Reference to item which has been inserted
00125                ) { }
00126 
00127             //! Called when item about to be removed from list.
00128             virtual void OnRemove (
00129                const _LIT& item              //!< Reference to item which is about to be removed
00130                ) { }
00131 
00132             //! Called when list has been sorted.
00133             virtual void OnSort (
00134                ) { }
00135 
00136          };
00137 
00138       class ITERATOR;               
00139       class CONST_ITERATOR;
00140       friend class ITERATOR;
00141       friend class CONST_ITERATOR;
00142 
00143       //! Constant bidirectional iterator.
00144       class CONST_ITERATOR {
00145          public:
00146 
00147             CONST_ITERATOR (           //! Default constructor
00148                ) {}
00149 
00150             CONST_ITERATOR (           //! Internal constructor
00151                LISTITEM *item
00152                ) : m_Ptr(item) {}
00153 
00154             CONST_ITERATOR (           //! Copy constructor
00155                const ITERATOR& item
00156                ) : m_Ptr(item.m_Ptr) {}
00157 
00158             const _LIT& operator* (    //! Dereference operator, returns reference to templated item
00159                ) const {
00160                return (m_Ptr->m_Item);
00161                }
00162 
00163             const _LIT* operator-> (   //! Dereference operator, returns pointer to templated item
00164                ) const {
00165                return (&**this);
00166                }
00167 
00168             //! Pre-increment operator.
00169             CONST_ITERATOR& operator++ (
00170                ) {
00171                m_Ptr = m_Ptr->m_Next;
00172                return (*this);
00173                }
00174 
00175             //! Post-increment operator.
00176             CONST_ITERATOR operator++(int
00177                ) {
00178                CONST_ITERATOR temp = *this;
00179                ++*this;
00180                return (temp);
00181                }
00182 
00183             //! Pre-decrement operator.
00184             CONST_ITERATOR& operator-- (
00185                ) {
00186                m_Ptr = m_Ptr->m_Prev;
00187                return (*this);
00188                }
00189 
00190             //! Post-decrement operator.
00191             CONST_ITERATOR operator--(int
00192                ) {
00193                CONST_ITERATOR temp = *this;
00194                --*this;
00195                return (temp);
00196                }
00197 
00198             bool operator== (          //! Equality operator
00199                const CONST_ITERATOR& rhs
00200                ) const {
00201                return (m_Ptr == rhs.m_Ptr);
00202                }
00203 
00204             bool operator!= (          //! Inequality operator
00205                const CONST_ITERATOR& rhs
00206                ) const {
00207                return (!(*this == rhs));
00208                }
00209 
00210             LISTITEM *GetNode (        //! Internal, get a LISTITEM*
00211                ) const {
00212                return (m_Ptr);
00213                }
00214 
00215          protected:
00216 
00217             LISTITEM *m_Ptr;
00218          }; //! End of CONST_ITERATOR
00219 
00220       //! Non-constant bidirectional iterator.
00221       class ITERATOR : public CONST_ITERATOR {
00222          public:
00223 
00224             ITERATOR (                 //! Default constructor
00225                ) {}
00226 
00227             ITERATOR (                 //! Internal constructor
00228                LISTITEM *item
00229                ) : CONST_ITERATOR(item) {}
00230 
00231             _LIT& operator* (          //! Dereference operator, returns reference to templated item
00232                ) const {
00233                return (m_Ptr->m_Item);
00234                }
00235 
00236             _LIT* operator-> (         //! Dereference operator, returns pointer to templated item
00237                ) const {
00238                return (&**this);
00239                }
00240 
00241             //! Pre-increment operator.
00242             ITERATOR& operator++ (
00243                ) {
00244                m_Ptr = m_Ptr->m_Next;
00245                return (*this);
00246                }
00247 
00248             //! Post-increment operator.
00249             ITERATOR operator++(int
00250                ) {
00251                ITERATOR temp = *this;
00252                ++*this;
00253                return (temp);
00254                }
00255 
00256             //! Pre-decrement operator.
00257             ITERATOR& operator-- (
00258                ) {
00259                m_Ptr = m_Ptr->m_Prev;
00260                return (*this);
00261                }
00262 
00263             //! Post-increment operator.
00264             ITERATOR operator--(int
00265                ) {
00266                ITERATOR temp = *this;
00267                --*this;
00268                return (temp);
00269                }
00270 
00271             //! Equality operator
00272             bool operator== (
00273                const ITERATOR& rhs
00274                ) const {
00275                return (m_Ptr == rhs.m_Ptr);
00276                }
00277 
00278             //! Inequality operator
00279             bool operator!= (
00280                const ITERATOR& rhs
00281                ) const {
00282                return (!(*this == rhs));
00283                }
00284 
00285          }; //! End of ITERATOR
00286 
00287 
00288       // CONSTRUCTION / DESTRUCTION
00289 
00290       //! Construct empty list.
00291       OBSERVABLE_LIST (
00292          ) : m_Head(0), m_NumItems(0) {
00293          MmAllocCExc((void **)&m_Head, sizeof(LISTITEM));      //! Deliberate MmAllocC instead of new
00294          m_Head->m_Next = m_Head->m_Prev = m_Head;
00295          }
00296 
00297       //! Copy constructor, copies list items, not observers.
00298       OBSERVABLE_LIST (                   
00299          const OBSERVABLE_LIST<_LIT>& rhs
00300          ) : m_Head(0), m_NumItems(0) {
00301          MmAllocCExc((void **)&m_Head, sizeof(LISTITEM));      //! Deliberate MmAllocC instead of new
00302          m_Head->m_Next = m_Head->m_Prev = m_Head;
00303          for (CONST_ITERATOR it = rhs.Begin(); (it != rhs.End()); ++it) {
00304             Insert(End(), *it);
00305             }
00306          }
00307 
00308       //! Destructor.
00309       ~OBSERVABLE_LIST (                     
00310          ) {
00311          Clear();
00312          MmFree(m_Head);
00313          }
00314 
00315       //! Assignment operator, copies list items, not observers.
00316       OBSERVABLE_LIST<_LIT>& operator= (     
00317          const OBSERVABLE_LIST<_LIT>& rhs
00318          ) {
00319          if (this != &rhs) {
00320             Clear();
00321             for (CONST_ITERATOR it = rhs.Begin(); (it != rhs.End()); ++it) {
00322                Insert(End(), *it);
00323                }
00324             }
00325          return (*this);
00326          }
00327 
00328       //! Return an ITERATOR that refers to the beginning of the list.
00329       ITERATOR Begin (              
00330          ) { return (ITERATOR(m_Head->m_Next)); }
00331 
00332       //! Return a CONST_ITERATOR that refers to the beginning of the list.
00333       CONST_ITERATOR Begin (       
00334          ) const { return (CONST_ITERATOR(m_Head->m_Next)); }
00335 
00336       //! Remove all entries from the list.
00337       void Clear (                  
00338          ) {
00339          for (ITERATOR it = Begin(); (it != End()); ) {
00340             Remove(it++,false);
00341             }
00342          m_ObserverMgr.NotifyClear();
00343          return;
00344          }
00345 
00346       //! Return an ITERATOR that refers to the end of the list, not a valid list item.
00347       ITERATOR End (                
00348          ) { return (ITERATOR(m_Head)); }
00349 
00350       //! Return a CONST_ITERATOR that refers to the end of the list, not a valid list item.
00351       CONST_ITERATOR End (          
00352          ) const { return (CONST_ITERATOR(m_Head)); }
00353          
00354       //! Return a reference to a const _LIT item from the front of the list
00355       const _LIT& GetBack (
00356          ) const { return (*(--End())); }
00357 
00358       //! Return a reference to a _LIT item from the front of the list
00359       _LIT& GetBack (
00360          ) { return (*(--End())); }
00361 
00362       //! Return a reference to a const _LIT item from the front of the list
00363       const _LIT& GetFront (
00364          ) const { return (*Begin()); }
00365 
00366       //! Return a reference to a _LIT item from the front of the list
00367       _LIT& GetFront (
00368          ) { return (*Begin()); }
00369 
00370       //! Return the number of items in the list.
00371       INT32 GetNumItems (           
00372          ) const { return (m_NumItems); }
00373 
00374       //! Insert an item into the place BEFORE the iterator.
00375       //! @return Reference to new item in list (not same as 'item' parameter as will be copied).
00376       _LIT& Insert (                
00377          ITERATOR p,
00378          const _LIT& item
00379          ) {
00380          LISTITEM *obj = p.GetNode();
00381          LISTITEM *newitem = new LISTITEM(item);
00382          newitem->m_Next = obj;
00383          newitem->m_Prev = obj->m_Prev;
00384          obj->m_Prev->m_Next = newitem;
00385          obj->m_Prev = newitem;
00386          m_NumItems ++;
00387          m_ObserverMgr.NotifyInsert(newitem->m_Item);
00388          return (newitem->m_Item);
00389          }
00390 
00391       //! Determine if any list entries exist.
00392       bool IsEmpty (                
00393          ) const { return (m_NumItems == 0); }
00394 
00395       //! Moves the item referenced by the iterator toward the beginning of the list.
00396       void Lower (
00397          ITERATOR it
00398          ) {
00399          if (it == Begin()) return;
00400          m_ObserverMgr.NotifyChangeOrderBegin(*it);
00401          ITERATOR lower = it;
00402          --lower;
00403          RemoveItem(it);
00404          InsertItem(it, lower);
00405          m_ObserverMgr.NotifyChangeOrderEnd(*it);
00406          return;
00407          }
00408 
00409       //! Moves the item referenced by the iterator to the back of the list
00410       void MoveToBack (
00411          ITERATOR it
00412          ) {
00413          if (it == --End()) return;
00414          m_ObserverMgr.NotifyChangeOrderBegin(*it);
00415          RemoveItem(it);
00416          InsertItem(it, End());
00417          m_ObserverMgr.NotifyChangeOrderEnd(*it);
00418          return;
00419          }
00420 
00421       //! Moves the item referenced by the iterator to the front of the list
00422       void MoveToFront (
00423          ITERATOR it
00424          ) {
00425          if (it == Begin()) return;
00426          m_ObserverMgr.NotifyChangeOrderBegin(*it);
00427          RemoveItem(it);
00428          InsertItem(it, Begin());
00429          m_ObserverMgr.NotifyChangeOrderEnd(*it);
00430          return;
00431          }
00432 
00433       //! Notify all list observers that a change has been made to the specified item.
00434       //! There is no verification that the item is actually in the list.
00435       void NotifyChanged (
00436          const _LIT& item
00437          ) { m_ObserverMgr.NotifyChanged(item); }
00438 
00439       //! Insert an item at the beginning of the list.
00440       //! @return Reference to new item in list (not same as 'item' parameter as will be copied).
00441       _LIT& PushFront (             
00442          const _LIT& item
00443          ) { return (Insert(Begin(), item)); }
00444 
00445       //! Remove an item from the beginning of the list.
00446       void PopFront (               
00447          ) { Remove(Begin()); }
00448 
00449       //! Insert an item on the end of the list.
00450       //! @return Reference to new item in list (not same as 'item' parameter as will be copied).
00451       _LIT& PushBack (              
00452          const _LIT& item
00453          ) { return (Insert(End(), item)); }
00454 
00455       //! Remove the last item from the list.
00456       void PopBack (                
00457          ) { Remove(--End()); }
00458          
00459       //! Moves the item referenced by the iterator toward the end of the list.
00460       void Raise (
00461          ITERATOR it
00462          ) {
00463          if (it == --End()) return;
00464          m_ObserverMgr.NotifyChangeOrderBegin(*it);
00465          ITERATOR upper = it;
00466          ++upper;
00467          RemoveItem(it);
00468          InsertItem(it, ++upper);
00469          m_ObserverMgr.NotifyChangeOrderEnd(*it);
00470          return;
00471          }
00472 
00473       //! Remove item specified by reference from the list.
00474       void Remove (
00475          const _LIT& item                 //!< Item to remove
00476          ) {
00477          for (ITERATOR it = Begin(); (it != End()); ) {
00478             if ((&*it) == &item) {
00479                Remove(it++);
00480                }
00481             else {
00482                ++it;
00483                }
00484             }
00485          return;
00486          }
00487 
00488       //! Remove item specified by ITERATOR from the list.
00489       //! Do not use the specified iterator after using this method as it will be invalid.
00490       void Remove (
00491          ITERATOR it,
00492          bool notify = true
00493          ) {
00494          RemoveItem(it);
00495          if (notify) m_ObserverMgr.NotifyRemove(*it);
00496          delete it.GetNode();
00497          return;
00498          }
00499 
00500       //! Remove a range of items from the list.
00501       void Remove (
00502          ITERATOR start,                  //!< Iterator for first item to remove
00503          ITERATOR end                     //!< Ending item, exclusive, will not be removed
00504          ) {
00505          for (ITERATOR it = start; (it != end); ) {
00506             Remove(it++);
00507             }
00508          return;
00509          }
00510 
00511       //! Remove item at specified position.
00512       void RemovePos (
00513          int pos                          //!< Position starting at 0 for beginning of list
00514          ) {
00515          ITERATOR it;
00516          for (it = Begin(); (it != End() && pos > 0); --pos)
00517             ;
00518          if (it != End()) Remove(it);
00519          return;
00520          }
00521 
00522       //! Sort the list in operator< () order.
00523       void Sort (
00524          ) {
00525          SortItems();
00526          m_ObserverMgr.NotifySort();
00527          return;
00528          }
00529 
00530       //! Sort the list in operator< () order.
00531       void Sort (                   
00532          bool (*PredFunc)(const _LIT& lhs, const _LIT& rhs)
00533          ) {
00534          SortItems(PredFunc);
00535          m_ObserverMgr.NotifySort();
00536          return;
00537          }
00538 
00539       //! Remove duplicate entries.
00540       void RemoveDuplicates (       
00541          ) {
00542          if (m_NumItems < 2) return;
00543          for (ITERATOR check = Begin(); (check != End()); ++check) {
00544             for (ITERATOR it = ++check; (it != End()); ++it) {
00545                if (*check == *it) {
00546                   ITERATOR prev = --it;
00547                   Remove(it);
00548                   it = prev;
00549                   }
00550                }
00551             }
00552          return;
00553          }
00554 
00555 
00556    private:
00557       #ifndef GENERATING_DOXYGEN_OUTPUT
00558 
00559       class OBSERVERMGR : public SUBJECT<OBSERVER> {
00560          public:
00561             void NotifyChanged (
00562                const _LIT& item
00563                ) {
00564                for (OBSERVERMGR::ITERATOR it = ObserverBegin(); (it != ObserverEnd()); ++it) {
00565                   (*it)->OnChanged(item);
00566                   }
00567                }
00568 
00569             void NotifyChangeOrderBegin (
00570                const _LIT& item
00571                ) {
00572                for (OBSERVERMGR::ITERATOR it = ObserverBegin(); (it != ObserverEnd()); ++it) {
00573                   (*it)->OnChangeOrderBegin(item);
00574                   }
00575                }
00576 
00577             void NotifyChangeOrderEnd (
00578                const _LIT& item
00579                ) {
00580                for (OBSERVERMGR::ITERATOR it = ObserverBegin(); (it != ObserverEnd()); ++it) {
00581                   (*it)->OnChangeOrderEnd(item);
00582                   }
00583                }
00584 
00585             void NotifyClear (
00586                ) {
00587                for (OBSERVERMGR::ITERATOR it = ObserverBegin(); (it != ObserverEnd()); ++it) {
00588                   (*it)->OnClear();
00589                   }
00590                }
00591 
00592             void NotifyInsert (
00593                const _LIT& item
00594                ) {
00595                for (OBSERVERMGR::ITERATOR it = ObserverBegin(); (it != ObserverEnd()); ++it) {
00596                   (*it)->OnInsert(item);
00597                   }
00598                }
00599 
00600             void NotifyRemove (
00601                const _LIT& item
00602                ) {
00603                for (OBSERVERMGR::ITERATOR it = ObserverBegin(); (it != ObserverEnd()); ++it) {
00604                   (*it)->OnRemove(item);
00605                   }
00606                }
00607 
00608             void NotifySort (
00609                ) {
00610                for (OBSERVERMGR::ITERATOR it = ObserverBegin(); (it != ObserverEnd()); ++it) {
00611                   (*it)->OnSort();
00612                   }
00613                }
00614          };
00615 
00616       void InsertItem (
00617          ITERATOR it,
00618          ITERATOR place
00619          ) {
00620          LISTITEM *q = it.GetNode();
00621          LISTITEM *after = place.GetNode();
00622 
00623          q->m_Next = after;
00624          q->m_Prev = after->m_Prev;
00625          after->m_Prev->m_Next = q;
00626          after->m_Prev = q;
00627          m_NumItems ++;
00628          return;
00629          }
00630 
00631       void RemoveItem (
00632          ITERATOR it
00633          ) {
00634          LISTITEM *q = it.GetNode();
00635          q->m_Next->m_Prev = q->m_Prev;
00636          q->m_Prev->m_Next = q->m_Next;
00637          m_NumItems --;
00638          return;
00639          }
00640          
00641       void SortItems (                    //! Sort the list in operator< () order
00642          ) {
00643          if (m_NumItems < 2) return;
00644          OBSERVABLE_LIST<_LIT> NewList;
00645          ITERATOR *ItArray = new ITERATOR[m_NumItems+1];
00646          ItArray[0] = NewList.End();
00647 
00648          while (m_NumItems > 0) {
00649             ITERATOR item = Begin();
00650             RemoveItem(item);
00651 
00652             INT32 index = 0;
00653             if (NewList.m_NumItems) {
00654                INT32 Left = 0, Right = NewList.m_NumItems-1;
00655                do {
00656                   index = (Left+Right) / 2;
00657                   if (*item < *ItArray[index]) {
00658                      Right = index - 1;
00659                      }
00660                   else {
00661                      Left = ++index;         //!< The insert method is a place behind, add one to index in case Left > Right
00662                      }
00663                   } while (Left <= Right);
00664                }
00665             
00666             ITERATOR place = ItArray[index];
00667             for (int i = NewList.m_NumItems+1; (i > index); --i) ItArray[i] = ItArray[i-1];
00668             ItArray[index] = item;
00669             NewList.InsertItem(item, place);
00670             }
00671          
00672          delete [] ItArray;
00673          LISTITEM *temp = m_Head;      //!< Switch headers
00674          m_Head = NewList.m_Head;
00675          NewList.m_Head = temp;
00676          m_NumItems = NewList.m_NumItems;
00677          return;
00678          }
00679 
00680       void SortItems (                    //! Sort the list in operator< () order
00681          bool (*PredFunc)(const _LIT& lhs, const _LIT& rhs)
00682          ) {
00683          if (m_NumItems < 2) return;
00684          OBSERVABLE_LIST<_LIT> NewList;
00685          ITERATOR *ItArray = new ITERATOR[m_NumItems+1];
00686          ItArray[0] = NewList.End();
00687 
00688          while (m_NumItems > 0) {
00689             ITERATOR item = Begin();
00690             RemoveItem(item);
00691 
00692             INT32 index = 0;
00693             if (NewList.m_NumItems) {
00694                INT32 Left = 0, Right = NewList.m_NumItems-1;
00695                do {
00696                   index = (Left+Right) / 2;
00697                   if (PredFunc(*item, *ItArray[index])) {
00698                      Right = index - 1;
00699                      }
00700                   else {
00701                      Left = ++index;         //!< The insert method is a place behind, add one to index in case Left > Right
00702                      }
00703                   } while (Left <= Right);
00704                }
00705 
00706             ITERATOR place = ItArray[index];
00707             for (int i = NewList.m_NumItems + 1; (i > index); --i) ItArray[i] = ItArray[i-1];
00708             ItArray[index] = item;
00709             NewList.InsertItem(item, place);
00710             }
00711          
00712          delete [] ItArray;
00713          LISTITEM *temp = m_Head;      //!< Switch headers
00714          m_Head = NewList.m_Head;
00715          NewList.m_Head = temp;
00716          m_NumItems = NewList.m_NumItems;
00717          return;
00718          }
00719 
00720       LISTITEM *m_Head;
00721       INT32 m_NumItems;
00722       OBSERVERMGR m_ObserverMgr;
00723       #endif // GENERATING_DOXYGEN_OUTPUT
00724 
00725    };
00726 
00727 #endif      //!< INC_MI32_OBSLIST_H

Generated on Tue Dec 14 13:18:31 2004 for TNTsdk by  doxygen 1.3.8-20040913