Skip to content

Commit 8149c3b

Browse files
committed
Add use of a thread for resource loading
If use thread is enabled in the language server, threaded load from ResourceLoader will be utilized. Only one load task will be running at a time. Remove unused header
1 parent 38991a8 commit 8149c3b

5 files changed

+144
-24
lines changed

modules/gdscript/language_server/gdscript_language_protocol.cpp

+133-19
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "gdscript_language_protocol.h"
3232

3333
#include "core/config/project_settings.h"
34+
#include "core/error/error_list.h"
35+
#include "core/io/resource_loader.h"
3436
#include "editor/doc_tools.h"
3537
#include "editor/editor_help.h"
3638
#include "editor/editor_log.h"
@@ -238,6 +240,8 @@ void GDScriptLanguageProtocol::poll(int p_limit_usec) {
238240
on_client_connected();
239241
}
240242

243+
scene_cache._check_thread_for_cache_update();
244+
241245
HashMap<int, Ref<LSPeer>>::Iterator E = clients.begin();
242246
while (E != clients.end()) {
243247
Ref<LSPeer> peer = E->value;
@@ -350,17 +354,17 @@ GDScriptLanguageProtocol::GDScriptLanguageProtocol() {
350354
scene_cache.workspace = workspace;
351355
}
352356

353-
void SceneCache::_get_owners(EditorFileSystemDirectory *efsd, String p_path, List<String> &owners) {
354-
if (!efsd) {
357+
void SceneCache::_get_owners(EditorFileSystemDirectory *p_efsd, String p_path, List<String> &r_owners) {
358+
if (!p_efsd) {
355359
return;
356360
}
357361

358-
for (int i = 0; i < efsd->get_subdir_count(); i++) {
359-
_get_owners(efsd->get_subdir(i), p_path, owners);
362+
for (int i = 0; i < p_efsd->get_subdir_count(); i++) {
363+
_get_owners(p_efsd->get_subdir(i), p_path, r_owners);
360364
}
361365

362-
for (int i = 0; i < efsd->get_file_count(); i++) {
363-
Vector<String> deps = efsd->get_file_deps(i);
366+
for (int i = 0; i < p_efsd->get_file_count(); i++) {
367+
Vector<String> deps = p_efsd->get_file_deps(i);
364368
bool found = false;
365369
for (int j = 0; j < deps.size(); j++) {
366370
if (deps[j] == p_path) {
@@ -372,19 +376,20 @@ void SceneCache::_get_owners(EditorFileSystemDirectory *efsd, String p_path, Lis
372376
continue;
373377
}
374378

375-
owners.push_back(efsd->get_file_path(i));
379+
r_owners.push_back(p_efsd->get_file_path(i));
376380
}
377381
}
378382

379383
void SceneCache::_set_owner_scene_node(String p_path) {
380-
Node *owner_scene_node = nullptr;
381-
List<String> owners;
382-
383384
if (cache.has(p_path)) {
384385
return;
385386
}
386387

388+
Node *owner_scene_node = nullptr;
389+
List<String> owners;
390+
387391
_get_owners(EditorFileSystem::get_singleton()->get_filesystem(), p_path, owners);
392+
owners_path_cache[p_path] = owners;
388393

389394
for (const String &owner : owners) {
390395
NodePath owner_path = owner;
@@ -399,46 +404,155 @@ void SceneCache::_set_owner_scene_node(String p_path) {
399404
cache[p_path] = owner_scene_node;
400405
}
401406

402-
bool SceneCache::has(const String &p_uri) {
403-
return cache.has(p_uri);
407+
/**
408+
* Does only one threaded request to the ResourceLoader at a time.
409+
* Because loading the same subresources in parallel can bring up errors in the editor.
410+
* */
411+
void SceneCache::_add_owner_scene_request(String p_path = "") {
412+
if (p_path.is_empty()) {
413+
if (resource_request_queue.size() > 0) {
414+
p_path = resource_request_queue.front();
415+
} else {
416+
return;
417+
}
418+
}
419+
if (cache.has(p_path) && resource_request_queue.size() == 0) {
420+
return;
421+
}
422+
if (!cache.has(p_path) && !resource_request_queue.has(p_path)) {
423+
resource_request_queue.push_back(p_path);
424+
}
425+
if (is_loading) {
426+
return;
427+
}
428+
429+
String path = resource_request_queue.front();
430+
if (!owners_path_cache.has(p_path)) {
431+
_get_owners(EditorFileSystem::get_singleton()->get_filesystem(), path, owners_path_cache[p_path]);
432+
}
433+
Error r_error = Error::FAILED;
434+
while (r_error != Error::OK && owners_path_cache[p_path].size() > 0) {
435+
NodePath owner_path = owners_path_cache[p_path].front()->get();
436+
r_error = ResourceLoader::load_threaded_request(owner_path);
437+
if (r_error != Error::OK) {
438+
owners_path_cache[path].pop_front();
439+
}
440+
}
441+
if (owners_path_cache[path].size() > 0) {
442+
is_loading = true;
443+
} else {
444+
cache[path] = nullptr;
445+
resource_request_queue.pop_front();
446+
_add_owner_scene_request();
447+
}
448+
}
449+
450+
void SceneCache::_check_thread_for_cache_update() {
451+
if (!is_loading) {
452+
return;
453+
}
454+
455+
String check_path = resource_request_queue.front();
456+
457+
NodePath owner_path = owners_path_cache[check_path].front()->get();
458+
459+
if (ResourceLoader::load_threaded_get_status(owner_path) != ResourceLoader::ThreadLoadStatus::THREAD_LOAD_LOADED) {
460+
return;
461+
}
462+
463+
is_loading = false;
464+
465+
Ref<PackedScene> owner_res = ResourceLoader::load_threaded_get(owner_path);
466+
if (owner_res.is_valid()) {
467+
cache[check_path] = owner_res->instantiate();
468+
owners_path_cache.erase(check_path);
469+
resource_request_queue.pop_front();
470+
_add_owner_scene_request();
471+
return;
472+
}
473+
owners_path_cache[check_path].pop_front();
474+
if (owners_path_cache[check_path].size() == 0) {
475+
cache[check_path] = nullptr;
476+
owners_path_cache.erase(check_path);
477+
resource_request_queue.pop_front();
478+
}
479+
_add_owner_scene_request();
480+
}
481+
482+
bool SceneCache::has(const String &p_path) {
483+
return cache.has(p_path);
404484
}
405485

406-
Node *SceneCache::get(const String &p_uri) {
407-
return cache[p_uri];
486+
Node *SceneCache::get(const String &p_path) {
487+
bool remote_use_thread = (bool)_EDITOR_GET("network/language_server/use_thread");
488+
if (remote_use_thread) {
489+
_check_thread_for_cache_update();
490+
_add_owner_scene_request(p_path);
491+
}
492+
return cache.has(p_path) ? cache[p_path] : nullptr;
408493
}
409494

410495
Node *SceneCache::get_for_uri(const String &p_uri) {
411496
String path = workspace->get_file_path(p_uri);
412-
return cache[path];
497+
return get(path);
413498
}
414499

415500
void SceneCache::set(const String &p_path) {
416-
_set_owner_scene_node(p_path);
501+
bool remote_use_thread = (bool)_EDITOR_GET("network/language_server/use_thread");
502+
if (remote_use_thread) {
503+
_check_thread_for_cache_update();
504+
_add_owner_scene_request(p_path);
505+
} else {
506+
_set_owner_scene_node(p_path);
507+
}
417508
}
418509

419510
void SceneCache::set_for_uri(const String &p_uri) {
420511
String path = workspace->get_file_path(p_uri);
421-
_set_owner_scene_node(path);
512+
set(path);
422513
}
423514

424515
void SceneCache::erase(const String &p_path) {
516+
bool remote_use_thread = (bool)_EDITOR_GET("network/language_server/use_thread");
517+
if (remote_use_thread && resource_request_queue.has(p_path)) {
518+
if (is_loading && resource_request_queue.front() == p_path) {
519+
while (is_loading) {
520+
_check_thread_for_cache_update();
521+
OS::get_singleton()->delay_usec(50000);
522+
}
523+
} else {
524+
resource_request_queue.erase(p_path);
525+
}
526+
}
527+
if (!cache.has(p_path)) {
528+
return;
529+
}
425530
if (cache[p_path]) {
426531
memdelete(cache[p_path]);
427532
}
428533
cache.erase(p_path);
534+
owners_path_cache.erase(p_path);
429535
}
430536

431537
void SceneCache::erase_for_uri(const String &p_uri) {
432538
String path = workspace->get_file_path(p_uri);
433-
memdelete(cache[path]);
434-
cache.erase(path);
539+
erase(path);
435540
}
436541

437542
void SceneCache::clear() {
543+
if (is_loading) {
544+
while (is_loading) {
545+
_check_thread_for_cache_update();
546+
OS::get_singleton()->delay_usec(100);
547+
}
548+
}
549+
resource_request_queue.clear();
438550
for (const KeyValue<String, Node *> &E : cache) {
439551
if (E.value) {
440552
memdelete(E.value);
441553
}
442554
}
443555
cache.clear();
556+
owners_path_cache.clear();
557+
is_loading = false;
444558
}

modules/gdscript/language_server/gdscript_language_protocol.h

+10-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#ifndef GDSCRIPT_LANGUAGE_PROTOCOL_H
3232
#define GDSCRIPT_LANGUAGE_PROTOCOL_H
3333

34+
#include "core/templates/hash_map.h"
3435
#include "core/variant/array.h"
3536
#include "gdscript_text_document.h"
3637
#include "gdscript_workspace.h"
@@ -49,17 +50,23 @@
4950
#define LSP_MAX_BUFFER_SIZE 4194304
5051
#define LSP_MAX_CLIENTS 8
5152

53+
/**
54+
* Used to load and cache scenes for autocompletion.
55+
* */
5256
class SceneCache {
5357
private:
5458
friend class GDScriptLanguageProtocol;
5559

5660
HashMap<String, Node *> cache;
5761
Ref<GDScriptWorkspace> workspace;
58-
String current_resource_request_path;
59-
TypedArray<String> resource_request_queue;
62+
bool is_loading = false;
63+
HashMap<String, List<String>> owners_path_cache;
64+
Array resource_request_queue;
6065

61-
void _get_owners(EditorFileSystemDirectory *efsd, String p_path, List<String> &owners);
66+
void _get_owners(EditorFileSystemDirectory *p_efsd, String p_path, List<String> &r_owners);
6267
void _set_owner_scene_node(String p_path);
68+
void _add_owner_scene_request(String p_path);
69+
void _check_thread_for_cache_update();
6370

6471
public:
6572
bool has(const String &p_path);

modules/gdscript/language_server/gdscript_text_document.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ void GDScriptTextDocument::didChange(const Variant &p_param) {
8383
doc.text = evt.text;
8484
}
8585
sync_script_content(doc.uri, doc.text);
86+
GDScriptLanguageProtocol::get_singleton()->get_scene_cache()->get_for_uri(doc.uri);
8687
}
8788

8889
void GDScriptTextDocument::willSaveWaitUntil(const Variant &p_param) {

modules/gdscript/language_server/gdscript_workspace.h

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#ifndef GDSCRIPT_WORKSPACE_H
3232
#define GDSCRIPT_WORKSPACE_H
3333

34-
#include "../gdscript_parser.h"
3534
#include "gdscript_extend_parser.h"
3635
#include "godot_lsp.h"
3736

modules/gdscript/language_server/godot_lsp.h

-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
#include "core/doc_data.h"
3535
#include "core/object/class_db.h"
3636
#include "core/templates/list.h"
37-
#include "scene/main/node.h"
3837

3938
namespace lsp {
4039

0 commit comments

Comments
 (0)