home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 6.ddi / MWHC.006 / R2 < prev    next >
Encoding:
Text File  |  1992-06-07  |  6.2 KB  |  212 lines

  1. #ifndef __RWTVREF_H__
  2. #define __RWTVREF_H__
  3. pragma push_align_members(64);
  4.  
  5. /*
  6.  * RWTVirtualRef<T>: A typed interface to RWVirtualRef
  7.  *
  8.  * $Header:   E:/vcs/rw/tvref.h_v   1.1   17 Mar 1992 19:41:40   KEFFER  $
  9.  *
  10.  ****************************************************************************
  11.  *
  12.  * Rogue Wave Software, Inc.
  13.  * P.O. Box 2328
  14.  * Corvallis, OR 97339
  15.  *
  16.  * Copyright (C) 1992. This software is subject to copyright 
  17.  * protection under the laws of the United States and other countries.
  18.  *
  19.  ***************************************************************************
  20.  *
  21.  * Although this array could be used by the end user it is really intended
  22.  * to be the reference part of a reference counted array.  It uses
  23.  * pure copy semantics and hence is relatively slow.  
  24.  *
  25.  * It inherits from RWReference and hence contains a reference count.
  26.  * This is used to implement copy-on-write reference counting as was
  27.  * done with class RWTValVirtualArray<T>.
  28.  *
  29.  * Assumes that T has:
  30.  *   - well-defined copy constructor (T::T(const T&) or equiv.);
  31.  *   - well-defined assignment operator (T::operator=(const T&) or equiv.).
  32.  *
  33.  * Note that the location in physical memory of a particular index 
  34.  * of the array can change from invocation to invocation.  Hence,
  35.  * the address of an element should never be taken. 
  36.  *
  37.  ***************************************************************************
  38.  *
  39.  * $Log:   E:/vcs/rw/tvref.h_v  $
  40.  * 
  41.  *    Rev 1.1   17 Mar 1992 19:41:40   KEFFER
  42.  * 
  43.  *    Rev 1.0   11 Mar 1992 14:10:00   KEFFER
  44.  * Initial revision.
  45.  */
  46.  
  47. #include "rw/vref.h"
  48. #include "rw/toolerr.h"
  49.  
  50. template <class T> class RWTVirtualRef : public RWVirtualRef {
  51.  
  52. public:
  53.  
  54.   RWTVirtualRef(long size, RWVirtualPageHeap* h);
  55.   RWTVirtualRef(RWTVirtualRef<T>&);        // Takes deep copy.
  56.  
  57.   T            val(long i);
  58.   void            set(long i, T v);
  59.   void            set(long start, long extent, T v);
  60.   virtual void        conformalCopy(long start1, RWVirtualRef& v2, long start2, long N);
  61. };
  62.  
  63.  
  64. /****************************************************************
  65.  ****************************************************************
  66.  *                                *
  67.  *            RWTVirtualRef<T>            *
  68.  *            Definitions                *
  69.  *                                *
  70.  ****************************************************************
  71.  ****************************************************************/
  72.  
  73. template <class T>
  74. RWTVirtualRef<T>::RWTVirtualRef(long size, RWVirtualPageHeap* heap) :
  75.   RWVirtualRef(size, sizeof(T), heap)
  76. {
  77. }
  78.  
  79. // Copy constructor: use copy semantics
  80. template <class T>
  81. RWTVirtualRef<T>::RWTVirtualRef(RWTVirtualRef<T>& v) :
  82.   RWVirtualRef(v)
  83. {
  84.   conformalCopy(0, (RWVirtualRef&)v, 0, _length);    // Painful, but unavoidable w. copy semantics!
  85. }
  86.  
  87. // Return the value at index idx
  88. template <class T> T
  89. RWTVirtualRef<T>::val(long idx)
  90. {
  91.   RWPageSlot slot;
  92.   unsigned rem;
  93.   findLocation(idx, slot, rem);
  94.   T* p = (T*)lock(slot);
  95.   T ret = p[rem];
  96.   unlock(slot);
  97.   return ret;
  98. }
  99.  
  100. // Set the item at index idx to "val"
  101. template <class T> void
  102. RWTVirtualRef<T>::set(long idx, T val)
  103. {
  104.   RWPageSlot slot;
  105.   unsigned rem;
  106.   findLocation(idx, slot, rem);
  107.   T* p = (T*)lock(slot);
  108.   p[rem] = val;
  109.   dirty(slot);
  110.   unlock(slot);
  111. }
  112.  
  113. // Set "extent" items starting at index "start" to the value "val":
  114. template <class T> void
  115. RWTVirtualRef<T>::set(long start, long extent, T val)
  116. {
  117.   long stop = start + extent - 1L;
  118.   RWPageSlot startSlot, stopSlot;
  119.   unsigned startRem, stopRem;
  120.   findLocation(start, startSlot, startRem);
  121.   findLocation(stop,  stopSlot,  stopRem);
  122.  
  123.   for (RWPageSlot slot = startSlot; slot <= stopSlot; slot++) {
  124.     unsigned startIdx = slot==startSlot ? startRem : 0;
  125.     unsigned endIdx   = slot==stopSlot  ? stopRem  : _nPerPage-1;
  126.     T* p = (T*)lock(slot);
  127.     for (int i = startIdx; i<=endIdx; i++){
  128.       p[i] = val;
  129.     }
  130.     dirty(slot);
  131.     unlock(slot);
  132.   }
  133. }
  134.  
  135. /*
  136.  * Copies the data in v2 starting at index start2 into self,
  137.  * starting at index start1.
  138.  * Logically:
  139.  *
  140.  *   for(i=0; i<N; i++)
  141.  *     (*this)[i+start1] = v2[i+start2];
  142.  *
  143.  * although the copy is actually done by minimizing the number of page
  144.  * locks and, hence, page swaps.
  145.  *
  146.  */
  147. template <class T> void
  148. RWTVirtualRef<T>::conformalCopy(long start1,
  149.                 RWVirtualRef& v2,
  150.                 long start2,
  151.                 long N)
  152. {
  153.   RWPageSlot startSlot1, stopSlot1, lockedSlot1, lockedSlot2, slot2;
  154.   unsigned   startRem1,  stopRem1,  lockedRem1,  lockedRem2,  rem2;
  155.   long stop1 = start1 + N - 1L;
  156.   findLocation(start1, startSlot1, startRem1);
  157.   findLocation(stop1,  stopSlot1,  stopRem1);
  158.  
  159.   long idx2 = start1 > start2 ? start2 : start2 + N - 1L;
  160.  
  161.   v2.findLocation(idx2, lockedSlot2, lockedRem2);
  162.   T* p2 = (T*)v2.lock(lockedSlot2);
  163.  
  164.   if (start1 > start2) {
  165.  
  166.     // Work upwards (from left to right)
  167.     for(lockedSlot1=startSlot1; lockedSlot1<=stopSlot1; lockedSlot1++){
  168.       unsigned leftIdx  = lockedSlot1==startSlot1 ? startRem1 : 0;
  169.       unsigned rightIdx = lockedSlot1==stopSlot1  ? stopRem1  : _nPerPage-1;
  170.       T* p1 = (T*)lock(lockedSlot1);
  171.       for (unsigned i = leftIdx; i<=rightIdx; i++){
  172.         v2.findLocation(idx2++, slot2, rem2);
  173.         if (lockedSlot2 != slot2){
  174.           v2.unlock(lockedSlot2);
  175.           p2 = (T*)v2.lock(lockedSlot2=slot2);
  176.         }
  177.         p1[i] = p2[rem2];
  178.       }
  179.       dirty(lockedSlot1);
  180.       unlock(lockedSlot1);
  181.     }
  182.     v2.unlock(lockedSlot2);
  183.   }
  184.   else {
  185.  
  186.     unsigned countSlot = stopSlot1 - startSlot1 + 1;
  187.  
  188.     // Work downwards (from right to left)
  189.     while (countSlot--) {
  190.       lockedSlot1 = startSlot1 + countSlot;
  191.       unsigned leftIdx  = lockedSlot1==startSlot1 ? startRem1 : 0;
  192.       unsigned rightIdx = lockedSlot1==stopSlot1  ? stopRem1  : _nPerPage-1;
  193.       unsigned countIdx = rightIdx - leftIdx + 1;
  194.       T* p1 = (T*)lock(lockedSlot1);
  195.       while (countIdx--) {
  196.         v2.findLocation(idx2--, slot2, rem2);
  197.         if (lockedSlot2 != slot2){
  198.           v2.unlock(lockedSlot2);
  199.           p2 = (T*)v2.lock(lockedSlot2=slot2);
  200.         }
  201.         p1[rightIdx--] = p2[rem2];
  202.       }
  203.       dirty(lockedSlot1);
  204.       unlock(lockedSlot1);
  205.     }
  206.     v2.unlock(lockedSlot2);
  207.   }
  208. }
  209.  
  210. pragma pop_align_members();
  211. #endif    /* __RWTVREF_H__ */
  212.