1 /* 2 * A page queue whose users take turns to access pages. 3 * 4 * Copyright (C) 2021, 2024 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 std::lock_guard<std::mutex> guard(_lock); 31 32 discard(_queue, memory); 33 } 34 35 /* Keep waiting for a potential queue non-empty condition. 36 Then, attempt to pop an entry from the queue. */ 37 38 void PageQueueShared::pop(PageOwner **owner, Flexpage **flexpage) 39 { 40 std::unique_lock<std::mutex> guard(_lock); 41 QueueEntry entry; 42 43 while (1) 44 { 45 if (_pop(&entry)) 46 { 47 *owner = entry.owner; 48 *flexpage = entry.flexpage; 49 return; 50 } 51 else 52 _counter.wait(guard); 53 } 54 } 55 56 /* Check the queue for entries, returning false if no entries are available, 57 returning true and providing the details if an entry can be removed from the 58 front of the queue. */ 59 60 bool PageQueueShared::_pop(QueueEntry *entry) 61 { 62 if (_queue.empty()) 63 return false; 64 65 *entry = _queue.front(); 66 _queue.pop_front(); 67 68 /* Remove any position reference for the flexpage. */ 69 70 Positions::iterator position = _positions.find(entry->flexpage); 71 72 if (position != _positions.end()) 73 _positions.erase(position); 74 75 return true; 76 } 77 78 /* Push an entry for the given owner and flexpage to the queue. */ 79 80 void PageQueueShared::push(PageOwner *owner, Flexpage *flexpage) 81 { 82 std::lock_guard<std::mutex> guard(_lock); 83 84 /* Record the entry and a position reference for the flexpage. */ 85 86 _queue.push_back((QueueEntry) {flexpage, owner}); 87 88 Queue::iterator last = _queue.end(); 89 last--; 90 _positions.insert(Position(flexpage, last)); 91 92 _counter.notify_one(); 93 } 94 95 /* Push an entry to the front of the queue. */ 96 97 void PageQueueShared::push_front(PageOwner *owner, Flexpage *flexpage) 98 { 99 std::lock_guard<std::mutex> guard(_lock); 100 101 _queue.push_back((QueueEntry) {flexpage, owner}); 102 _positions.insert(Position(flexpage, _queue.begin())); 103 104 _counter.notify_one(); 105 } 106 107 /* Remove an entry for the given owner and flexpage from the queue. */ 108 109 bool PageQueueShared::remove(PageOwner *owner, Flexpage *flexpage) 110 { 111 std::lock_guard<std::mutex> guard(_lock); 112 113 return PageQueue::remove(_queue, _positions, owner, flexpage); 114 } 115 116 // vim: tabstop=4 expandtab shiftwidth=4