1 /* 2 * A page queue whose users take turns to access pages. 3 * 4 * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include "page_queue_shared.h" 23 24 25 26 /* Discard all queued flexpages. */ 27 28 void PageQueueShared::close(Memory *memory) 29 { 30 discard(_queue, memory); 31 } 32 33 /* Keep waiting for a potential queue non-empty condition. 34 Then, attempt to pop an entry from the queue. */ 35 36 void PageQueueShared::pop(PageOwner **owner, Flexpage **flexpage) 37 { 38 std::unique_lock<std::mutex> guard(_lock); 39 QueueEntry entry; 40 41 while (1) 42 { 43 if (_pop(&entry)) 44 { 45 *owner = entry.owner; 46 *flexpage = entry.flexpage; 47 return; 48 } 49 else 50 _counter.wait(guard); 51 } 52 } 53 54 /* Check the queue for entries, returning false if no entries are available, 55 returning true and providing the details if an entry can be removed from the 56 front of the queue. */ 57 58 bool PageQueueShared::_pop(QueueEntry *entry) 59 { 60 if (_queue.empty()) 61 return false; 62 63 *entry = _queue.front(); 64 _queue.pop_front(); 65 66 /* Remove any position reference for the flexpage. */ 67 68 Positions::iterator position = _positions.find(entry->flexpage); 69 70 if (position != _positions.end()) 71 _positions.erase(position); 72 73 return true; 74 } 75 76 /* Push an entry for the given owner and flexpage to the queue. */ 77 78 void PageQueueShared::push(PageOwner *owner, Flexpage *flexpage) 79 { 80 std::lock_guard<std::mutex> guard(_lock); 81 82 /* Record the entry and a position reference for the flexpage. */ 83 84 _queue.push_back((QueueEntry) {flexpage, owner}); 85 86 Queue::iterator last = _queue.end(); 87 last--; 88 _positions.insert(Position(flexpage, last)); 89 90 _counter.notify_one(); 91 } 92 93 /* Push an entry to the front of the queue. */ 94 95 void PageQueueShared::push_front(PageOwner *owner, Flexpage *flexpage) 96 { 97 std::lock_guard<std::mutex> guard(_lock); 98 99 _queue.push_back((QueueEntry) {flexpage, owner}); 100 _positions.insert(Position(flexpage, _queue.begin())); 101 102 _counter.notify_one(); 103 } 104 105 /* Remove an entry for the given owner and flexpage from the queue. */ 106 107 bool PageQueueShared::remove(PageOwner *owner, Flexpage *flexpage) 108 { 109 return PageQueue::remove(_queue, _positions, owner, flexpage); 110 } 111 112 // vim: tabstop=4 expandtab shiftwidth=4