home *** CD-ROM | disk | FTP | other *** search
- #ifndef __RWTVREF_H__
- #define __RWTVREF_H__
- pragma push_align_members(64);
-
- /*
- * RWTVirtualRef<T>: A typed interface to RWVirtualRef
- *
- * $Header: E:/vcs/rw/tvref.h_v 1.1 17 Mar 1992 19:41:40 KEFFER $
- *
- ****************************************************************************
- *
- * Rogue Wave Software, Inc.
- * P.O. Box 2328
- * Corvallis, OR 97339
- *
- * Copyright (C) 1992. This software is subject to copyright
- * protection under the laws of the United States and other countries.
- *
- ***************************************************************************
- *
- * Although this array could be used by the end user it is really intended
- * to be the reference part of a reference counted array. It uses
- * pure copy semantics and hence is relatively slow.
- *
- * It inherits from RWReference and hence contains a reference count.
- * This is used to implement copy-on-write reference counting as was
- * done with class RWTValVirtualArray<T>.
- *
- * Assumes that T has:
- * - well-defined copy constructor (T::T(const T&) or equiv.);
- * - well-defined assignment operator (T::operator=(const T&) or equiv.).
- *
- * Note that the location in physical memory of a particular index
- * of the array can change from invocation to invocation. Hence,
- * the address of an element should never be taken.
- *
- ***************************************************************************
- *
- * $Log: E:/vcs/rw/tvref.h_v $
- *
- * Rev 1.1 17 Mar 1992 19:41:40 KEFFER
- *
- * Rev 1.0 11 Mar 1992 14:10:00 KEFFER
- * Initial revision.
- */
-
- #include "rw/vref.h"
- #include "rw/toolerr.h"
-
- template <class T> class RWTVirtualRef : public RWVirtualRef {
-
- public:
-
- RWTVirtualRef(long size, RWVirtualPageHeap* h);
- RWTVirtualRef(RWTVirtualRef<T>&); // Takes deep copy.
-
- T val(long i);
- void set(long i, T v);
- void set(long start, long extent, T v);
- virtual void conformalCopy(long start1, RWVirtualRef& v2, long start2, long N);
- };
-
-
- /****************************************************************
- ****************************************************************
- * *
- * RWTVirtualRef<T> *
- * Definitions *
- * *
- ****************************************************************
- ****************************************************************/
-
- template <class T>
- RWTVirtualRef<T>::RWTVirtualRef(long size, RWVirtualPageHeap* heap) :
- RWVirtualRef(size, sizeof(T), heap)
- {
- }
-
- // Copy constructor: use copy semantics
- template <class T>
- RWTVirtualRef<T>::RWTVirtualRef(RWTVirtualRef<T>& v) :
- RWVirtualRef(v)
- {
- conformalCopy(0, (RWVirtualRef&)v, 0, _length); // Painful, but unavoidable w. copy semantics!
- }
-
- // Return the value at index idx
- template <class T> T
- RWTVirtualRef<T>::val(long idx)
- {
- RWPageSlot slot;
- unsigned rem;
- findLocation(idx, slot, rem);
- T* p = (T*)lock(slot);
- T ret = p[rem];
- unlock(slot);
- return ret;
- }
-
- // Set the item at index idx to "val"
- template <class T> void
- RWTVirtualRef<T>::set(long idx, T val)
- {
- RWPageSlot slot;
- unsigned rem;
- findLocation(idx, slot, rem);
- T* p = (T*)lock(slot);
- p[rem] = val;
- dirty(slot);
- unlock(slot);
- }
-
- // Set "extent" items starting at index "start" to the value "val":
- template <class T> void
- RWTVirtualRef<T>::set(long start, long extent, T val)
- {
- long stop = start + extent - 1L;
- RWPageSlot startSlot, stopSlot;
- unsigned startRem, stopRem;
- findLocation(start, startSlot, startRem);
- findLocation(stop, stopSlot, stopRem);
-
- for (RWPageSlot slot = startSlot; slot <= stopSlot; slot++) {
- unsigned startIdx = slot==startSlot ? startRem : 0;
- unsigned endIdx = slot==stopSlot ? stopRem : _nPerPage-1;
- T* p = (T*)lock(slot);
- for (int i = startIdx; i<=endIdx; i++){
- p[i] = val;
- }
- dirty(slot);
- unlock(slot);
- }
- }
-
- /*
- * Copies the data in v2 starting at index start2 into self,
- * starting at index start1.
- * Logically:
- *
- * for(i=0; i<N; i++)
- * (*this)[i+start1] = v2[i+start2];
- *
- * although the copy is actually done by minimizing the number of page
- * locks and, hence, page swaps.
- *
- */
- template <class T> void
- RWTVirtualRef<T>::conformalCopy(long start1,
- RWVirtualRef& v2,
- long start2,
- long N)
- {
- RWPageSlot startSlot1, stopSlot1, lockedSlot1, lockedSlot2, slot2;
- unsigned startRem1, stopRem1, lockedRem1, lockedRem2, rem2;
- long stop1 = start1 + N - 1L;
- findLocation(start1, startSlot1, startRem1);
- findLocation(stop1, stopSlot1, stopRem1);
-
- long idx2 = start1 > start2 ? start2 : start2 + N - 1L;
-
- v2.findLocation(idx2, lockedSlot2, lockedRem2);
- T* p2 = (T*)v2.lock(lockedSlot2);
-
- if (start1 > start2) {
-
- // Work upwards (from left to right)
- for(lockedSlot1=startSlot1; lockedSlot1<=stopSlot1; lockedSlot1++){
- unsigned leftIdx = lockedSlot1==startSlot1 ? startRem1 : 0;
- unsigned rightIdx = lockedSlot1==stopSlot1 ? stopRem1 : _nPerPage-1;
- T* p1 = (T*)lock(lockedSlot1);
- for (unsigned i = leftIdx; i<=rightIdx; i++){
- v2.findLocation(idx2++, slot2, rem2);
- if (lockedSlot2 != slot2){
- v2.unlock(lockedSlot2);
- p2 = (T*)v2.lock(lockedSlot2=slot2);
- }
- p1[i] = p2[rem2];
- }
- dirty(lockedSlot1);
- unlock(lockedSlot1);
- }
- v2.unlock(lockedSlot2);
- }
- else {
-
- unsigned countSlot = stopSlot1 - startSlot1 + 1;
-
- // Work downwards (from right to left)
- while (countSlot--) {
- lockedSlot1 = startSlot1 + countSlot;
- unsigned leftIdx = lockedSlot1==startSlot1 ? startRem1 : 0;
- unsigned rightIdx = lockedSlot1==stopSlot1 ? stopRem1 : _nPerPage-1;
- unsigned countIdx = rightIdx - leftIdx + 1;
- T* p1 = (T*)lock(lockedSlot1);
- while (countIdx--) {
- v2.findLocation(idx2--, slot2, rem2);
- if (lockedSlot2 != slot2){
- v2.unlock(lockedSlot2);
- p2 = (T*)v2.lock(lockedSlot2=slot2);
- }
- p1[rightIdx--] = p2[rem2];
- }
- dirty(lockedSlot1);
- unlock(lockedSlot1);
- }
- v2.unlock(lockedSlot2);
- }
- }
-
- pragma pop_align_members();
- #endif /* __RWTVREF_H__ */
-