1 #include "page_queue_shared.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 PageQueueShared::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 PageQueueShared::_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 PageQueueShared::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 PageQueueShared::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 PageQueueShared::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