Read the next item from the cursor, possibly moving to and waiting for a new page if the prior page was exhausted. If the item is <= inclusiveMaximum, then return it after advancing the cursor to the next item. Otherwise, return nothing and do not advance the cursor. If locked is true, this call owns the mutex, which would have been locked by readNext() before a recursive call. See waitThenReadNex
| 1011 | // If locked is true, this call owns the mutex, which would have been locked by readNext() before a recursive |
| 1012 | // call. See waitThenReadNext() for more detail. |
| 1013 | Future<Optional<T>> readNext(const Optional<T>& inclusiveMaximum = {}, FlowMutex::Lock* lock = nullptr) { |
| 1014 | if ((mode != POP && mode != READONLY) || pageID == invalidPhysicalPageID || pageID == endPageID) { |
| 1015 | debug_printf("FIFOQueue::Cursor(%s) readNext returning nothing\n", toString().c_str()); |
| 1016 | return Optional<T>(); |
| 1017 | } |
| 1018 | |
| 1019 | // If we don't have a lock and the mutex isn't available then acquire it |
| 1020 | if (lock == nullptr && isBusy()) { |
| 1021 | return waitThenReadNext(this, inclusiveMaximum, lock, false); |
| 1022 | } |
| 1023 | |
| 1024 | // We now know pageID is valid and should be used, but page might not point to it yet |
| 1025 | if (!page) { |
| 1026 | debug_printf("FIFOQueue::Cursor(%s) loading\n", toString().c_str()); |
| 1027 | |
| 1028 | // If the next pageID loading or loaded is not the page we should be reading then restart the load |
| 1029 | // nextPageID coud be different because it could be invalid or it could be no longer relevant |
| 1030 | // if the previous commit added new pages to the front of the queue. |
| 1031 | if (pageID != nextPageID) { |
| 1032 | debug_printf("FIFOQueue::Cursor(%s) reloading\n", toString().c_str()); |
| 1033 | startNextPageLoad(pageID); |
| 1034 | } |
| 1035 | |
| 1036 | if (!nextPageReader.isReady()) { |
| 1037 | return waitThenReadNext(this, inclusiveMaximum, lock, true); |
| 1038 | } |
| 1039 | |
| 1040 | page = nextPageReader.get(); |
| 1041 | |
| 1042 | // Start loading the next page if it's not the end page |
| 1043 | auto p = header(); |
| 1044 | if (p->nextPageID != endPageID) { |
| 1045 | startNextPageLoad(p->nextPageID); |
| 1046 | } else { |
| 1047 | // Prevent a future next page read from reusing the same result as page would have to be updated |
| 1048 | // before the queue would read it again |
| 1049 | nextPageID = invalidPhysicalPageID; |
| 1050 | } |
| 1051 | } |
| 1052 | auto p = header(); |
| 1053 | debug_printf("FIFOQueue::Cursor(%s) readNext reading at current position\n", toString().c_str()); |
| 1054 | ASSERT(offset < p->endOffset); |
| 1055 | int bytesRead; |
| 1056 | const T result = Codec::readFromBytes(p->begin() + offset, bytesRead); |
| 1057 | |
| 1058 | if (inclusiveMaximum.present() && inclusiveMaximum.get() < result) { |
| 1059 | debug_printf("FIFOQueue::Cursor(%s) not popping %s, exceeds upper bound %s\n", |
| 1060 | toString().c_str(), |
| 1061 | ::toString(result).c_str(), |
| 1062 | ::toString(inclusiveMaximum.get()).c_str()); |
| 1063 | |
| 1064 | return Optional<T>(); |
| 1065 | } |
| 1066 | |
| 1067 | offset += bytesRead; |
| 1068 | if (mode == POP) { |
| 1069 | --queue->numEntries; |
| 1070 | } |
no test coverage detected