]> git.seodisparate.com - UDPConnection/commitdiff
Drop support from C++17 to C++11
authorStephen Seo <seo.disparate@gmail.com>
Wed, 11 Dec 2019 11:00:48 +0000 (20:00 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 11 Dec 2019 11:00:48 +0000 (20:00 +0900)
std::optional replaced with Entry in TSLQueue (which is basically a poor
man's optional).

CMakeLists.txt
src/TSLQueue.hpp
src/UDPConnection.cpp
src/test/TestTSLQueue.cpp

index fa4c321f5a0eee6143767d861153ef63e131a2af..f63fec6f8af10ac4ec6636b40cd34fe509deebd1 100644 (file)
@@ -21,7 +21,7 @@ add_library(UDPConnection ${UDPConnection_SOURCES})
 
 set_target_properties(UDPConnection PROPERTIES VERSION ${UDPConnection_VERSION})
 
-target_compile_features(UDPConnection PUBLIC cxx_std_17)
+target_compile_features(UDPConnection PUBLIC cxx_std_11)
 target_link_libraries(UDPConnection PUBLIC pthread)
 if(WIN32)
     if(MINGW)
index d368f39f7bfaad8197d922398908f4b4e584346b..7ef865cea0cc53062525eead9454813e162a8dbd 100644 (file)
@@ -23,14 +23,40 @@ class TSLQueue {
     TSLQueue(TSLQueue &&other);
     TSLQueue &operator=(TSLQueue &&other);
 
+    // in place of std::optional which is only available in C++17
+    struct Entry {
+        Entry();
+        Entry(const T& value);
+        Entry(T&& rvalue);
+
+        // enable copy
+        Entry(const Entry& other) = default;
+        Entry &operator =(const Entry& other) = default;
+
+        // enable move
+        Entry(Entry&& other) = default;
+        Entry &operator =(Entry&& other) = default;
+
+        enum Type {
+            NONE,
+            SOME
+        } type;
+        T value;
+
+        bool has_value() const;
+        operator bool () const;
+        T& operator *();
+        const T& operator *() const;
+    };
+
     void push(const T &data);
     bool push_nb(const T &data);
-    std::optional<T> top();
-    std::optional<T> top_nb();
+    Entry top();
+    Entry top_nb();
     bool pop();
-    std::optional<T> top_and_pop();
-    std::optional<T> top_and_pop_and_empty(bool *isEmpty);
-    std::optional<T> top_and_pop_and_rsize(unsigned long *rsize);
+    Entry top_and_pop();
+    Entry top_and_pop_and_empty(bool *isEmpty);
+    Entry top_and_pop_and_rsize(unsigned long *rsize);
     void clear();
 
     bool empty();
@@ -62,18 +88,18 @@ class TSLQueue {
 
     class TSLQIter {
     public:
-        TSLQIter(std::mutex &mutex,
+        TSLQIter(std::mutex *mutex,
                  std::weak_ptr<TSLQNode> currentNode,
                  unsigned long *msize);
         ~TSLQIter();
 
-        std::optional<T> current();
+        Entry current();
         bool next();
         bool prev();
         bool remove();
 
     private:
-        std::lock_guard<std::mutex> lock;
+        std::mutex *mutex;
         std::weak_ptr<TSLQNode> currentNode;
         unsigned long *const msize;
 
@@ -108,7 +134,7 @@ TSLQueue<T>::~TSLQueue() {
 template <typename T>
 TSLQueue<T>::TSLQueue(TSLQueue &&other)
 {
-    std::lock_guard lock(other.mutex);
+    std::lock_guard<std::mutex> lock(other.mutex);
     head = std::move(other.head);
     tail = std::move(other.tail);
     msize = std::move(other.msize);
@@ -116,15 +142,54 @@ TSLQueue<T>::TSLQueue(TSLQueue &&other)
 
 template <typename T>
 TSLQueue<T> & TSLQueue<T>::operator=(TSLQueue &&other) {
-    std::scoped_lock lock(mutex, other.mutex);
+    std::lock_guard<std::mutex> lock(mutex);
+    std::lock_guard<std::mutex> otherLock(other.mutex);
     head = std::move(other.head);
     tail = std::move(other.tail);
     msize = std::move(other.msize);
 }
 
+template <typename T>
+TSLQueue<T>::Entry::Entry() :
+    type(Type::NONE),
+    value()
+{}
+
+template <typename T>
+TSLQueue<T>::Entry::Entry(const T& value) :
+    type(Type::SOME),
+    value(value)
+{}
+
+template <typename T>
+TSLQueue<T>::Entry::Entry(T&& value) :
+    type(Type::SOME),
+    value(std::forward<T>(value))
+{}
+
+template <typename T>
+bool TSLQueue<T>::Entry::has_value() const {
+    return type == Type::SOME;
+}
+
+template <typename T>
+TSLQueue<T>::Entry::operator bool() const {
+    return has_value();
+}
+
+template <typename T>
+T& TSLQueue<T>::Entry::operator *() {
+    return value;
+}
+
+template <typename T>
+const T& TSLQueue<T>::Entry::operator *() const {
+    return value;
+}
+
 template <typename T>
 void TSLQueue<T>::push(const T &data) {
-    std::lock_guard lock(mutex);
+    std::lock_guard<std::mutex> lock(mutex);
     auto newNode = std::make_shared<TSLQNode>();
     newNode->data = std::make_unique<T>(data);
 
@@ -161,34 +226,34 @@ bool TSLQueue<T>::push_nb(const T &data) {
 }
 
 template <typename T>
-std::optional<T> TSLQueue<T>::top() {
-    std::lock_guard lock(mutex);
+typename TSLQueue<T>::Entry TSLQueue<T>::top() {
+    std::lock_guard<std::mutex> lock(mutex);
     if(head->next != tail) {
         assert(head->next->data);
-        return *head->next->data.get();
+        return Entry(*head->next->data.get());
     } else {
-        return std::nullopt;
+        return Entry();
     }
 }
 
 template <typename T>
-std::optional<T> TSLQueue<T>::top_nb() {
+typename TSLQueue<T>::Entry TSLQueue<T>::top_nb() {
     if(mutex.try_lock()) {
-        std::optional<T> ret = std::nullopt;
+        Entry ret;
         if(head->next != tail) {
             assert(head->next->data);
-            ret = *head->next->data.get();
+            ret = Entry(*head->next->data.get());
         }
         mutex.unlock();
         return ret;
     } else {
-        return std::nullopt;
+        return Entry();
     }
 }
 
 template <typename T>
 bool TSLQueue<T>::pop() {
-    std::lock_guard lock(mutex);
+    std::lock_guard<std::mutex> lock(mutex);
     if(head->next == tail) {
         return false;
     } else {
@@ -203,12 +268,12 @@ bool TSLQueue<T>::pop() {
 }
 
 template <typename T>
-std::optional<T> TSLQueue<T>::top_and_pop() {
-    std::optional<T> ret = std::nullopt;
-    std::lock_guard lock(mutex);
+typename TSLQueue<T>::Entry TSLQueue<T>::top_and_pop() {
+    Entry ret;
+    std::lock_guard<std::mutex> lock(mutex);
     if(head->next != tail) {
         assert(head->next->data);
-        ret = *head->next->data.get();
+        ret = Entry(*head->next->data.get());
 
         auto& newNext = head->next->next;
         newNext->prev = head;
@@ -220,16 +285,16 @@ std::optional<T> TSLQueue<T>::top_and_pop() {
 }
 
 template <typename T>
-std::optional<T> TSLQueue<T>::top_and_pop_and_empty(bool *isEmpty) {
-    std::optional<T> ret = std::nullopt;
-    std::lock_guard lock(mutex);
+typename TSLQueue<T>::Entry TSLQueue<T>::top_and_pop_and_empty(bool *isEmpty) {
+    Entry ret;
+    std::lock_guard<std::mutex> lock(mutex);
     if(head->next == tail) {
         if(isEmpty) {
             *isEmpty = true;
         }
     } else {
         assert(head->next->data);
-        ret = *head->next->data.get();
+        ret = Entry(*head->next->data.get());
 
         auto& newNext = head->next->next;
         newNext->prev = head;
@@ -245,16 +310,16 @@ std::optional<T> TSLQueue<T>::top_and_pop_and_empty(bool *isEmpty) {
 }
 
 template <typename T>
-std::optional<T> TSLQueue<T>::top_and_pop_and_rsize(unsigned long *rsize) {
-    std::optional<T> ret = std::nullopt;
-    std::lock_guard lock(mutex);
+typename TSLQueue<T>::Entry TSLQueue<T>::top_and_pop_and_rsize(unsigned long *rsize) {
+    Entry ret;
+    std::lock_guard<std::mutex> lock(mutex);
     if(head->next == tail) {
         if(rsize) {
             *rsize = 0;
         }
     } else {
         assert(head->next->data);
-        ret = *head->next->data.get();
+        ret = Entry(*head->next->data.get());
 
         auto& newNext = head->next->next;
         newNext->prev = head;
@@ -271,7 +336,7 @@ std::optional<T> TSLQueue<T>::top_and_pop_and_rsize(unsigned long *rsize) {
 
 template <typename T>
 void TSLQueue<T>::clear() {
-    std::lock_guard lock(mutex);
+    std::lock_guard<std::mutex> lock(mutex);
 
     head->next = tail;
     tail->prev = head;
@@ -280,13 +345,13 @@ void TSLQueue<T>::clear() {
 
 template <typename T>
 bool TSLQueue<T>::empty() {
-    std::lock_guard lock(mutex);
+    std::lock_guard<std::mutex> lock(mutex);
     return head->next == tail;
 }
 
 template <typename T>
 unsigned long TSLQueue<T>::size() {
-    std::lock_guard lock(mutex);
+    std::lock_guard<std::mutex> lock(mutex);
     return msize;
 }
 
@@ -301,27 +366,29 @@ bool TSLQueue<T>::TSLQNode::isNormal() const {
 }
 
 template <typename T>
-TSLQueue<T>::TSLQIter::TSLQIter(std::mutex &mutex,
+TSLQueue<T>::TSLQIter::TSLQIter(std::mutex *mutex,
                                 std::weak_ptr<TSLQNode> currentNode,
                                 unsigned long *msize) :
-lock(mutex),
+mutex(mutex),
 currentNode(currentNode),
 msize(msize)
 {
+    mutex->lock();
 }
 
 template <typename T>
 TSLQueue<T>::TSLQIter::~TSLQIter() {
+    mutex->unlock();
 }
 
 template <typename T>
-std::optional<T> TSLQueue<T>::TSLQIter::current() {
+typename TSLQueue<T>::Entry TSLQueue<T>::TSLQIter::current() {
     std::shared_ptr<TSLQNode> currentNode = this->currentNode.lock();
     assert(currentNode);
     if(currentNode->isNormal()) {
-        return *currentNode->data.get();
+        return Entry(*currentNode->data.get());
     } else {
-        return std::nullopt;
+        return Entry();
     }
 }
 
@@ -374,7 +441,7 @@ bool TSLQueue<T>::TSLQIter::remove() {
 
 template <typename T>
 typename TSLQueue<T>::TSLQIter TSLQueue<T>::begin() {
-    return TSLQIter(mutex, head->next, &msize);
+    return TSLQIter(&mutex, head->next, &msize);
 }
 
 #endif
index c2501c767b00248cb7361fa934439cd0ecfcf39f..d754b35f330b5f5c3833ad87173386eed79df01d 100644 (file)
@@ -265,7 +265,7 @@ void UDPC::Context::update_impl() {
     do {
         auto optE = internalEvents.top_and_pop();
         if(optE.has_value()) {
-            switch(optE.value().type) {
+            switch(optE.value.type) {
             case UDPC_ET_REQUEST_CONNECT:
             {
                 unsigned char *sk = nullptr;
@@ -277,11 +277,11 @@ void UDPC::Context::update_impl() {
                 UDPC::ConnectionData newCon(
                     false,
                     this,
-                    optE.value().conId.addr,
-                    optE.value().conId.scope_id,
-                    optE.value().conId.port,
+                    optE.value.conId.addr,
+                    optE.value.conId.scope_id,
+                    optE.value.conId.port,
 #ifdef UDPC_LIBSODIUM_ENABLED
-                    flags.test(2) && optE.value().v.enableLibSodium != 0,
+                    flags.test(2) && optE.value.v.enableLibSodium != 0,
                     sk, pk);
 #else
                     false,
@@ -292,9 +292,9 @@ void UDPC::Context::update_impl() {
                         UDPC_LoggingType::UDPC_ERROR,
                         "Failed to init ConnectionData instance (libsodium "
                         "init fail) while client establishing connection with ",
-                        UDPC_atostr((UDPC_HContext)this, optE.value().conId.addr),
+                        UDPC_atostr((UDPC_HContext)this, optE.value.conId.addr),
                         " port ",
-                        optE.value().conId.port);
+                        optE.value.conId.port);
                     continue;
                 }
                 newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT;
@@ -314,34 +314,34 @@ void UDPC::Context::update_impl() {
 #endif
                 }
 
-                if(conMap.find(optE.value().conId) == conMap.end()) {
+                if(conMap.find(optE.value.conId) == conMap.end()) {
                     conMap.insert(std::make_pair(
-                        optE.value().conId,
+                        optE.value.conId,
                         std::move(newCon)));
-                    auto addrConIter = addrConMap.find(optE.value().conId.addr);
+                    auto addrConIter = addrConMap.find(optE.value.conId.addr);
                     if(addrConIter == addrConMap.end()) {
                         auto insertResult = addrConMap.insert(std::make_pair(
-                            optE.value().conId.addr,
+                            optE.value.conId.addr,
                             std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}));
                         assert(insertResult.second &&
                             "new connection insert into addrConMap must not fail");
                         addrConIter = insertResult.first;
                     }
-                    addrConIter->second.insert(optE.value().conId);
+                    addrConIter->second.insert(optE.value.conId);
                     UDPC_CHECK_LOG(this,
                         UDPC_LoggingType::UDPC_INFO,
                         "Client initiating connection to ",
-                        UDPC_atostr((UDPC_HContext)this, optE.value().conId.addr),
+                        UDPC_atostr((UDPC_HContext)this, optE.value.conId.addr),
                         " port ",
-                        optE.value().conId.port,
+                        optE.value.conId.port,
                         " ...");
                 } else {
                     UDPC_CHECK_LOG(this,
                         UDPC_LoggingType::UDPC_WARNING,
                         "Client initiate connection, already connected to peer ",
-                        UDPC_atostr((UDPC_HContext)this, optE.value().conId.addr),
+                        UDPC_atostr((UDPC_HContext)this, optE.value.conId.addr),
                         " port ",
-                        optE.value().conId.port);
+                        optE.value.conId.port);
                 }
             }
                 break;
@@ -358,9 +358,9 @@ void UDPC::Context::update_impl() {
                 UDPC::ConnectionData newCon(
                     false,
                     this,
-                    optE.value().conId.addr,
-                    optE.value().conId.scope_id,
-                    optE.value().conId.port,
+                    optE.value.conId.addr,
+                    optE.value.conId.scope_id,
+                    optE.value.conId.port,
 #ifdef UDPC_LIBSODIUM_ENABLED
                     true,
                     sk, pk);
@@ -368,18 +368,18 @@ void UDPC::Context::update_impl() {
                     false,
                     sk, pk);
                 assert(!"compiled without libsodium support");
-                delete[] optE.value().v.pk;
+                delete[] optE.value.v.pk;
                 break;
 #endif
                 if(newCon.flags.test(5)) {
-                    delete[] optE.value().v.pk;
+                    delete[] optE.value.v.pk;
                     UDPC_CHECK_LOG(this,
                         UDPC_LoggingType::UDPC_ERROR,
                         "Failed to init ConnectionData instance (libsodium "
                         "init fail) while client establishing connection with ",
-                        UDPC_atostr((UDPC_HContext)this, optE.value().conId.addr),
+                        UDPC_atostr((UDPC_HContext)this, optE.value.conId.addr),
                         " port ",
-                        optE.value().conId.port);
+                        optE.value.conId.port);
                     continue;
                 }
                 newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT;
@@ -401,48 +401,48 @@ void UDPC::Context::update_impl() {
                     // set peer public key
                     std::memcpy(
                         newCon.peer_pk,
-                        optE.value().v.pk,
+                        optE.value.v.pk,
                         crypto_sign_PUBLICKEYBYTES);
                     newCon.flags.set(7);
                 }
 
-                delete[] optE.value().v.pk;
+                delete[] optE.value.v.pk;
 
-                if(conMap.find(optE.value().conId) == conMap.end()) {
+                if(conMap.find(optE.value.conId) == conMap.end()) {
                     conMap.insert(std::make_pair(
-                        optE.value().conId,
+                        optE.value.conId,
                         std::move(newCon)));
-                    auto addrConIter = addrConMap.find(optE.value().conId.addr);
+                    auto addrConIter = addrConMap.find(optE.value.conId.addr);
                     if(addrConIter == addrConMap.end()) {
                         auto insertResult = addrConMap.insert(std::make_pair(
-                            optE.value().conId.addr,
+                            optE.value.conId.addr,
                             std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}));
                         assert(insertResult.second &&
                             "new connection insert into addrConMap must not fail");
                         addrConIter = insertResult.first;
                     }
-                    addrConIter->second.insert(optE.value().conId);
+                    addrConIter->second.insert(optE.value.conId);
                     UDPC_CHECK_LOG(this,
                         UDPC_LoggingType::UDPC_INFO,
                         "Client initiating connection to ",
-                        UDPC_atostr((UDPC_HContext)this, optE.value().conId.addr),
+                        UDPC_atostr((UDPC_HContext)this, optE.value.conId.addr),
                         " port ",
-                        optE.value().conId.port,
+                        optE.value.conId.port,
                         " ...");
                 } else {
                     UDPC_CHECK_LOG(this,
                         UDPC_LoggingType::UDPC_WARNING,
                         "Client initiate connection, already connected to peer ",
-                        UDPC_atostr((UDPC_HContext)this, optE.value().conId.addr),
+                        UDPC_atostr((UDPC_HContext)this, optE.value.conId.addr),
                         " port ",
-                        optE.value().conId.port);
+                        optE.value.conId.port);
                 }
             }
                 break;
             case UDPC_ET_REQUEST_DISCONNECT:
-                if(optE.value().v.dropAllWithAddr != 0) {
+                if(optE.value.v.dropAllWithAddr != 0) {
                     // drop all connections with same address
-                    auto addrConIter = addrConMap.find(optE.value().conId.addr);
+                    auto addrConIter = addrConMap.find(optE.value.conId.addr);
                     if(addrConIter != addrConMap.end()) {
                         for(auto identIter = addrConIter->second.begin();
                                 identIter != addrConIter->second.end();
@@ -463,14 +463,14 @@ void UDPC::Context::update_impl() {
                     }
                 } else {
                     // drop only specific connection with addr and port
-                    auto iter = conMap.find(optE.value().conId);
+                    auto iter = conMap.find(optE.value.conId);
                     if(iter != conMap.end()) {
                         if(iter->second.flags.test(4)) {
                             idMap.erase(iter->second.id);
                         }
-                        auto addrConIter = addrConMap.find(optE.value().conId.addr);
+                        auto addrConIter = addrConMap.find(optE.value.conId.addr);
                         if(addrConIter != addrConMap.end()) {
-                            addrConIter->second.erase(optE.value().conId);
+                            addrConIter->second.erase(optE.value.conId);
                             if(addrConIter->second.empty()) {
                                 addrConMap.erase(addrConIter);
                             }
@@ -607,18 +607,18 @@ void UDPC::Context::update_impl() {
         while(true) {
             auto next = sendIter.current();
             if(next) {
-                if(auto iter = conMap.find(next.value().receiver);
-                        iter != conMap.end()) {
+                auto iter = conMap.find(next.value.receiver);
+                if(iter != conMap.end()) {
                     if(iter->second.sendPkts.size() >= UDPC_QUEUED_PKTS_MAX_SIZE) {
-                        if(notQueued.find(next.value().receiver) == notQueued.end()) {
-                            notQueued.insert(next.value().receiver);
+                        if(notQueued.find(next.value.receiver) == notQueued.end()) {
+                            notQueued.insert(next.value.receiver);
                             UDPC_CHECK_LOG(this,
                                 UDPC_LoggingType::UDPC_DEBUG,
                                 "Not queueing packet to ",
                                 UDPC_atostr((UDPC_HContext)this,
-                                    next.value().receiver.addr),
+                                    next.value.receiver.addr),
                                 ", port = ",
-                                next.value().receiver.port,
+                                next.value.receiver.port,
                                 ", connection's queue reached max size");
                         }
                         if(sendIter.next()) {
@@ -627,24 +627,24 @@ void UDPC::Context::update_impl() {
                             break;
                         }
                     }
-                    iter->second.sendPkts.push_back(next.value());
+                    iter->second.sendPkts.push_back(next.value);
                     if(sendIter.remove()) {
                         continue;
                     } else {
                         break;
                     }
                 } else {
-                    if(dropped.find(next.value().receiver) == dropped.end()) {
+                    if(dropped.find(next.value.receiver) == dropped.end()) {
                         UDPC_CHECK_LOG(this,
                             UDPC_LoggingType::UDPC_WARNING,
                             "Dropped queued packets to ",
                             UDPC_atostr(
                                 (UDPC_HContext)this,
-                                next.value().receiver.addr),
+                                next.value.receiver.addr),
                             ", port = ",
-                            next.value().receiver.port,
+                            next.value.receiver.port,
                             " due to connection not existing");
-                        dropped.insert(next.value().receiver);
+                        dropped.insert(next.value.receiver);
                     }
                     if(sendIter.remove()) {
                         continue;
@@ -1589,17 +1589,22 @@ UDPC::Context *UDPC::verifyContext(UDPC_HContext ctx) {
 }
 
 bool UDPC::isBigEndian() {
-    static std::optional<bool> isBigEndian = std::nullopt;
-    if(isBigEndian) {
-        return *isBigEndian;
+    /*
+     * 0 - unset
+     * 1 - is big endian
+     * 2 - is not big endian
+     */
+    static char isBigEndian = 0;
+    if(isBigEndian != 0) {
+        return isBigEndian == 1;
     }
     union {
         uint32_t i;
         char c[4];
     } bint = {0x01020304};
 
-    isBigEndian = (bint.c[0] == 1);
-    return *isBigEndian;
+    isBigEndian = (bint.c[0] == 1 ? 1 : 2);
+    return isBigEndian;
 }
 
 void UDPC::preparePacket(
@@ -1923,8 +1928,8 @@ void UDPC_destroy(UDPC_HContext ctx) {
 #endif
         while(!UDPC_ctx->internalEvents.empty()) {
             auto optE = UDPC_ctx->internalEvents.top_and_pop();
-            if(optE.has_value() && optE.value().type == UDPC_ET_REQUEST_CONNECT_PK) {
-                delete[] optE.value().v.pk;
+            if(optE.has_value() && optE.value.type == UDPC_ET_REQUEST_CONNECT_PK) {
+                delete[] optE.value.v.pk;
             }
         }
         UDPC_ctx->_contextIdentifier = 0;
@@ -2141,7 +2146,7 @@ UDPC_Event UDPC_get_event(UDPC_HContext ctx, unsigned long *remaining) {
 
     auto optE = c->externalEvents.top_and_pop_and_rsize(remaining);
     if(optE) {
-        return optE.value();
+        return optE.value;
     } else {
         return UDPC_Event{UDPC_ET_NONE, UDPC_create_id_anyaddr(0), 0};
     }
index 2ac41a546938d4b915b2d382f112de07b6110b04..4bb3647501139dcc8d9b80d3b176f04cf656d595 100644 (file)
@@ -18,7 +18,7 @@ TEST(TSLQueue, PushTopPopSize) {
     for(int i = 0; i < 10; ++i) {
         auto v = q.top();
         ASSERT_TRUE(v.has_value());
-        EXPECT_EQ(v.value(), i);
+        EXPECT_EQ(v.value, i);
         EXPECT_EQ(10 - i, q.size());
         EXPECT_TRUE(q.pop());
     }
@@ -38,11 +38,11 @@ TEST(TSLQueue, PushNB_TopNB_TopAndPop_Size) {
     for(int i = 0; i < 10; ++i) {
         auto v = q.top_nb();
         ASSERT_TRUE(v.has_value());
-        EXPECT_EQ(v.value(), i);
+        EXPECT_EQ(v.value, i);
         EXPECT_EQ(q.size(), 10 - i);
         v = q.top_and_pop();
         ASSERT_TRUE(v.has_value());
-        EXPECT_EQ(v.value(), i);
+        EXPECT_EQ(v.value, i);
     }
 
     {
@@ -69,7 +69,7 @@ TEST(TSLQueue, Push_TopAndPopAndEmpty_Size) {
         EXPECT_EQ(q.size(), 10 - i);
         auto v = q.top_and_pop_and_empty(&isEmpty);
         ASSERT_TRUE(v.has_value());
-        EXPECT_EQ(v.value(), i);
+        EXPECT_EQ(v.value, i);
         EXPECT_EQ(i == 9, isEmpty);
     }
     EXPECT_EQ(q.size(), 0);
@@ -110,8 +110,8 @@ TEST(TSLQueue, Concurrent) {
         EXPECT_EQ(q.size(), 100 - i);
         auto v = q.top_and_pop();
         ASSERT_TRUE(v.has_value());
-        EXPECT_GE(v.value(), 0);
-        EXPECT_LE(v.value(), 100);
+        EXPECT_GE(v.value, 0);
+        EXPECT_LE(v.value, 100);
         EXPECT_EQ(i == 99, q.empty());
     }
     EXPECT_EQ(q.size(), 0);
@@ -131,7 +131,7 @@ TEST(TSLQueue, Iterator) {
         int i = 0;
         auto op = iter.current();
         while(op.has_value()) {
-            EXPECT_EQ(op.value(), i++);
+            EXPECT_EQ(op.value, i++);
             if(i < 10) {
                 EXPECT_TRUE(iter.next());
             } else {
@@ -149,7 +149,7 @@ TEST(TSLQueue, Iterator) {
         EXPECT_TRUE(iter.prev());
         op = iter.current();
         while(op.has_value()) {
-            EXPECT_EQ(op.value(), --i);
+            EXPECT_EQ(op.value, --i);
             if(i > 0) {
                 EXPECT_TRUE(iter.prev());
             } else {
@@ -169,22 +169,22 @@ TEST(TSLQueue, Iterator) {
 
         auto op = iter.current();
         EXPECT_TRUE(op.has_value());
-        EXPECT_EQ(op.value(), 4);
+        EXPECT_EQ(op.value, 4);
 
         EXPECT_TRUE(iter.prev());
         op = iter.current();
         EXPECT_TRUE(op.has_value());
-        EXPECT_EQ(op.value(), 2);
+        EXPECT_EQ(op.value, 2);
     }
     EXPECT_EQ(q.size(), 9);
 
     // check that "3" was removed from queue
     int i = 0;
-    std::optional<int> op;
+    TSLQueue<int>::Entry op;
     while(!q.empty()) {
         op = q.top();
         EXPECT_TRUE(op.has_value());
-        EXPECT_EQ(i++, op.value());
+        EXPECT_EQ(i++, op.value);
         if(i == 3) {
             ++i;
         }
@@ -206,7 +206,7 @@ TEST(TSLQueue, Iterator) {
     while(!q.empty()) {
         op = q.top();
         EXPECT_TRUE(op.has_value());
-        EXPECT_EQ(i++, op.value());
+        EXPECT_EQ(i++, op.value);
         EXPECT_TRUE(q.pop());
     }
 
@@ -222,7 +222,7 @@ TEST(TSLQueue, Iterator) {
             EXPECT_TRUE(iter.next());
             op = iter.current();
             EXPECT_TRUE(op.has_value());
-            if(op.value() == 3) {
+            if(op.value == 3) {
                 EXPECT_FALSE(iter.remove());
                 break;
             }
@@ -233,7 +233,7 @@ TEST(TSLQueue, Iterator) {
     while(!q.empty()) {
         op = q.top();
         EXPECT_TRUE(op.has_value());
-        EXPECT_EQ(i++, op.value());
+        EXPECT_EQ(i++, op.value);
         EXPECT_TRUE(q.pop());
         if(i == 3) {
             EXPECT_TRUE(q.empty());