diff options
Diffstat (limited to 'core/io')
-rw-r--r-- | core/io/http_client.cpp | 13 | ||||
-rw-r--r-- | core/io/resource_loader.cpp | 40 | ||||
-rw-r--r-- | core/io/resource_loader.h | 20 |
3 files changed, 57 insertions, 16 deletions
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index b3fd814870..b25b1934ff 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -426,11 +426,10 @@ Error HTTPClient::poll() { response_headers.clear(); response_num = RESPONSE_OK; - // Per the HTTP 1.1 spec, keep-alive is the default, but in practice - // it's safe to assume it only if the explicit header is found, allowing - // to handle body-up-to-EOF responses on naive servers; that's what Curl - // and browsers do - bool keep_alive = false; + // Per the HTTP 1.1 spec, keep-alive is the default. + // Not following that specification breaks standard implemetations. + // Broken web servers should be fixed. + bool keep_alive = true; for (int i = 0; i < responses.size(); i++) { @@ -447,8 +446,8 @@ Error HTTPClient::poll() { if (encoding == "chunked") { chunked = true; } - } else if (s.begins_with("connection: keep-alive")) { - keep_alive = true; + } else if (s.begins_with("connection: close")) { + keep_alive = false; } if (i == 0 && responses[i].begins_with("HTTP")) { diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 4aa002e9a2..10a32bae41 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -55,7 +55,7 @@ Error ResourceInteractiveLoader::wait() { ResourceInteractiveLoader::~ResourceInteractiveLoader() { if (path_loading != String()) { - ResourceLoader::_remove_from_loading_map(path_loading); + ResourceLoader::_remove_from_loading_map_and_thread(path_loading, path_loading_thread); } } @@ -293,10 +293,14 @@ bool ResourceLoader::_add_to_loading_map(const String &p_path) { loading_map_mutex->lock(); } - if (loading_map.has(p_path)) { + LoadingMapKey key; + key.path = p_path; + key.thread = Thread::get_caller_id(); + + if (loading_map.has(key)) { success = false; } else { - loading_map[p_path] = true; + loading_map[key] = true; success = true; } @@ -312,7 +316,27 @@ void ResourceLoader::_remove_from_loading_map(const String &p_path) { loading_map_mutex->lock(); } - loading_map.erase(p_path); + LoadingMapKey key; + key.path = p_path; + key.thread = Thread::get_caller_id(); + + loading_map.erase(key); + + if (loading_map_mutex) { + loading_map_mutex->unlock(); + } +} + +void ResourceLoader::_remove_from_loading_map_and_thread(const String &p_path, Thread::ID p_thread) { + if (loading_map_mutex) { + loading_map_mutex->lock(); + } + + LoadingMapKey key; + key.path = p_path; + key.thread = p_thread; + + loading_map.erase(key); if (loading_map_mutex) { loading_map_mutex->unlock(); @@ -471,6 +495,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_ ril->resource = res_cached; ril->path_loading = local_path; + ril->path_loading_thread = Thread::get_caller_id(); return ril; } } @@ -499,6 +524,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_ if (!p_no_cache) { ril->set_local_path(local_path); ril->path_loading = local_path; + ril->path_loading_thread = Thread::get_caller_id(); } if (xl_remapped) @@ -919,7 +945,7 @@ void ResourceLoader::remove_custom_loaders() { } Mutex *ResourceLoader::loading_map_mutex = NULL; -HashMap<String, int> ResourceLoader::loading_map; +HashMap<ResourceLoader::LoadingMapKey, int, ResourceLoader::LoadingMapKeyHasher> ResourceLoader::loading_map; void ResourceLoader::initialize() { #ifndef NO_THREADS @@ -929,9 +955,9 @@ void ResourceLoader::initialize() { void ResourceLoader::finalize() { #ifndef NO_THREADS - const String *K = NULL; + const LoadingMapKey *K = NULL; while ((K = loading_map.next(K))) { - ERR_PRINTS("Exited while resource is being loaded: " + *K); + ERR_PRINTS("Exited while resource is being loaded: " + K->path); } loading_map.clear(); memdelete(loading_map_mutex); diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 622b74a998..70eb1a3de0 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -31,8 +31,8 @@ #ifndef RESOURCE_LOADER_H #define RESOURCE_LOADER_H +#include "core/os/thread.h" #include "core/resource.h" - /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -42,6 +42,7 @@ class ResourceInteractiveLoader : public Reference { GDCLASS(ResourceInteractiveLoader, Reference); friend class ResourceLoader; String path_loading; + Thread::ID path_loading_thread; protected: static void _bind_methods(); @@ -121,10 +122,25 @@ class ResourceLoader { static Ref<ResourceFormatLoader> _find_custom_resource_format_loader(String path); static Mutex *loading_map_mutex; - static HashMap<String, int> loading_map; + + //used to track paths being loaded in a thread, avoids cyclic recursion + struct LoadingMapKey { + String path; + Thread::ID thread; + bool operator==(const LoadingMapKey &p_key) const { + return (thread == p_key.thread && path == p_key.path); + } + }; + struct LoadingMapKeyHasher { + + static _FORCE_INLINE_ uint32_t hash(const LoadingMapKey &p_key) { return p_key.path.hash() + HashMapHasherDefault::hash(p_key.thread); } + }; + + static HashMap<LoadingMapKey, int, LoadingMapKeyHasher> loading_map; static bool _add_to_loading_map(const String &p_path); static void _remove_from_loading_map(const String &p_path); + static void _remove_from_loading_map_and_thread(const String &p_path, Thread::ID p_thread); public: static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL); |