1 #include "page_queue.h" 2 3 /* Keep waiting for a potential queue non-empty condition. 4 Then, attempt to pop an entry from the queue. */ 5 6 void PageQueue::pop(PageOwner **owner, Flexpage **flexpage) 7 { 8 std::unique_lock<std::mutex> guard(_lock); 9 QueueEntry entry; 10 11 while (1) 12 { 13 if (_pop(&entry)) 14 { 15 *owner = entry.owner; 16 *flexpage = entry.flexpage; 17 return; 18 } 19 else 20 _counter.wait(guard); 21 } 22 } 23 24 /* Check the queue for entries, returning false if no entries are available, 25 returning true and providing the details if an entry can be removed from the 26 front of the queue. */ 27 28 bool PageQueue::_pop(QueueEntry *entry) 29 { 30 if (_queue.empty()) 31 return false; 32 33 *entry = _queue.front(); 34 _queue.pop_front(); 35 36 /* Remove any position reference for the flexpage. */ 37 38 Positions::iterator position = _positions.find(entry->flexpage); 39 40 if (position != _positions.end()) 41 _positions.erase(position); 42 43 return true; 44 } 45 46 /* Push an entry for the given owner and flexpage to the queue. */ 47 48 void PageQueue::push(PageOwner *owner, Flexpage *flexpage) 49 { 50 std::lock_guard<std::mutex> guard(_lock); 51 52 /* Record the entry and a position reference for the flexpage. */ 53 54 _queue.push_back((QueueEntry) {flexpage, owner}); 55 56 Queue::iterator last = _queue.end(); 57 last--; 58 _positions.insert(Position(flexpage, last)); 59 60 _counter.notify_one(); 61 } 62 63 /* Push an entry to the front of the queue. */ 64 65 void PageQueue::push_front(PageOwner *owner, Flexpage *flexpage) 66 { 67 std::lock_guard<std::mutex> guard(_lock); 68 69 _queue.push_back((QueueEntry) {flexpage, owner}); 70 _positions.insert(Position(flexpage, _queue.begin())); 71 72 _counter.notify_one(); 73 } 74 75 /* Remove an entry for the given owner and flexpage from the queue. */ 76 77 bool PageQueue::remove(PageOwner *owner, Flexpage *flexpage) 78 { 79 std::lock_guard<std::mutex> guard(_lock); 80 81 Positions::iterator position = _positions.find(flexpage); 82 83 if (position == _positions.end()) 84 return false; 85 86 /* The found owner may be different from the requesting owner or even NULL 87 if another owner has acquired and then purged its pages. Such a purged 88 flexpage is not immediately usable, however. */ 89 90 Queue::iterator entry = position->second; 91 92 if ((entry->owner == NULL) || (entry->owner != owner)) 93 return false; 94 95 _queue.erase(entry); 96 _positions.erase(position); 97 98 return true; 99 } 100 101 // vim: tabstop=4 expandtab shiftwidth=4