Fixed the IP resolver code blocking the main thread, it uses a Mutex now to lock its own thread.

This commit is contained in:
Marcelo Fernandez 2017-05-06 12:07:35 -03:00 committed by Rémi Verschelde
parent ce6bae1716
commit bba8f1db30

View file

@ -68,6 +68,7 @@ struct _IP_ResolverPrivate {
return IP::RESOLVER_INVALID_ID; return IP::RESOLVER_INVALID_ID;
} }
Mutex *mutex;
Semaphore *sem; Semaphore *sem;
Thread *thread; Thread *thread;
@ -96,8 +97,10 @@ struct _IP_ResolverPrivate {
while (!ipr->thread_abort) { while (!ipr->thread_abort) {
ipr->sem->wait(); ipr->sem->wait();
GLOBAL_LOCK_FUNCTION;
ipr->mutex->lock();
ipr->resolve_queues(); ipr->resolve_queues();
ipr->mutex->unlock();
} }
} }
@ -110,24 +113,30 @@ struct _IP_ResolverPrivate {
IP_Address IP::resolve_hostname(const String &p_hostname, IP::Type p_type) { IP_Address IP::resolve_hostname(const String &p_hostname, IP::Type p_type) {
GLOBAL_LOCK_FUNCTION; resolver->mutex->lock();
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type); String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
if (resolver->cache.has(key)) if (resolver->cache.has(key)) {
return resolver->cache[key]; IP_Address res = resolver->cache[key];
resolver->mutex->unlock();
return res;
}
IP_Address res = _resolve_hostname(p_hostname, p_type); IP_Address res = _resolve_hostname(p_hostname, p_type);
resolver->cache[key] = res; resolver->cache[key] = res;
resolver->mutex->unlock();
return res; return res;
} }
IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Type p_type) { IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Type p_type) {
GLOBAL_LOCK_FUNCTION; resolver->mutex->lock();
ResolverID id = resolver->find_empty_id(); ResolverID id = resolver->find_empty_id();
if (id == RESOLVER_INVALID_ID) { if (id == RESOLVER_INVALID_ID) {
WARN_PRINT("Out of resolver queries"); WARN_PRINT("Out of resolver queries");
resolver->mutex->unlock();
return id; return id;
} }
@ -146,6 +155,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ
resolver->resolve_queues(); resolver->resolve_queues();
} }
resolver->mutex->unlock();
return id; return id;
} }
@ -153,35 +163,51 @@ IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const {
ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP::RESOLVER_STATUS_NONE); ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP::RESOLVER_STATUS_NONE);
GLOBAL_LOCK_FUNCTION; resolver->mutex->lock();
ERR_FAIL_COND_V(resolver->queue[p_id].status == IP::RESOLVER_STATUS_NONE, IP::RESOLVER_STATUS_NONE); if (resolver->queue[p_id].status == IP::RESOLVER_STATUS_NONE) {
ERR_PRINT("Condition status == IP::RESOLVER_STATUS_NONE");
resolver->mutex->unlock();
return IP::RESOLVER_STATUS_NONE;
}
IP::ResolverStatus res = resolver->queue[p_id].status;
return resolver->queue[p_id].status; resolver->mutex->unlock();
return res;
} }
IP_Address IP::get_resolve_item_address(ResolverID p_id) const { IP_Address IP::get_resolve_item_address(ResolverID p_id) const {
ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP_Address()); ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP_Address());
GLOBAL_LOCK_FUNCTION; resolver->mutex->lock();
if (resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE) { if (resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE) {
ERR_EXPLAIN("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet."); ERR_PRINTS("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet.");
ERR_FAIL_COND_V(resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE, IP_Address()); resolver->mutex->unlock();
return IP_Address();
} }
return resolver->queue[p_id].response; IP_Address res = resolver->queue[p_id].response;
resolver->mutex->unlock();
return res;
} }
void IP::erase_resolve_item(ResolverID p_id) { void IP::erase_resolve_item(ResolverID p_id) {
ERR_FAIL_INDEX(p_id, IP::RESOLVER_MAX_QUERIES); ERR_FAIL_INDEX(p_id, IP::RESOLVER_MAX_QUERIES);
GLOBAL_LOCK_FUNCTION; resolver->mutex->lock();
resolver->queue[p_id].status = IP::RESOLVER_STATUS_NONE; resolver->queue[p_id].status = IP::RESOLVER_STATUS_NONE;
resolver->mutex->unlock();
} }
void IP::clear_cache(const String &p_hostname) { void IP::clear_cache(const String &p_hostname) {
resolver->mutex->lock();
if (p_hostname.empty()) { if (p_hostname.empty()) {
resolver->cache.clear(); resolver->cache.clear();
} else { } else {
@ -190,7 +216,9 @@ void IP::clear_cache(const String &p_hostname) {
resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_IPV6)); resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_IPV6));
resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_ANY)); resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_ANY));
} }
};
resolver->mutex->unlock();
}
Array IP::_get_local_addresses() const { Array IP::_get_local_addresses() const {
@ -249,12 +277,11 @@ IP::IP() {
singleton = this; singleton = this;
resolver = memnew(_IP_ResolverPrivate); resolver = memnew(_IP_ResolverPrivate);
resolver->sem = NULL; resolver->sem = NULL;
resolver->mutex = Mutex::create();
#ifndef NO_THREADS #ifndef NO_THREADS
//resolver->sem = Semaphore::create(); resolver->sem = Semaphore::create();
resolver->sem = NULL;
if (resolver->sem) { if (resolver->sem) {
resolver->thread_abort = false; resolver->thread_abort = false;
@ -281,7 +308,9 @@ IP::~IP() {
memdelete(resolver->thread); memdelete(resolver->thread);
memdelete(resolver->sem); memdelete(resolver->sem);
} }
memdelete(resolver);
#endif #endif
memdelete(resolver->mutex);
memdelete(resolver);
} }