Drop support from C++17 to C++11

std::optional replaced with Entry in TSLQueue (which is basically a poor
man's optional).
This commit is contained in:
Stephen Seo 2019-12-11 20:00:48 +09:00
parent 7c444cb460
commit ece17e1aca
4 changed files with 187 additions and 115 deletions

View file

@ -21,7 +21,7 @@ add_library(UDPConnection ${UDPConnection_SOURCES})
set_target_properties(UDPConnection PROPERTIES VERSION ${UDPConnection_VERSION}) 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) target_link_libraries(UDPConnection PUBLIC pthread)
if(WIN32) if(WIN32)
if(MINGW) if(MINGW)

View file

@ -23,14 +23,40 @@ class TSLQueue {
TSLQueue(TSLQueue &&other); TSLQueue(TSLQueue &&other);
TSLQueue &operator=(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); void push(const T &data);
bool push_nb(const T &data); bool push_nb(const T &data);
std::optional<T> top(); Entry top();
std::optional<T> top_nb(); Entry top_nb();
bool pop(); bool pop();
std::optional<T> top_and_pop(); Entry top_and_pop();
std::optional<T> top_and_pop_and_empty(bool *isEmpty); Entry top_and_pop_and_empty(bool *isEmpty);
std::optional<T> top_and_pop_and_rsize(unsigned long *rsize); Entry top_and_pop_and_rsize(unsigned long *rsize);
void clear(); void clear();
bool empty(); bool empty();
@ -62,18 +88,18 @@ class TSLQueue {
class TSLQIter { class TSLQIter {
public: public:
TSLQIter(std::mutex &mutex, TSLQIter(std::mutex *mutex,
std::weak_ptr<TSLQNode> currentNode, std::weak_ptr<TSLQNode> currentNode,
unsigned long *msize); unsigned long *msize);
~TSLQIter(); ~TSLQIter();
std::optional<T> current(); Entry current();
bool next(); bool next();
bool prev(); bool prev();
bool remove(); bool remove();
private: private:
std::lock_guard<std::mutex> lock; std::mutex *mutex;
std::weak_ptr<TSLQNode> currentNode; std::weak_ptr<TSLQNode> currentNode;
unsigned long *const msize; unsigned long *const msize;
@ -108,7 +134,7 @@ TSLQueue<T>::~TSLQueue() {
template <typename T> template <typename T>
TSLQueue<T>::TSLQueue(TSLQueue &&other) TSLQueue<T>::TSLQueue(TSLQueue &&other)
{ {
std::lock_guard lock(other.mutex); std::lock_guard<std::mutex> lock(other.mutex);
head = std::move(other.head); head = std::move(other.head);
tail = std::move(other.tail); tail = std::move(other.tail);
msize = std::move(other.msize); msize = std::move(other.msize);
@ -116,15 +142,54 @@ TSLQueue<T>::TSLQueue(TSLQueue &&other)
template <typename T> template <typename T>
TSLQueue<T> & TSLQueue<T>::operator=(TSLQueue &&other) { 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); head = std::move(other.head);
tail = std::move(other.tail); tail = std::move(other.tail);
msize = std::move(other.msize); 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> template <typename T>
void TSLQueue<T>::push(const T &data) { 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>(); auto newNode = std::make_shared<TSLQNode>();
newNode->data = std::make_unique<T>(data); newNode->data = std::make_unique<T>(data);
@ -161,34 +226,34 @@ bool TSLQueue<T>::push_nb(const T &data) {
} }
template <typename T> template <typename T>
std::optional<T> TSLQueue<T>::top() { typename TSLQueue<T>::Entry TSLQueue<T>::top() {
std::lock_guard lock(mutex); std::lock_guard<std::mutex> lock(mutex);
if(head->next != tail) { if(head->next != tail) {
assert(head->next->data); assert(head->next->data);
return *head->next->data.get(); return Entry(*head->next->data.get());
} else { } else {
return std::nullopt; return Entry();
} }
} }
template <typename T> template <typename T>
std::optional<T> TSLQueue<T>::top_nb() { typename TSLQueue<T>::Entry TSLQueue<T>::top_nb() {
if(mutex.try_lock()) { if(mutex.try_lock()) {
std::optional<T> ret = std::nullopt; Entry ret;
if(head->next != tail) { if(head->next != tail) {
assert(head->next->data); assert(head->next->data);
ret = *head->next->data.get(); ret = Entry(*head->next->data.get());
} }
mutex.unlock(); mutex.unlock();
return ret; return ret;
} else { } else {
return std::nullopt; return Entry();
} }
} }
template <typename T> template <typename T>
bool TSLQueue<T>::pop() { bool TSLQueue<T>::pop() {
std::lock_guard lock(mutex); std::lock_guard<std::mutex> lock(mutex);
if(head->next == tail) { if(head->next == tail) {
return false; return false;
} else { } else {
@ -203,12 +268,12 @@ bool TSLQueue<T>::pop() {
} }
template <typename T> template <typename T>
std::optional<T> TSLQueue<T>::top_and_pop() { typename TSLQueue<T>::Entry TSLQueue<T>::top_and_pop() {
std::optional<T> ret = std::nullopt; Entry ret;
std::lock_guard lock(mutex); std::lock_guard<std::mutex> lock(mutex);
if(head->next != tail) { if(head->next != tail) {
assert(head->next->data); assert(head->next->data);
ret = *head->next->data.get(); ret = Entry(*head->next->data.get());
auto& newNext = head->next->next; auto& newNext = head->next->next;
newNext->prev = head; newNext->prev = head;
@ -220,16 +285,16 @@ std::optional<T> TSLQueue<T>::top_and_pop() {
} }
template <typename T> template <typename T>
std::optional<T> TSLQueue<T>::top_and_pop_and_empty(bool *isEmpty) { typename TSLQueue<T>::Entry TSLQueue<T>::top_and_pop_and_empty(bool *isEmpty) {
std::optional<T> ret = std::nullopt; Entry ret;
std::lock_guard lock(mutex); std::lock_guard<std::mutex> lock(mutex);
if(head->next == tail) { if(head->next == tail) {
if(isEmpty) { if(isEmpty) {
*isEmpty = true; *isEmpty = true;
} }
} else { } else {
assert(head->next->data); assert(head->next->data);
ret = *head->next->data.get(); ret = Entry(*head->next->data.get());
auto& newNext = head->next->next; auto& newNext = head->next->next;
newNext->prev = head; newNext->prev = head;
@ -245,16 +310,16 @@ std::optional<T> TSLQueue<T>::top_and_pop_and_empty(bool *isEmpty) {
} }
template <typename T> template <typename T>
std::optional<T> TSLQueue<T>::top_and_pop_and_rsize(unsigned long *rsize) { typename TSLQueue<T>::Entry TSLQueue<T>::top_and_pop_and_rsize(unsigned long *rsize) {
std::optional<T> ret = std::nullopt; Entry ret;
std::lock_guard lock(mutex); std::lock_guard<std::mutex> lock(mutex);
if(head->next == tail) { if(head->next == tail) {
if(rsize) { if(rsize) {
*rsize = 0; *rsize = 0;
} }
} else { } else {
assert(head->next->data); assert(head->next->data);
ret = *head->next->data.get(); ret = Entry(*head->next->data.get());
auto& newNext = head->next->next; auto& newNext = head->next->next;
newNext->prev = head; newNext->prev = head;
@ -271,7 +336,7 @@ std::optional<T> TSLQueue<T>::top_and_pop_and_rsize(unsigned long *rsize) {
template <typename T> template <typename T>
void TSLQueue<T>::clear() { void TSLQueue<T>::clear() {
std::lock_guard lock(mutex); std::lock_guard<std::mutex> lock(mutex);
head->next = tail; head->next = tail;
tail->prev = head; tail->prev = head;
@ -280,13 +345,13 @@ void TSLQueue<T>::clear() {
template <typename T> template <typename T>
bool TSLQueue<T>::empty() { bool TSLQueue<T>::empty() {
std::lock_guard lock(mutex); std::lock_guard<std::mutex> lock(mutex);
return head->next == tail; return head->next == tail;
} }
template <typename T> template <typename T>
unsigned long TSLQueue<T>::size() { unsigned long TSLQueue<T>::size() {
std::lock_guard lock(mutex); std::lock_guard<std::mutex> lock(mutex);
return msize; return msize;
} }
@ -301,27 +366,29 @@ bool TSLQueue<T>::TSLQNode::isNormal() const {
} }
template <typename T> template <typename T>
TSLQueue<T>::TSLQIter::TSLQIter(std::mutex &mutex, TSLQueue<T>::TSLQIter::TSLQIter(std::mutex *mutex,
std::weak_ptr<TSLQNode> currentNode, std::weak_ptr<TSLQNode> currentNode,
unsigned long *msize) : unsigned long *msize) :
lock(mutex), mutex(mutex),
currentNode(currentNode), currentNode(currentNode),
msize(msize) msize(msize)
{ {
mutex->lock();
} }
template <typename T> template <typename T>
TSLQueue<T>::TSLQIter::~TSLQIter() { TSLQueue<T>::TSLQIter::~TSLQIter() {
mutex->unlock();
} }
template <typename T> 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(); std::shared_ptr<TSLQNode> currentNode = this->currentNode.lock();
assert(currentNode); assert(currentNode);
if(currentNode->isNormal()) { if(currentNode->isNormal()) {
return *currentNode->data.get(); return Entry(*currentNode->data.get());
} else { } else {
return std::nullopt; return Entry();
} }
} }
@ -374,7 +441,7 @@ bool TSLQueue<T>::TSLQIter::remove() {
template <typename T> template <typename T>
typename TSLQueue<T>::TSLQIter TSLQueue<T>::begin() { typename TSLQueue<T>::TSLQIter TSLQueue<T>::begin() {
return TSLQIter(mutex, head->next, &msize); return TSLQIter(&mutex, head->next, &msize);
} }
#endif #endif

View file

@ -265,7 +265,7 @@ void UDPC::Context::update_impl() {
do { do {
auto optE = internalEvents.top_and_pop(); auto optE = internalEvents.top_and_pop();
if(optE.has_value()) { if(optE.has_value()) {
switch(optE.value().type) { switch(optE.value.type) {
case UDPC_ET_REQUEST_CONNECT: case UDPC_ET_REQUEST_CONNECT:
{ {
unsigned char *sk = nullptr; unsigned char *sk = nullptr;
@ -277,11 +277,11 @@ void UDPC::Context::update_impl() {
UDPC::ConnectionData newCon( UDPC::ConnectionData newCon(
false, false,
this, this,
optE.value().conId.addr, optE.value.conId.addr,
optE.value().conId.scope_id, optE.value.conId.scope_id,
optE.value().conId.port, optE.value.conId.port,
#ifdef UDPC_LIBSODIUM_ENABLED #ifdef UDPC_LIBSODIUM_ENABLED
flags.test(2) && optE.value().v.enableLibSodium != 0, flags.test(2) && optE.value.v.enableLibSodium != 0,
sk, pk); sk, pk);
#else #else
false, false,
@ -292,9 +292,9 @@ void UDPC::Context::update_impl() {
UDPC_LoggingType::UDPC_ERROR, UDPC_LoggingType::UDPC_ERROR,
"Failed to init ConnectionData instance (libsodium " "Failed to init ConnectionData instance (libsodium "
"init fail) while client establishing connection with ", "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 ", " port ",
optE.value().conId.port); optE.value.conId.port);
continue; continue;
} }
newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT; newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT;
@ -314,34 +314,34 @@ void UDPC::Context::update_impl() {
#endif #endif
} }
if(conMap.find(optE.value().conId) == conMap.end()) { if(conMap.find(optE.value.conId) == conMap.end()) {
conMap.insert(std::make_pair( conMap.insert(std::make_pair(
optE.value().conId, optE.value.conId,
std::move(newCon))); std::move(newCon)));
auto addrConIter = addrConMap.find(optE.value().conId.addr); auto addrConIter = addrConMap.find(optE.value.conId.addr);
if(addrConIter == addrConMap.end()) { if(addrConIter == addrConMap.end()) {
auto insertResult = addrConMap.insert(std::make_pair( auto insertResult = addrConMap.insert(std::make_pair(
optE.value().conId.addr, optE.value.conId.addr,
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{})); std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}));
assert(insertResult.second && assert(insertResult.second &&
"new connection insert into addrConMap must not fail"); "new connection insert into addrConMap must not fail");
addrConIter = insertResult.first; addrConIter = insertResult.first;
} }
addrConIter->second.insert(optE.value().conId); addrConIter->second.insert(optE.value.conId);
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_INFO,
"Client initiating connection to ", "Client initiating connection to ",
UDPC_atostr((UDPC_HContext)this, optE.value().conId.addr), UDPC_atostr((UDPC_HContext)this, optE.value.conId.addr),
" port ", " port ",
optE.value().conId.port, optE.value.conId.port,
" ..."); " ...");
} else { } else {
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_WARNING, UDPC_LoggingType::UDPC_WARNING,
"Client initiate connection, already connected to peer ", "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 ", " port ",
optE.value().conId.port); optE.value.conId.port);
} }
} }
break; break;
@ -358,9 +358,9 @@ void UDPC::Context::update_impl() {
UDPC::ConnectionData newCon( UDPC::ConnectionData newCon(
false, false,
this, this,
optE.value().conId.addr, optE.value.conId.addr,
optE.value().conId.scope_id, optE.value.conId.scope_id,
optE.value().conId.port, optE.value.conId.port,
#ifdef UDPC_LIBSODIUM_ENABLED #ifdef UDPC_LIBSODIUM_ENABLED
true, true,
sk, pk); sk, pk);
@ -368,18 +368,18 @@ void UDPC::Context::update_impl() {
false, false,
sk, pk); sk, pk);
assert(!"compiled without libsodium support"); assert(!"compiled without libsodium support");
delete[] optE.value().v.pk; delete[] optE.value.v.pk;
break; break;
#endif #endif
if(newCon.flags.test(5)) { if(newCon.flags.test(5)) {
delete[] optE.value().v.pk; delete[] optE.value.v.pk;
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_ERROR, UDPC_LoggingType::UDPC_ERROR,
"Failed to init ConnectionData instance (libsodium " "Failed to init ConnectionData instance (libsodium "
"init fail) while client establishing connection with ", "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 ", " port ",
optE.value().conId.port); optE.value.conId.port);
continue; continue;
} }
newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT; 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 // set peer public key
std::memcpy( std::memcpy(
newCon.peer_pk, newCon.peer_pk,
optE.value().v.pk, optE.value.v.pk,
crypto_sign_PUBLICKEYBYTES); crypto_sign_PUBLICKEYBYTES);
newCon.flags.set(7); 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( conMap.insert(std::make_pair(
optE.value().conId, optE.value.conId,
std::move(newCon))); std::move(newCon)));
auto addrConIter = addrConMap.find(optE.value().conId.addr); auto addrConIter = addrConMap.find(optE.value.conId.addr);
if(addrConIter == addrConMap.end()) { if(addrConIter == addrConMap.end()) {
auto insertResult = addrConMap.insert(std::make_pair( auto insertResult = addrConMap.insert(std::make_pair(
optE.value().conId.addr, optE.value.conId.addr,
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{})); std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}));
assert(insertResult.second && assert(insertResult.second &&
"new connection insert into addrConMap must not fail"); "new connection insert into addrConMap must not fail");
addrConIter = insertResult.first; addrConIter = insertResult.first;
} }
addrConIter->second.insert(optE.value().conId); addrConIter->second.insert(optE.value.conId);
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_INFO,
"Client initiating connection to ", "Client initiating connection to ",
UDPC_atostr((UDPC_HContext)this, optE.value().conId.addr), UDPC_atostr((UDPC_HContext)this, optE.value.conId.addr),
" port ", " port ",
optE.value().conId.port, optE.value.conId.port,
" ..."); " ...");
} else { } else {
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_WARNING, UDPC_LoggingType::UDPC_WARNING,
"Client initiate connection, already connected to peer ", "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 ", " port ",
optE.value().conId.port); optE.value.conId.port);
} }
} }
break; break;
case UDPC_ET_REQUEST_DISCONNECT: case UDPC_ET_REQUEST_DISCONNECT:
if(optE.value().v.dropAllWithAddr != 0) { if(optE.value.v.dropAllWithAddr != 0) {
// drop all connections with same address // 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()) { if(addrConIter != addrConMap.end()) {
for(auto identIter = addrConIter->second.begin(); for(auto identIter = addrConIter->second.begin();
identIter != addrConIter->second.end(); identIter != addrConIter->second.end();
@ -463,14 +463,14 @@ void UDPC::Context::update_impl() {
} }
} else { } else {
// drop only specific connection with addr and port // 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 != conMap.end()) {
if(iter->second.flags.test(4)) { if(iter->second.flags.test(4)) {
idMap.erase(iter->second.id); 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()) { if(addrConIter != addrConMap.end()) {
addrConIter->second.erase(optE.value().conId); addrConIter->second.erase(optE.value.conId);
if(addrConIter->second.empty()) { if(addrConIter->second.empty()) {
addrConMap.erase(addrConIter); addrConMap.erase(addrConIter);
} }
@ -607,18 +607,18 @@ void UDPC::Context::update_impl() {
while(true) { while(true) {
auto next = sendIter.current(); auto next = sendIter.current();
if(next) { if(next) {
if(auto iter = conMap.find(next.value().receiver); auto iter = conMap.find(next.value.receiver);
iter != conMap.end()) { if(iter != conMap.end()) {
if(iter->second.sendPkts.size() >= UDPC_QUEUED_PKTS_MAX_SIZE) { if(iter->second.sendPkts.size() >= UDPC_QUEUED_PKTS_MAX_SIZE) {
if(notQueued.find(next.value().receiver) == notQueued.end()) { if(notQueued.find(next.value.receiver) == notQueued.end()) {
notQueued.insert(next.value().receiver); notQueued.insert(next.value.receiver);
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_DEBUG, UDPC_LoggingType::UDPC_DEBUG,
"Not queueing packet to ", "Not queueing packet to ",
UDPC_atostr((UDPC_HContext)this, UDPC_atostr((UDPC_HContext)this,
next.value().receiver.addr), next.value.receiver.addr),
", port = ", ", port = ",
next.value().receiver.port, next.value.receiver.port,
", connection's queue reached max size"); ", connection's queue reached max size");
} }
if(sendIter.next()) { if(sendIter.next()) {
@ -627,24 +627,24 @@ void UDPC::Context::update_impl() {
break; break;
} }
} }
iter->second.sendPkts.push_back(next.value()); iter->second.sendPkts.push_back(next.value);
if(sendIter.remove()) { if(sendIter.remove()) {
continue; continue;
} else { } else {
break; break;
} }
} else { } else {
if(dropped.find(next.value().receiver) == dropped.end()) { if(dropped.find(next.value.receiver) == dropped.end()) {
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_WARNING, UDPC_LoggingType::UDPC_WARNING,
"Dropped queued packets to ", "Dropped queued packets to ",
UDPC_atostr( UDPC_atostr(
(UDPC_HContext)this, (UDPC_HContext)this,
next.value().receiver.addr), next.value.receiver.addr),
", port = ", ", port = ",
next.value().receiver.port, next.value.receiver.port,
" due to connection not existing"); " due to connection not existing");
dropped.insert(next.value().receiver); dropped.insert(next.value.receiver);
} }
if(sendIter.remove()) { if(sendIter.remove()) {
continue; continue;
@ -1589,17 +1589,22 @@ UDPC::Context *UDPC::verifyContext(UDPC_HContext ctx) {
} }
bool UDPC::isBigEndian() { bool UDPC::isBigEndian() {
static std::optional<bool> isBigEndian = std::nullopt; /*
if(isBigEndian) { * 0 - unset
return *isBigEndian; * 1 - is big endian
* 2 - is not big endian
*/
static char isBigEndian = 0;
if(isBigEndian != 0) {
return isBigEndian == 1;
} }
union { union {
uint32_t i; uint32_t i;
char c[4]; char c[4];
} bint = {0x01020304}; } bint = {0x01020304};
isBigEndian = (bint.c[0] == 1); isBigEndian = (bint.c[0] == 1 ? 1 : 2);
return *isBigEndian; return isBigEndian;
} }
void UDPC::preparePacket( void UDPC::preparePacket(
@ -1923,8 +1928,8 @@ void UDPC_destroy(UDPC_HContext ctx) {
#endif #endif
while(!UDPC_ctx->internalEvents.empty()) { while(!UDPC_ctx->internalEvents.empty()) {
auto optE = UDPC_ctx->internalEvents.top_and_pop(); auto optE = UDPC_ctx->internalEvents.top_and_pop();
if(optE.has_value() && optE.value().type == UDPC_ET_REQUEST_CONNECT_PK) { if(optE.has_value() && optE.value.type == UDPC_ET_REQUEST_CONNECT_PK) {
delete[] optE.value().v.pk; delete[] optE.value.v.pk;
} }
} }
UDPC_ctx->_contextIdentifier = 0; 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); auto optE = c->externalEvents.top_and_pop_and_rsize(remaining);
if(optE) { if(optE) {
return optE.value(); return optE.value;
} else { } else {
return UDPC_Event{UDPC_ET_NONE, UDPC_create_id_anyaddr(0), 0}; return UDPC_Event{UDPC_ET_NONE, UDPC_create_id_anyaddr(0), 0};
} }

View file

@ -18,7 +18,7 @@ TEST(TSLQueue, PushTopPopSize) {
for(int i = 0; i < 10; ++i) { for(int i = 0; i < 10; ++i) {
auto v = q.top(); auto v = q.top();
ASSERT_TRUE(v.has_value()); ASSERT_TRUE(v.has_value());
EXPECT_EQ(v.value(), i); EXPECT_EQ(v.value, i);
EXPECT_EQ(10 - i, q.size()); EXPECT_EQ(10 - i, q.size());
EXPECT_TRUE(q.pop()); EXPECT_TRUE(q.pop());
} }
@ -38,11 +38,11 @@ TEST(TSLQueue, PushNB_TopNB_TopAndPop_Size) {
for(int i = 0; i < 10; ++i) { for(int i = 0; i < 10; ++i) {
auto v = q.top_nb(); auto v = q.top_nb();
ASSERT_TRUE(v.has_value()); ASSERT_TRUE(v.has_value());
EXPECT_EQ(v.value(), i); EXPECT_EQ(v.value, i);
EXPECT_EQ(q.size(), 10 - i); EXPECT_EQ(q.size(), 10 - i);
v = q.top_and_pop(); v = q.top_and_pop();
ASSERT_TRUE(v.has_value()); 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); EXPECT_EQ(q.size(), 10 - i);
auto v = q.top_and_pop_and_empty(&isEmpty); auto v = q.top_and_pop_and_empty(&isEmpty);
ASSERT_TRUE(v.has_value()); ASSERT_TRUE(v.has_value());
EXPECT_EQ(v.value(), i); EXPECT_EQ(v.value, i);
EXPECT_EQ(i == 9, isEmpty); EXPECT_EQ(i == 9, isEmpty);
} }
EXPECT_EQ(q.size(), 0); EXPECT_EQ(q.size(), 0);
@ -110,8 +110,8 @@ TEST(TSLQueue, Concurrent) {
EXPECT_EQ(q.size(), 100 - i); EXPECT_EQ(q.size(), 100 - i);
auto v = q.top_and_pop(); auto v = q.top_and_pop();
ASSERT_TRUE(v.has_value()); ASSERT_TRUE(v.has_value());
EXPECT_GE(v.value(), 0); EXPECT_GE(v.value, 0);
EXPECT_LE(v.value(), 100); EXPECT_LE(v.value, 100);
EXPECT_EQ(i == 99, q.empty()); EXPECT_EQ(i == 99, q.empty());
} }
EXPECT_EQ(q.size(), 0); EXPECT_EQ(q.size(), 0);
@ -131,7 +131,7 @@ TEST(TSLQueue, Iterator) {
int i = 0; int i = 0;
auto op = iter.current(); auto op = iter.current();
while(op.has_value()) { while(op.has_value()) {
EXPECT_EQ(op.value(), i++); EXPECT_EQ(op.value, i++);
if(i < 10) { if(i < 10) {
EXPECT_TRUE(iter.next()); EXPECT_TRUE(iter.next());
} else { } else {
@ -149,7 +149,7 @@ TEST(TSLQueue, Iterator) {
EXPECT_TRUE(iter.prev()); EXPECT_TRUE(iter.prev());
op = iter.current(); op = iter.current();
while(op.has_value()) { while(op.has_value()) {
EXPECT_EQ(op.value(), --i); EXPECT_EQ(op.value, --i);
if(i > 0) { if(i > 0) {
EXPECT_TRUE(iter.prev()); EXPECT_TRUE(iter.prev());
} else { } else {
@ -169,22 +169,22 @@ TEST(TSLQueue, Iterator) {
auto op = iter.current(); auto op = iter.current();
EXPECT_TRUE(op.has_value()); EXPECT_TRUE(op.has_value());
EXPECT_EQ(op.value(), 4); EXPECT_EQ(op.value, 4);
EXPECT_TRUE(iter.prev()); EXPECT_TRUE(iter.prev());
op = iter.current(); op = iter.current();
EXPECT_TRUE(op.has_value()); EXPECT_TRUE(op.has_value());
EXPECT_EQ(op.value(), 2); EXPECT_EQ(op.value, 2);
} }
EXPECT_EQ(q.size(), 9); EXPECT_EQ(q.size(), 9);
// check that "3" was removed from queue // check that "3" was removed from queue
int i = 0; int i = 0;
std::optional<int> op; TSLQueue<int>::Entry op;
while(!q.empty()) { while(!q.empty()) {
op = q.top(); op = q.top();
EXPECT_TRUE(op.has_value()); EXPECT_TRUE(op.has_value());
EXPECT_EQ(i++, op.value()); EXPECT_EQ(i++, op.value);
if(i == 3) { if(i == 3) {
++i; ++i;
} }
@ -206,7 +206,7 @@ TEST(TSLQueue, Iterator) {
while(!q.empty()) { while(!q.empty()) {
op = q.top(); op = q.top();
EXPECT_TRUE(op.has_value()); EXPECT_TRUE(op.has_value());
EXPECT_EQ(i++, op.value()); EXPECT_EQ(i++, op.value);
EXPECT_TRUE(q.pop()); EXPECT_TRUE(q.pop());
} }
@ -222,7 +222,7 @@ TEST(TSLQueue, Iterator) {
EXPECT_TRUE(iter.next()); EXPECT_TRUE(iter.next());
op = iter.current(); op = iter.current();
EXPECT_TRUE(op.has_value()); EXPECT_TRUE(op.has_value());
if(op.value() == 3) { if(op.value == 3) {
EXPECT_FALSE(iter.remove()); EXPECT_FALSE(iter.remove());
break; break;
} }
@ -233,7 +233,7 @@ TEST(TSLQueue, Iterator) {
while(!q.empty()) { while(!q.empty()) {
op = q.top(); op = q.top();
EXPECT_TRUE(op.has_value()); EXPECT_TRUE(op.has_value());
EXPECT_EQ(i++, op.value()); EXPECT_EQ(i++, op.value);
EXPECT_TRUE(q.pop()); EXPECT_TRUE(q.pop());
if(i == 3) { if(i == 3) {
EXPECT_TRUE(q.empty()); EXPECT_TRUE(q.empty());