00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef Fennel_TwoQVictimPolicy_Included
00025 #define Fennel_TwoQVictimPolicy_Included
00026
00027 #include "fennel/common/IntrusiveDList.h"
00028
00029 #include <boost/dynamic_bitset.hpp>
00030
00031 FENNEL_BEGIN_NAMESPACE
00032
00038 class FENNEL_CACHE_EXPORT TwoQPageQueue
00039 {
00043 IntrusiveDListNode *head;
00044
00048 IntrusiveDListNode *tail;
00049
00053 uint len;
00054
00058 void validateQueue()
00059 {
00060 assert(head == NULL || head->getPrev() == NULL);
00061 assert(tail == NULL || tail->getNext() == NULL);
00062
00063 uint actualLen = 0;
00064 IntrusiveDListNode *curr = head;
00065 while (curr != NULL) {
00066 actualLen++;
00067 curr = curr->getNext();
00068 }
00069 assert(actualLen == len);
00070
00071 curr = tail;
00072 actualLen = 0;
00073 while (curr != NULL) {
00074 actualLen++;
00075 curr = curr->getPrev();
00076 }
00077 assert(actualLen == len);
00078 }
00079
00080 public:
00081 TwoQPageQueue()
00082 {
00083 head = NULL;
00084 tail = NULL;
00085 len = 0;
00086 }
00087
00093 void insertAtHead(IntrusiveDListNode &page)
00094 {
00095 if (head == NULL) {
00096 assert(tail == NULL);
00097 tail = &page;
00098 } else {
00099 page.insertBefore(*head);
00100 }
00101 head = &page;
00102 len++;
00103 }
00104
00110 void moveToHead(IntrusiveDListNode &page)
00111 {
00112 if (head == &page) {
00113 return;
00114 }
00115 if (tail == &page) {
00116 tail = page.getPrev();
00117 }
00118 page.detach();
00119 page.insertBefore(*head);
00120 head = &page;
00121 }
00122
00128 void insertAtTail(IntrusiveDListNode &page)
00129 {
00130 if (tail == NULL) {
00131 assert(head == NULL);
00132 head = &page;
00133 } else {
00134 page.insertAfter(*tail);
00135 }
00136 tail = &page;
00137 len++;
00138 }
00139
00145 void moveToTail(IntrusiveDListNode &page)
00146 {
00147 if (tail == &page) {
00148 return;
00149 }
00150 if (head == &page) {
00151 head = page.getNext();
00152 }
00153 page.detach();
00154 page.insertAfter(*tail);
00155 tail = &page;
00156 }
00157
00163 void remove(IntrusiveDListNode &page)
00164 {
00165 assert(len == 1 || (page.getNext() != NULL || page.getPrev() != NULL));
00166 if (&page == head && &page == tail) {
00167 assert(len == 1);
00168 head = tail = NULL;
00169 } else if (&page == head) {
00170 head = head->getNext();
00171 } else if (&page == tail) {
00172 tail = tail->getPrev();
00173 }
00174 page.detach();
00175 assert(len > 0);
00176 len--;
00177 }
00178
00182 uint size()
00183 {
00184 return len;
00185 }
00186
00190 IntrusiveDListNode *getHead()
00191 {
00192 return head;
00193 }
00194 };
00195
00203 class FENNEL_CACHE_EXPORT TwoQDirtyPage
00204 : public IntrusiveDListNode
00205 {
00206 public:
00211 enum DirtyPageState {
00215 PAGE_CLEAN,
00216
00220 PAGE_DIRTY_POPULAR_UNPINNED,
00221
00225 PAGE_DIRTY_FRESHMAN,
00226
00230 PAGE_DIRTY_POPULAR_PINNED
00231 };
00232
00233 private:
00237 CachePage *pParentPage;
00238
00242 DirtyPageState dirtyState;
00243
00244 public:
00250 void setParentPage(CachePage &parentPageInit)
00251 {
00252 pParentPage = &parentPageInit;
00253 }
00254
00258 CachePage &getParentPage()
00259 {
00260 return *pParentPage;
00261 }
00262
00266 DirtyPageState getDirtyState()
00267 {
00268 return dirtyState;
00269 }
00270
00276 void setDirtyState(DirtyPageState newState)
00277 {
00278 dirtyState = newState;
00279 }
00280 };
00281
00286 class FENNEL_CACHE_EXPORT TwoQVictim
00287 : public IntrusiveDListNode
00288 {
00289 public:
00294 enum PageState {
00298 PAGE_STATE_POPULAR_PINNED,
00302 PAGE_STATE_POPULAR_UNPINNED,
00306 PAGE_STATE_FRESHMAN,
00310 PAGE_STATE_FREE
00311 };
00312
00313 private:
00317 PageState state;
00318
00322 TwoQDirtyPage dirtyPageNode;
00323
00324 public:
00325
00326 TwoQVictim()
00327 {
00328 state = PAGE_STATE_FREE;
00329 dirtyPageNode.setDirtyState(TwoQDirtyPage::PAGE_CLEAN);
00330 }
00331
00335 PageState getState()
00336 {
00337 return state;
00338 }
00339
00345 void setState(PageState newState)
00346 {
00347 state = newState;
00348 }
00349
00353 TwoQDirtyPage &getDirtyPageNode()
00354 {
00355 return dirtyPageNode;
00356 }
00357 };
00358
00362 template <class PageT>
00363 class TwoQPageListIter : public IntrusiveTwoDListIter<PageT, PageT>
00364 {
00368 virtual PageT *getReturnElement(PageT *page) const
00369 {
00370 return page;
00371 }
00372
00373 public:
00374 TwoQPageListIter()
00375 : IntrusiveTwoDListIter<PageT, PageT>()
00376 {
00377 }
00378
00379 TwoQPageListIter(PageT *list1, PageT *list2)
00380 : IntrusiveTwoDListIter<PageT, PageT>(list1, list2)
00381 {
00382 }
00383
00384 ~TwoQPageListIter()
00385 {
00386 }
00387 };
00388
00389
00394 template <class PageT>
00395 class TwoQDirtyPageListIter : public IntrusiveTwoDListIter<TwoQDirtyPage, PageT>
00396 {
00406 virtual PageT *getReturnElement(TwoQDirtyPage *dirtyPage) const
00407 {
00408 if (dirtyPage == NULL) {
00409 return NULL;
00410 } else {
00411 return static_cast<PageT *>(&(dirtyPage->getParentPage()));
00412 }
00413 }
00414
00415 public:
00416 TwoQDirtyPageListIter()
00417 : IntrusiveTwoDListIter<TwoQDirtyPage, PageT>()
00418 {
00419 }
00420
00421 TwoQDirtyPageListIter(TwoQDirtyPage *list1, TwoQDirtyPage *list2)
00422 : IntrusiveTwoDListIter<TwoQDirtyPage, PageT>(list1, list2)
00423 {
00424 }
00425
00426 ~TwoQDirtyPageListIter()
00427 {
00428 }
00429 };
00430
00473 template <class PageT>
00474 class TwoQVictimPolicy
00475 {
00479 SXMutex mutex;
00480
00485 TwoQPageQueue popularPinnedQueue;
00486
00490 TwoQPageQueue popularUnpinnedQueue;
00491
00495 TwoQPageQueue freshmenQueue;
00496
00501 TwoQPageQueue dirtyPopularUnpinnedQueue;
00502
00507 TwoQPageQueue dirtyFreshmenQueue;
00508
00512 std::vector<BlockId> historyQueue;
00513
00517 uint historyQueueStart;
00518
00522 uint currHistoryQueueLen;
00523
00531 boost::dynamic_bitset<> historyBitmap;
00532
00536 uint nCachePages;
00537
00543 uint maxFreshmenQueueLen;
00544
00548 uint maxHistoryQueueLen;
00549
00555 uint freshmenQueuePercentage;
00556
00561 uint pageHistoryQueuePercentage;
00562
00566 void init()
00567 {
00568 nCachePages = 0;
00569 maxFreshmenQueueLen = 0;
00570 maxHistoryQueueLen = 0;
00571 historyQueueStart = 0;
00572 currHistoryQueueLen = 0;
00573 }
00574
00578 bool isPageClean(PageT &page)
00579 {
00580 return
00581 (!page.isDirty() &&
00582 page.getDirtyPageNode().getDirtyState() ==
00583 TwoQDirtyPage::PAGE_CLEAN);
00584 }
00585
00594 void notifyPopularPageAccess(PageT &page, bool pin)
00595 {
00596 assert(mutex.isLocked(LOCKMODE_X));
00597 TwoQVictim::PageState state = page.TwoQVictim::getState();
00598 assert(
00599 state != TwoQVictim::PAGE_STATE_FRESHMAN &&
00600 state != TwoQVictim::PAGE_STATE_POPULAR_PINNED);
00601
00602 if (pin) {
00603
00604
00605 if (state == TwoQVictim::PAGE_STATE_POPULAR_UNPINNED) {
00606 popularUnpinnedQueue.remove(page);
00607 TwoQDirtyPage &dirtyPageNode =
00608 page.TwoQVictim::getDirtyPageNode();
00609 if (dirtyPageNode.getDirtyState() ==
00610 TwoQDirtyPage::PAGE_DIRTY_POPULAR_UNPINNED)
00611 {
00612 dirtyPopularUnpinnedQueue.remove(dirtyPageNode);
00613 dirtyPageNode.setDirtyState(
00614 TwoQDirtyPage::PAGE_DIRTY_POPULAR_PINNED);
00615 } else {
00616 assert(isPageClean(page));
00617 }
00618 }
00619 popularPinnedQueue.insertAtTail(page);
00620 page.TwoQVictim::setState(TwoQVictim::PAGE_STATE_POPULAR_PINNED);
00621
00622 } else {
00623
00624 if (state == TwoQVictim::PAGE_STATE_POPULAR_UNPINNED) {
00625 popularUnpinnedQueue.moveToTail(page);
00626 TwoQDirtyPage &dirtyPageNode =
00627 page.TwoQVictim::getDirtyPageNode();
00628 if (dirtyPageNode.getDirtyState() ==
00629 TwoQDirtyPage::PAGE_DIRTY_POPULAR_UNPINNED)
00630 {
00631 dirtyPopularUnpinnedQueue.moveToTail(dirtyPageNode);
00632 } else {
00633 assert(isPageClean(page));
00634 }
00635 } else {
00636
00637
00638 assert(isPageClean(page));
00639 popularUnpinnedQueue.insertAtTail(page);
00640 page.TwoQVictim::setState(
00641 TwoQVictim::PAGE_STATE_POPULAR_UNPINNED);
00642 }
00643 }
00644 }
00645
00646 public:
00647
00656 typedef TwoQPageListIter<PageT> PageIterator;
00657
00665 typedef TwoQDirtyPageListIter<PageT> DirtyPageIterator;
00666
00677 typedef SXMutexSharedGuard SharedGuard;
00678
00682 typedef SXMutexExclusiveGuard ExclusiveGuard;
00683
00687 TwoQVictimPolicy()
00688 {
00689 init();
00690 freshmenQueuePercentage = CacheParams::defaultFreshmenQueuePercentage;
00691 pageHistoryQueuePercentage =
00692 CacheParams::defaultPageHistoryQueuePercentage;
00693 }
00694
00695 TwoQVictimPolicy(const CacheParams ¶ms)
00696 {
00697 init();
00698 freshmenQueuePercentage = params.freshmenQueuePercentage;
00699 pageHistoryQueuePercentage = params.pageHistoryQueuePercentage;
00700 }
00701
00708 void setAllocatedPageCount(uint nCachePagesInit)
00709 {
00710 ExclusiveGuard exclusiveGuard(mutex);
00711
00712 if (nCachePagesInit == nCachePages) {
00713 return;
00714 }
00715
00716 uint newHistoryQueueLen =
00717 nCachePagesInit * pageHistoryQueuePercentage / 100;
00718 if ((currHistoryQueueLen > newHistoryQueueLen) ||
00719 (historyQueueStart != 0))
00720 {
00721
00722
00723
00724
00725
00726
00727
00728 std::vector<BlockId> temp;
00729 temp.resize(newHistoryQueueLen);
00730 uint excess =
00731 (currHistoryQueueLen > newHistoryQueueLen)
00732 ? (currHistoryQueueLen - newHistoryQueueLen) : 0;
00733 currHistoryQueueLen -= excess;
00734 for (uint i = 0; i < currHistoryQueueLen; i++) {
00735 temp[i] =
00736 historyQueue[
00737 (historyQueueStart + excess + i) %
00738 maxHistoryQueueLen];
00739 }
00740 historyQueueStart = 0;
00741 historyQueue.resize(newHistoryQueueLen);
00742 historyQueue.swap(temp);
00743 } else {
00744 historyQueue.resize(newHistoryQueueLen);
00745 }
00746
00747
00748
00749
00750
00751 assert(historyQueueStart == 0);
00752 for (uint i = 0; i < currHistoryQueueLen; i++) {
00753 if (!historyBitmap.test(
00754 opaqueToInt(historyQueue[i] % historyBitmap.size())))
00755 {
00756 historyQueue[i] = NULL_BLOCK_ID;
00757 }
00758 }
00759
00760 nCachePages = nCachePagesInit;
00761 maxFreshmenQueueLen = nCachePages * freshmenQueuePercentage / 100;
00762 maxHistoryQueueLen = newHistoryQueueLen;
00763
00764 historyBitmap.resize(maxHistoryQueueLen * 64);
00765
00766
00767 if (currHistoryQueueLen > 0) {
00768 historyBitmap.reset();
00769 for (uint i = 0; i < currHistoryQueueLen; i++) {
00770 if (historyQueue[i] != NULL_BLOCK_ID) {
00771 historyBitmap.set(
00772 opaqueToInt(historyQueue[i]) % historyBitmap.size());
00773 }
00774 }
00775 }
00776 }
00777
00785 void registerPage(PageT &page)
00786 {
00787 page.TwoQVictim::setState(TwoQVictim::PAGE_STATE_FREE);
00788 page.TwoQVictim::getDirtyPageNode().setParentPage(page);
00789 page.TwoQVictim::getDirtyPageNode().setDirtyState(
00790 TwoQDirtyPage::PAGE_CLEAN);
00791 }
00792
00800 void unregisterPage(PageT &page)
00801 {
00802 assert(page.TwoQVictim::getState() == TwoQVictim::PAGE_STATE_FREE);
00803 assert(
00804 page.TwoQVictim::getDirtyPageNode().getDirtyState() ==
00805 TwoQDirtyPage::PAGE_CLEAN);
00806 }
00807
00834 void notifyPageAccess(PageT &page, bool pin)
00835 {
00836 ExclusiveGuard exclusiveGuard(mutex);
00837
00838 switch (page.TwoQVictim::getState()) {
00839 case TwoQVictim::PAGE_STATE_FRESHMAN:
00840 case TwoQVictim::PAGE_STATE_POPULAR_PINNED:
00841 return;
00842
00843 case TwoQVictim::PAGE_STATE_POPULAR_UNPINNED:
00844 notifyPopularPageAccess(page, pin);
00845 break;
00846
00847 case TwoQVictim::PAGE_STATE_FREE:
00848 if (historyBitmap.test(
00849 opaqueToInt(page.getBlockId()) % historyBitmap.size()))
00850 {
00851 notifyPopularPageAccess(page, pin);
00852 } else {
00853 assert(isPageClean(page));
00854 page.TwoQVictim::setState(TwoQVictim::PAGE_STATE_FRESHMAN);
00855 freshmenQueue.insertAtTail(page);
00856 }
00857 break;
00858
00859 default:
00860 permAssert(false);
00861 }
00862 }
00863
00872 void notifyPageNice(PageT &page)
00873 {
00874 ExclusiveGuard exclusiveGuard(mutex);
00875 TwoQVictim::PageState state = page.TwoQVictim::getState();
00876 assert(state != TwoQVictim::PAGE_STATE_FREE);
00877
00878 if (state == TwoQVictim::PAGE_STATE_POPULAR_UNPINNED) {
00879 popularUnpinnedQueue.moveToHead(page);
00880 TwoQDirtyPage &dirtyPageNode = page.TwoQVictim::getDirtyPageNode();
00881 if (dirtyPageNode.getDirtyState() ==
00882 TwoQDirtyPage::PAGE_DIRTY_POPULAR_UNPINNED)
00883 {
00884 dirtyPopularUnpinnedQueue.moveToHead(dirtyPageNode);
00885 } else {
00886 assert(isPageClean(page));
00887 }
00888 } else if (state == TwoQVictim::PAGE_STATE_FRESHMAN) {
00889 freshmenQueue.moveToHead(page);
00890 TwoQDirtyPage &dirtyPageNode = page.TwoQVictim::getDirtyPageNode();
00891 if (dirtyPageNode.getDirtyState() ==
00892 TwoQDirtyPage::PAGE_DIRTY_FRESHMAN)
00893 {
00894 dirtyFreshmenQueue.moveToHead(dirtyPageNode);
00895 } else {
00896 assert(isPageClean(page));
00897 }
00898 }
00899 }
00900
00909 void notifyPageMap(PageT &page, bool pin)
00910 {
00911
00912
00913 notifyPageAccess(page, pin);
00914 }
00915
00924 void notifyPageUnmap(PageT &page, bool discard)
00925 {
00926 ExclusiveGuard exclusiveGuard(mutex);
00927 TwoQVictim::PageState state = page.TwoQVictim::getState();
00928 assert(
00929 state != TwoQVictim::PAGE_STATE_POPULAR_PINNED &&
00930 state != TwoQVictim::PAGE_STATE_FREE);
00931
00932 if (state == TwoQVictim::PAGE_STATE_POPULAR_UNPINNED) {
00933 popularUnpinnedQueue.remove(page);
00934 TwoQDirtyPage &dirtyPageNode =
00935 page.TwoQVictim::getDirtyPageNode();
00936 if (dirtyPageNode.getDirtyState() ==
00937 TwoQDirtyPage::PAGE_DIRTY_POPULAR_UNPINNED)
00938 {
00939 dirtyPopularUnpinnedQueue.remove(dirtyPageNode);
00940 dirtyPageNode.setDirtyState(TwoQDirtyPage::PAGE_CLEAN);
00941 } else {
00942 assert(isPageClean(page));
00943 }
00944 } else {
00945
00946
00947
00948
00949
00950 if (!discard) {
00951 if (currHistoryQueueLen >= maxHistoryQueueLen) {
00952 historyBitmap.set(
00953 opaqueToInt(historyQueue[historyQueueStart])
00954 % historyBitmap.size(),
00955 false);
00956 historyQueueStart =
00957 (historyQueueStart + 1) % maxHistoryQueueLen;
00958 currHistoryQueueLen--;
00959 }
00960 uint currIdx =
00961 (historyQueueStart + currHistoryQueueLen) %
00962 maxHistoryQueueLen;
00963 historyQueue[currIdx] = page.getBlockId();
00964 historyBitmap.set(
00965 opaqueToInt(page.getBlockId()) % historyBitmap.size());
00966 currHistoryQueueLen++;
00967 }
00968
00969 freshmenQueue.remove(page);
00970 TwoQDirtyPage &dirtyPageNode = page.TwoQVictim::getDirtyPageNode();
00971 if (dirtyPageNode.getDirtyState() ==
00972 TwoQDirtyPage::PAGE_DIRTY_FRESHMAN)
00973 {
00974 dirtyFreshmenQueue.remove(dirtyPageNode);
00975 dirtyPageNode.setDirtyState(TwoQDirtyPage::PAGE_CLEAN);
00976 } else {
00977 assert(isPageClean(page));
00978 }
00979 }
00980
00981
00982
00983
00984
00985 if (discard) {
00986 historyBitmap.set(
00987 opaqueToInt(page.getBlockId()) % historyBitmap.size(),
00988 false);
00989 }
00990
00991 page.TwoQVictim::setState(TwoQVictim::PAGE_STATE_FREE);
00992 assert(page.getNext() == NULL && page.getPrev() == NULL);
00993 }
00994
01001 void notifyPageUnpin(PageT &page)
01002 {
01003 ExclusiveGuard exclusiveGuard(mutex);
01004 TwoQVictim::PageState state = page.TwoQVictim::getState();
01005 assert(
01006 state != TwoQVictim::PAGE_STATE_POPULAR_UNPINNED &&
01007 state != TwoQVictim::PAGE_STATE_FREE);
01008
01009
01010
01011 if (state == TwoQVictim::PAGE_STATE_POPULAR_PINNED) {
01012 popularPinnedQueue.remove(page);
01013 popularUnpinnedQueue.insertAtTail(page);
01014 TwoQDirtyPage &dirtyPageNode = page.TwoQVictim::getDirtyPageNode();
01015 if (dirtyPageNode.getDirtyState() ==
01016 TwoQDirtyPage::PAGE_DIRTY_POPULAR_PINNED)
01017 {
01018 dirtyPopularUnpinnedQueue.insertAtTail(dirtyPageNode);
01019 dirtyPageNode.setDirtyState(
01020 TwoQDirtyPage::PAGE_DIRTY_POPULAR_UNPINNED);
01021 } else {
01022 assert(isPageClean(page));
01023 }
01024 page.TwoQVictim::setState(TwoQVictim::PAGE_STATE_POPULAR_UNPINNED);
01025 }
01026
01027 }
01028
01035 void notifyPageDirty(PageT &page)
01036 {
01037 ExclusiveGuard exclusiveGuard(mutex);
01038 TwoQVictim::PageState state = page.TwoQVictim::getState();
01039 assert(state != TwoQVictim::PAGE_STATE_FREE);
01040
01041 TwoQDirtyPage &dirtyPageNode = page.TwoQVictim::getDirtyPageNode();
01042 assert(
01043 dirtyPageNode.getDirtyState() == TwoQDirtyPage::PAGE_CLEAN);
01044
01045
01046
01047
01048
01049
01050
01051
01052 if (state == TwoQVictim::PAGE_STATE_POPULAR_UNPINNED) {
01053 dirtyPopularUnpinnedQueue.insertAtTail(dirtyPageNode);
01054 dirtyPageNode.setDirtyState(
01055 TwoQDirtyPage::PAGE_DIRTY_POPULAR_UNPINNED);
01056 } else if (state == TwoQVictim::PAGE_STATE_FRESHMAN) {
01057 dirtyFreshmenQueue.insertAtTail(dirtyPageNode);
01058 dirtyPageNode.setDirtyState(
01059 TwoQDirtyPage::PAGE_DIRTY_FRESHMAN);
01060 } else if (state == TwoQVictim::PAGE_STATE_POPULAR_PINNED) {
01061 dirtyPageNode.setDirtyState(
01062 TwoQDirtyPage::PAGE_DIRTY_POPULAR_PINNED);
01063 }
01064 }
01065
01071 void notifyPageClean(PageT &page)
01072 {
01073 ExclusiveGuard exclusiveGuard(mutex);
01074 TwoQVictim::PageState state = page.TwoQVictim::getState();
01075
01076
01077
01078 assert(state != TwoQVictim::PAGE_STATE_FREE);
01079
01080
01081
01082
01083 TwoQDirtyPage &dirtyPageNode = page.TwoQVictim::getDirtyPageNode();
01084 if (state == TwoQVictim::PAGE_STATE_POPULAR_UNPINNED) {
01085 assert(
01086 dirtyPageNode.getDirtyState() ==
01087 TwoQDirtyPage::PAGE_DIRTY_POPULAR_UNPINNED);
01088 dirtyPopularUnpinnedQueue.remove(dirtyPageNode);
01089 } else if (state == TwoQVictim::PAGE_STATE_FRESHMAN) {
01090 assert(
01091 dirtyPageNode.getDirtyState() ==
01092 TwoQDirtyPage::PAGE_DIRTY_FRESHMAN);
01093 dirtyFreshmenQueue.remove(dirtyPageNode);
01094 } else if (state == TwoQVictim::PAGE_STATE_POPULAR_PINNED) {
01095 assert(
01096 dirtyPageNode.getDirtyState() ==
01097 TwoQDirtyPage::PAGE_DIRTY_POPULAR_PINNED);
01098 }
01099 dirtyPageNode.setDirtyState(TwoQDirtyPage::PAGE_CLEAN);
01100 }
01101
01109 void notifyPageDiscard(BlockId blockId)
01110 {
01111 ExclusiveGuard exclusiveGuard(mutex);
01112
01113
01114
01115 historyBitmap.set(opaqueToInt(blockId % historyBitmap.size()), false);
01116 }
01117
01125 SXMutex &getMutex()
01126 {
01127 return mutex;
01128 }
01129
01136 std::pair<PageIterator,PageIterator> getVictimRange()
01137 {
01138
01139
01140
01141
01142
01143 if (freshmenQueue.size() < maxFreshmenQueueLen) {
01144 return std::pair<PageIterator, PageIterator>(
01145 PageIterator(
01146 static_cast<PageT *>(popularUnpinnedQueue.getHead()),
01147 static_cast<PageT *>(freshmenQueue.getHead())),
01148 PageIterator());
01149 } else {
01150 return std::pair<PageIterator, PageIterator>(
01151 PageIterator(
01152 static_cast<PageT *>(freshmenQueue.getHead()),
01153 static_cast<PageT *>(popularUnpinnedQueue.getHead())),
01154 PageIterator());
01155 }
01156 }
01157
01164 std::pair<DirtyPageIterator,DirtyPageIterator> getDirtyVictimRange()
01165 {
01166
01167
01168
01169
01170
01171 if (freshmenQueue.size() < maxFreshmenQueueLen) {
01172 return std::pair<DirtyPageIterator, DirtyPageIterator>(
01173 DirtyPageIterator(
01174 static_cast<TwoQDirtyPage *>(
01175 dirtyPopularUnpinnedQueue.getHead()),
01176 static_cast<TwoQDirtyPage *>(dirtyFreshmenQueue.getHead())),
01177 DirtyPageIterator());
01178 } else {
01179 return std::pair<DirtyPageIterator, DirtyPageIterator>(
01180 DirtyPageIterator(
01181 static_cast<TwoQDirtyPage *>(dirtyFreshmenQueue.getHead()),
01182 static_cast<TwoQDirtyPage *>(
01183 dirtyPopularUnpinnedQueue.getHead())),
01184 DirtyPageIterator());
01185 }
01186 }
01187 };
01188
01189 FENNEL_END_NAMESPACE
01190
01191 #endif
01192
01193