Browse Source

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

(cherry picked from commit bba8f1db307459988385faa4e79fd4aace397e36)
Marcelo Fernandez 8 years ago
parent
commit
645636e27c
1 changed files with 47 additions and 18 deletions
  1. 47 18
      core/io/ip.cpp

+ 47 - 18
core/io/ip.cpp

@@ -68,6 +68,7 @@ struct _IP_ResolverPrivate {
 		return IP::RESOLVER_INVALID_ID;
 	}
 
+	Mutex *mutex;
 	Semaphore *sem;
 
 	Thread *thread;
@@ -96,8 +97,10 @@ struct _IP_ResolverPrivate {
 		while (!ipr->thread_abort) {
 
 			ipr->sem->wait();
-			GLOBAL_LOCK_FUNCTION;
+
+			ipr->mutex->lock();
 			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) {
 
-	GLOBAL_LOCK_FUNCTION;
+	resolver->mutex->lock();
 
 	String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
-	if (resolver->cache.has(key))
-		return resolver->cache[key];
+	if (resolver->cache.has(key)) {
+		IP_Address res = resolver->cache[key];
+		resolver->mutex->unlock();
+		return res;
+	}
 
 	IP_Address res = _resolve_hostname(p_hostname, p_type);
 	resolver->cache[key] = res;
+	resolver->mutex->unlock();
 	return res;
 }
+
 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();
 
 	if (id == RESOLVER_INVALID_ID) {
 		WARN_PRINT("Out of resolver queries");
+		resolver->mutex->unlock();
 		return id;
 	}
 
@@ -146,6 +155,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ
 			resolver->resolve_queues();
 	}
 
+	resolver->mutex->unlock();
 	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);
 
-	GLOBAL_LOCK_FUNCTION;
-	ERR_FAIL_COND_V(resolver->queue[p_id].status == IP::RESOLVER_STATUS_NONE, IP::RESOLVER_STATUS_NONE);
+	resolver->mutex->lock();
+	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 {
 
 	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) {
-		ERR_EXPLAIN("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());
+		ERR_PRINTS("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet.");
+		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) {
 
 	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->mutex->unlock();
 }
 
 void IP::clear_cache(const String &p_hostname) {
 
+	resolver->mutex->lock();
+
 	if (p_hostname.empty()) {
 		resolver->cache.clear();
 	} 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_ANY));
 	}
-};
+
+	resolver->mutex->unlock();
+}
 
 Array IP::_get_local_addresses() const {
 
@@ -249,12 +277,11 @@ IP::IP() {
 	singleton = this;
 	resolver = memnew(_IP_ResolverPrivate);
 	resolver->sem = NULL;
+	resolver->mutex = Mutex::create();
 
 #ifndef NO_THREADS
 
-	//resolver->sem = Semaphore::create();
-
-	resolver->sem = NULL;
+	resolver->sem = Semaphore::create();
 	if (resolver->sem) {
 		resolver->thread_abort = false;
 
@@ -281,7 +308,9 @@ IP::~IP() {
 		memdelete(resolver->thread);
 		memdelete(resolver->sem);
 	}
-	memdelete(resolver);
 
 #endif
+
+	memdelete(resolver->mutex);
+	memdelete(resolver);
 }