mirror of https://gitlab.com/nakst/essence
remove loadedFoldersMutex; bugfixes
This commit is contained in:
parent
9ad6930ac7
commit
db3f454bba
|
@ -64,8 +64,11 @@ void CommandRename(Instance *instance, EsElement *, EsCommand *) {
|
|||
|
||||
EsDirectoryChild information = {};
|
||||
EsPathQueryInformation(newPath, newPathBytes, &information);
|
||||
EsMutexAcquire(&folder->modifyEntriesMutex);
|
||||
EsAssert(folder->doneInitialEnumeration);
|
||||
uint64_t id = FolderRemoveEntryAndUpdateInstances(folder, STRING(task->string2));
|
||||
FolderAddEntryAndUpdateInstances(folder, STRING(task->string), &information, instance, false, id);
|
||||
FolderAddEntryAndUpdateInstances(folder, STRING(task->string), &information, instance, id);
|
||||
EsMutexRelease(&folder->modifyEntriesMutex);
|
||||
|
||||
EsHeapFree(oldPath);
|
||||
EsHeapFree(newPath);
|
||||
|
@ -102,7 +105,10 @@ void CommandNewFolder(Instance *instance, EsElement *, EsCommand *) {
|
|||
Folder *folder = instance->folder;
|
||||
EsDirectoryChild information = {};
|
||||
information.type = ES_NODE_DIRECTORY;
|
||||
FolderAddEntryAndUpdateInstances(folder, STRING(task->string), &information, instance, false);
|
||||
EsMutexAcquire(&folder->modifyEntriesMutex);
|
||||
EsAssert(folder->doneInitialEnumeration);
|
||||
FolderAddEntryAndUpdateInstances(folder, STRING(task->string), &information, instance);
|
||||
EsMutexRelease(&folder->modifyEntriesMutex);
|
||||
CommandRename(instance, nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
@ -136,9 +142,7 @@ void InstanceRegisterCommands(Instance *instance) {
|
|||
}, stableCommandID++, "Alt+Up");
|
||||
|
||||
EsCommandRegister(&instance->commandRefresh, instance, [] (Instance *instance, EsElement *, EsCommand *) {
|
||||
EsMutexAcquire(&loadedFoldersMutex);
|
||||
FolderRefresh(instance->folder);
|
||||
EsMutexRelease(&loadedFoldersMutex);
|
||||
}, stableCommandID++, "F5");
|
||||
|
||||
EsCommandRegister(&instance->commandNewFolder, instance, CommandNewFolder, stableCommandID++, "Ctrl+Shift+N");
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
#define NAMESPACE_HANDLER_ROOT (3) // Acts as a container handler where needed.
|
||||
#define NAMESPACE_HANDLER_INVALID (4) // For when a folder does not exist.
|
||||
|
||||
EsMutex loadedFoldersMutex;
|
||||
Array<Folder *> loadedFolders;
|
||||
|
||||
#define MAXIMUM_FOLDERS_WITH_NO_ATTACHED_INSTANCES (20)
|
||||
// #define MAXIMUM_FOLDERS_WITH_NO_ATTACHED_INSTANCES (20)
|
||||
// TODO Temporary.
|
||||
#define MAXIMUM_FOLDERS_WITH_NO_ATTACHED_INSTANCES (0)
|
||||
Array<Folder *> foldersWithNoAttachedInstances;
|
||||
|
||||
/////////////////////////////////
|
||||
|
@ -68,15 +69,16 @@ EsError FSDirEnumerate(Folder *folder) {
|
|||
EsDirectoryChild *buffer = nullptr;
|
||||
ptrdiff_t _entryCount = EsDirectoryEnumerateChildren(STRING(folder->path), &buffer);
|
||||
|
||||
if (ES_CHECK_ERROR(_entryCount)) {
|
||||
EsHeapFree(buffer);
|
||||
return (EsError) _entryCount;
|
||||
if (!ES_CHECK_ERROR(_entryCount)) {
|
||||
for (intptr_t i = 0; i < _entryCount; i++) {
|
||||
FolderAddEntry(folder, buffer[i].name, buffer[i].nameBytes, &buffer[i]);
|
||||
}
|
||||
|
||||
_entryCount = ES_SUCCESS;
|
||||
}
|
||||
|
||||
FolderAddEntries(folder, buffer, _entryCount);
|
||||
EsHeapFree(buffer);
|
||||
|
||||
return ES_SUCCESS;
|
||||
return (EsError) _entryCount;
|
||||
}
|
||||
|
||||
void FSDirGetTotalSize(Folder *folder) {
|
||||
|
@ -252,6 +254,8 @@ void NamespaceFindHandlersForPath(NamespaceHandler **itemHandler, NamespaceHandl
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
EsAssert(*itemHandler && *containerHandler); // NAMESPACE_HANDLER_INVALID should handle failure cases.
|
||||
}
|
||||
|
||||
uint32_t NamespaceGetIcon(String path) {
|
||||
|
@ -327,6 +331,10 @@ void FolderDestroy(Folder *folder) {
|
|||
}
|
||||
}
|
||||
|
||||
StringDestroy(&folder->path);
|
||||
folder->attachedInstances.Free();
|
||||
HashTableFree(&folder->entries, false);
|
||||
EsMutexDestroy(&folder->modifyEntriesMutex);
|
||||
EsHeapFree(folder);
|
||||
}
|
||||
|
||||
|
@ -335,8 +343,10 @@ void FolderDetachInstance(Instance *instance) {
|
|||
if (!folder) return;
|
||||
instance->folder = nullptr;
|
||||
folder->attachedInstances.FindAndDeleteSwap(instance, true);
|
||||
folder->referenceCount--;
|
||||
|
||||
if (!folder->attachedInstances.Length() && !folder->attachingInstances.Length()) {
|
||||
if (!folder->referenceCount) {
|
||||
EsAssert(!folder->attachedInstances.Length());
|
||||
foldersWithNoAttachedInstances.Add(folder);
|
||||
|
||||
if (foldersWithNoAttachedInstances.Length() > MAXIMUM_FOLDERS_WITH_NO_ATTACHED_INSTANCES) {
|
||||
|
@ -391,16 +401,8 @@ FolderEntry *FolderAddEntry(Folder *folder, const char *_name, size_t nameBytes,
|
|||
return entry;
|
||||
}
|
||||
|
||||
void FolderAddEntries(Folder *folder, EsDirectoryChild *buffer, size_t entryCount) {
|
||||
for (uintptr_t i = 0; i < entryCount; i++) {
|
||||
FolderAddEntry(folder, buffer[i].name, buffer[i].nameBytes, &buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FolderAddEntryAndUpdateInstances(Folder *folder, const char *name, size_t nameBytes,
|
||||
EsDirectoryChild *information, Instance *selectItem, bool mutexAlreadyAcquired, uint64_t id = 0) {
|
||||
if (!mutexAlreadyAcquired) EsMutexAcquire(&loadedFoldersMutex);
|
||||
|
||||
EsDirectoryChild *information, Instance *selectItem, uint64_t id = 0) {
|
||||
if (folder->containerHandler->getTotalSize) {
|
||||
folder->containerHandler->getTotalSize(folder);
|
||||
}
|
||||
|
@ -414,13 +416,9 @@ void FolderAddEntryAndUpdateInstances(Folder *folder, const char *name, size_t n
|
|||
InstanceAddSingle(instance, listEntry);
|
||||
InstanceUpdateStatusString(instance);
|
||||
}
|
||||
|
||||
if (!mutexAlreadyAcquired) EsMutexRelease(&loadedFoldersMutex);
|
||||
}
|
||||
|
||||
uint64_t FolderRemoveEntryAndUpdateInstances(Folder *folder, const char *name, size_t nameBytes) {
|
||||
EsMutexAcquire(&loadedFoldersMutex);
|
||||
|
||||
FolderEntry *entry = (FolderEntry *) HashTableGetLong(&folder->entries, name, nameBytes);
|
||||
uint64_t id = 0;
|
||||
|
||||
|
@ -434,15 +432,12 @@ uint64_t FolderRemoveEntryAndUpdateInstances(Folder *folder, const char *name, s
|
|||
FolderEntryCloseHandle(folder, entry);
|
||||
}
|
||||
|
||||
EsMutexRelease(&loadedFoldersMutex);
|
||||
return id;
|
||||
}
|
||||
|
||||
void FolderPathMoved(Instance *instance, String oldPath, String newPath) {
|
||||
_EsPathAnnouncePathMoved(instance, STRING(oldPath), STRING(newPath));
|
||||
|
||||
EsMutexAcquire(&loadedFoldersMutex);
|
||||
|
||||
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
|
||||
Folder *folder = loadedFolders[i];
|
||||
|
||||
|
@ -453,8 +448,6 @@ void FolderPathMoved(Instance *instance, String oldPath, String newPath) {
|
|||
}
|
||||
}
|
||||
|
||||
EsMutexRelease(&loadedFoldersMutex);
|
||||
|
||||
for (uintptr_t i = 0; i < bookmarks.Length(); i++) {
|
||||
PathReplacePrefix(&bookmarks[i], oldPath, newPath);
|
||||
}
|
||||
|
@ -502,21 +495,12 @@ void FolderPathMoved(Instance *instance, String oldPath, String newPath) {
|
|||
ConfigurationSave();
|
||||
}
|
||||
|
||||
EsError FolderAttachInstance(Instance *instance, String path, bool recurse, Folder **newFolder) {
|
||||
// TODO Don't modify attachedInstances/attachingInstances/loadedFolders without the message mutex!
|
||||
// And then we can remove loadedFoldersMutex.
|
||||
|
||||
// (Called on the blocking task thread.)
|
||||
|
||||
void FolderAttachInstance(Instance *instance, String path, bool recurse) {
|
||||
Folder *folder = nullptr;
|
||||
NamespaceHandler *itemHandler = nullptr, *containerHandler = nullptr;
|
||||
EsError error;
|
||||
bool driveRemoved = false;
|
||||
|
||||
// Check if we've already loaded the folder.
|
||||
|
||||
EsMutexAcquire(&loadedFoldersMutex);
|
||||
|
||||
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
|
||||
if (StringEquals(loadedFolders[i]->path, path) && loadedFolders[i]->recurse == recurse) {
|
||||
if (!loadedFolders[i]->refreshing) {
|
||||
|
@ -528,70 +512,39 @@ EsError FolderAttachInstance(Instance *instance, String path, bool recurse, Fold
|
|||
}
|
||||
}
|
||||
|
||||
EsMutexRelease(&loadedFoldersMutex);
|
||||
|
||||
// Find the handler for the path.
|
||||
|
||||
NamespaceFindHandlersForPath(&itemHandler, &containerHandler, path);
|
||||
|
||||
if (!itemHandler || !containerHandler) {
|
||||
return ES_ERROR_FILE_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
// Load a new folder.
|
||||
|
||||
folder = (Folder *) EsHeapAllocate(sizeof(Folder), true);
|
||||
|
||||
folder->path = StringDuplicate(path);
|
||||
folder->recurse = recurse;
|
||||
folder->itemHandler = itemHandler;
|
||||
folder->containerHandler = containerHandler;
|
||||
NamespaceFindHandlersForPath(&folder->itemHandler, &folder->containerHandler, path);
|
||||
folder->cEmptyMessage = interfaceString_FileManagerEmptyFolderView;
|
||||
folder->driveRemoved = driveRemoved;
|
||||
|
||||
EsArenaInitialise(&folder->entryArena, 1048576, sizeof(FolderEntry));
|
||||
|
||||
// TODO Make this asynchronous for some folder providers, or recursive requests
|
||||
// (that is, immediately present to the user while streaming data in).
|
||||
error = itemHandler->enumerate(folder);
|
||||
|
||||
folder->driveRemoved = false;
|
||||
folder->refreshing = false;
|
||||
|
||||
if (error != ES_SUCCESS) {
|
||||
StringDestroy(&folder->path);
|
||||
EsHeapFree(folder);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (containerHandler->getTotalSize) {
|
||||
containerHandler->getTotalSize(folder);
|
||||
}
|
||||
|
||||
EsMutexAcquire(&loadedFoldersMutex);
|
||||
loadedFolders.Add(folder);
|
||||
|
||||
success:;
|
||||
|
||||
foldersWithNoAttachedInstances.FindAndDeleteSwap(folder, false);
|
||||
folder->attachingInstances.Add(instance);
|
||||
|
||||
EsMutexRelease(&loadedFoldersMutex);
|
||||
|
||||
*newFolder = folder;
|
||||
return ES_SUCCESS;
|
||||
folder->referenceCount++;
|
||||
FolderDetachInstance(instance);
|
||||
instance->folder = folder;
|
||||
}
|
||||
|
||||
void FolderRefresh(Folder *folder) {
|
||||
// EsMutexAssertLocked(&loadedFoldersMutex);
|
||||
|
||||
if (folder->refreshing) {
|
||||
return;
|
||||
}
|
||||
|
||||
folder->refreshing = true;
|
||||
|
||||
Array<Instance *> instancesToRefresh = {};
|
||||
|
||||
for (uintptr_t i = 0; i < folder->attachedInstances.Length(); i++) {
|
||||
InstanceLoadFolder(folder->attachedInstances[i], StringDuplicate(folder->path), LOAD_FOLDER_REFRESH);
|
||||
instancesToRefresh.Add(folder->attachedInstances[i]);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < instancesToRefresh.Length(); i++) {
|
||||
InstanceLoadFolder(instancesToRefresh[i], StringDuplicate(folder->path), LOAD_FOLDER_REFRESH);
|
||||
}
|
||||
|
||||
instancesToRefresh.Free();
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ struct HistoryEntry {
|
|||
};
|
||||
|
||||
struct Drive {
|
||||
const char *prefix;
|
||||
char *prefix;
|
||||
size_t prefixBytes;
|
||||
EsVolumeInformation information;
|
||||
};
|
||||
|
@ -201,18 +201,20 @@ struct Folder {
|
|||
EsArena entryArena;
|
||||
|
||||
Array<Instance *> attachedInstances;
|
||||
Array<Instance *> attachingInstances;
|
||||
uintptr_t referenceCount;
|
||||
|
||||
String path;
|
||||
bool recurse;
|
||||
bool refreshing;
|
||||
bool driveRemoved;
|
||||
|
||||
bool doneInitialEnumeration;
|
||||
EsMutex modifyEntriesMutex;
|
||||
|
||||
EsFileOffset spaceTotal;
|
||||
EsFileOffset spaceUsed;
|
||||
|
||||
NamespaceHandler *itemHandler, *containerHandler;
|
||||
|
||||
const char *cEmptyMessage;
|
||||
};
|
||||
|
||||
|
@ -409,6 +411,25 @@ void ConfigurationSave() {
|
|||
#include "commands.cpp"
|
||||
#include "ui.cpp"
|
||||
|
||||
void DriveRefreshFolders(bool removed, const char *prefix, size_t prefixBytes) {
|
||||
Array<Folder *> foldersToRefresh = {};
|
||||
|
||||
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
|
||||
Folder *folder = loadedFolders[i];
|
||||
|
||||
if (folder->itemHandler->type == NAMESPACE_HANDLER_DRIVES_PAGE || StringStartsWith(folder->path, StringFromLiteralWithSize(prefix, prefixBytes))) {
|
||||
foldersToRefresh.Add(folder);
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < foldersToRefresh.Length(); i++) {
|
||||
foldersToRefresh[i]->driveRemoved = removed;
|
||||
FolderRefresh(foldersToRefresh[i]);
|
||||
}
|
||||
|
||||
foldersToRefresh.Free();
|
||||
}
|
||||
|
||||
void DriveRemove(const char *prefix, size_t prefixBytes) {
|
||||
if (!prefixBytes || prefix[0] == '|') return;
|
||||
EsMutexAcquire(&drivesMutex);
|
||||
|
@ -416,6 +437,7 @@ void DriveRemove(const char *prefix, size_t prefixBytes) {
|
|||
|
||||
for (uintptr_t index = 0; index < drives.Length(); index++) {
|
||||
if (0 == EsStringCompareRaw(prefix, prefixBytes, drives[index].prefix, drives[index].prefixBytes)) {
|
||||
EsHeapFree(drives[index].prefix);
|
||||
drives.Delete(index);
|
||||
found = true;
|
||||
|
||||
|
@ -429,20 +451,7 @@ void DriveRemove(const char *prefix, size_t prefixBytes) {
|
|||
|
||||
EsAssert(found);
|
||||
EsMutexRelease(&drivesMutex);
|
||||
|
||||
EsMutexAcquire(&loadedFoldersMutex);
|
||||
|
||||
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
|
||||
Folder *folder = loadedFolders[i];
|
||||
|
||||
if (folder->itemHandler->type == NAMESPACE_HANDLER_DRIVES_PAGE
|
||||
|| StringStartsWith(folder->path, StringFromLiteralWithSize(prefix, prefixBytes))) {
|
||||
folder->driveRemoved = true;
|
||||
FolderRefresh(folder);
|
||||
}
|
||||
}
|
||||
|
||||
EsMutexRelease(&loadedFoldersMutex);
|
||||
DriveRefreshFolders(true, prefix, prefixBytes);
|
||||
}
|
||||
|
||||
void DriveAdd(const char *prefix, size_t prefixBytes) {
|
||||
|
@ -451,7 +460,8 @@ void DriveAdd(const char *prefix, size_t prefixBytes) {
|
|||
EsMutexAcquire(&drivesMutex);
|
||||
|
||||
Drive drive = {};
|
||||
drive.prefix = prefix;
|
||||
drive.prefix = (char *) EsHeapAllocate(prefixBytes, false);
|
||||
EsMemoryCopy(drive.prefix, prefix, prefixBytes);
|
||||
drive.prefixBytes = prefixBytes;
|
||||
EsMountPointGetVolumeInformation(prefix, prefixBytes, &drive.information);
|
||||
drives.Add(drive);
|
||||
|
@ -461,13 +471,7 @@ void DriveAdd(const char *prefix, size_t prefixBytes) {
|
|||
}
|
||||
|
||||
EsMutexRelease(&drivesMutex);
|
||||
|
||||
for (uintptr_t i = 0; i < instances.Length(); i++) {
|
||||
if (instances[i]->folder->itemHandler->type == NAMESPACE_HANDLER_DRIVES_PAGE
|
||||
|| StringStartsWith(instances[i]->folder->path, StringFromLiteralWithSize(prefix, prefixBytes))) {
|
||||
FolderRefresh(instances[i]->folder);
|
||||
}
|
||||
}
|
||||
DriveRefreshFolders(false, prefix, prefixBytes);
|
||||
}
|
||||
|
||||
void LoadSettings() {
|
||||
|
@ -528,7 +532,6 @@ void _start() {
|
|||
InstanceCreateUI(instance);
|
||||
} else if (message->type == ES_MSG_INSTANCE_DESTROY) {
|
||||
// TODO Cleanup/cancel any unfinished non-blocking tasks before we get here!
|
||||
|
||||
Instance *instance = message->instanceDestroy.instance;
|
||||
InstanceDestroy(instance);
|
||||
instances.FindAndDeleteSwap(instance, true);
|
||||
|
@ -549,15 +552,18 @@ void _start() {
|
|||
EsDirectoryChild information = {};
|
||||
|
||||
if (EsPathQueryInformation(STRING(path), &information)) {
|
||||
EsMutexAcquire(&loadedFoldersMutex);
|
||||
|
||||
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
|
||||
if (loadedFolders[i]->itemHandler->type != NAMESPACE_HANDLER_FILE_SYSTEM) continue;
|
||||
if (EsStringCompareRaw(STRING(loadedFolders[i]->path), STRING(folder))) continue;
|
||||
FolderAddEntryAndUpdateInstances(loadedFolders[i], file.text, file.bytes, &information, nullptr, true);
|
||||
}
|
||||
|
||||
EsMutexRelease(&loadedFoldersMutex);
|
||||
EsMutexAcquire(&loadedFolders[i]->modifyEntriesMutex);
|
||||
|
||||
if (loadedFolders[i]->doneInitialEnumeration) {
|
||||
FolderAddEntryAndUpdateInstances(loadedFolders[i], file.text, file.bytes, &information, nullptr);
|
||||
}
|
||||
|
||||
EsMutexRelease(&loadedFolders[i]->modifyEntriesMutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,37 +23,46 @@ void InstanceFolderPathChanged(Instance *instance, bool fromLoadFolder) {
|
|||
}
|
||||
|
||||
bool InstanceLoadFolder(Instance *instance, String path /* takes ownership */, int historyMode) {
|
||||
// Check if the path hasn't changed.
|
||||
|
||||
if (instance->folder && !instance->folder->refreshing && StringEquals(path, instance->folder->path)) {
|
||||
// The path hasn't changed; ignore.
|
||||
StringDestroy(&path);
|
||||
return true;
|
||||
}
|
||||
|
||||
InstanceRemoveContents(instance);
|
||||
FolderAttachInstance(instance, path, false);
|
||||
StringDestroy(&path);
|
||||
|
||||
Task task = {};
|
||||
|
||||
task.context = historyMode;
|
||||
task.string = path;
|
||||
task.cDescription = interfaceString_FileManagerOpenFolderTask;
|
||||
|
||||
task.callback = [] (Instance *instance, Task *task) {
|
||||
Folder *newFolder = nullptr;
|
||||
task->result = FolderAttachInstance(instance, task->string, false, &newFolder);
|
||||
task->context2 = newFolder;
|
||||
StringDestroy(&task->string);
|
||||
task.callback = [] (Instance *instance, Task *) {
|
||||
Folder *folder = instance->folder;
|
||||
EsMutexAcquire(&folder->modifyEntriesMutex);
|
||||
|
||||
if (!folder->doneInitialEnumeration) {
|
||||
folder->itemHandler->enumerate(folder);
|
||||
|
||||
if (folder->containerHandler->getTotalSize) {
|
||||
folder->containerHandler->getTotalSize(folder);
|
||||
}
|
||||
|
||||
folder->driveRemoved = false;
|
||||
folder->refreshing = false;
|
||||
folder->doneInitialEnumeration = true;
|
||||
}
|
||||
|
||||
EsMutexRelease(&folder->modifyEntriesMutex);
|
||||
};
|
||||
|
||||
task.then = [] (Instance *instance, Task *task) {
|
||||
if (ES_CHECK_ERROR(task->result)) {
|
||||
EsTextboxSelectAll(instance->breadcrumbBar);
|
||||
EsTextboxInsert(instance->breadcrumbBar, STRING(instance->path));
|
||||
InstanceReportError(instance, ERROR_LOAD_FOLDER, task->result);
|
||||
return;
|
||||
}
|
||||
// TODO Check if folder was marked for refresh.
|
||||
|
||||
int historyMode = task->context.i & 0xFF;
|
||||
int flags = task->context.i;
|
||||
Folder *folder = (Folder *) task->context2.p;
|
||||
Folder *folder = instance->folder;
|
||||
folder->attachedInstances.Add(instance);
|
||||
|
||||
// Add the path to the history array.
|
||||
|
||||
|
@ -92,13 +101,6 @@ bool InstanceLoadFolder(Instance *instance, String path /* takes ownership */, i
|
|||
EsCommandSetDisabled(&instance->commandRename, true);
|
||||
EsCommandSetDisabled(&instance->commandRefresh, false);
|
||||
|
||||
// Detach from the old folder.
|
||||
|
||||
EsMutexAcquire(&loadedFoldersMutex);
|
||||
|
||||
InstanceRemoveContents(instance);
|
||||
FolderDetachInstance(instance);
|
||||
|
||||
// Load the view settings for the folder.
|
||||
|
||||
bool foundViewSettings = false;
|
||||
|
@ -129,24 +131,13 @@ bool InstanceLoadFolder(Instance *instance, String path /* takes ownership */, i
|
|||
|
||||
InstanceRefreshViewType(instance);
|
||||
|
||||
// Attach to the new folder.
|
||||
|
||||
folder->attachingInstances.FindAndDeleteSwap(instance, true);
|
||||
instance->folder = folder;
|
||||
folder->attachedInstances.Add(instance);
|
||||
// Update the user interface.
|
||||
|
||||
EsListViewSetEmptyMessage(instance->list, folder->cEmptyMessage);
|
||||
InstanceAddContents(instance, &folder->entries);
|
||||
|
||||
EsMutexRelease(&loadedFoldersMutex);
|
||||
|
||||
InstanceFolderPathChanged(instance, true);
|
||||
|
||||
if (~flags & LOAD_FOLDER_NO_FOCUS) {
|
||||
EsElementFocus(instance->list);
|
||||
}
|
||||
|
||||
EsListViewInvalidateAll(instance->placesView);
|
||||
if (~flags & LOAD_FOLDER_NO_FOCUS) EsElementFocus(instance->list);
|
||||
};
|
||||
|
||||
BlockingTaskQueue(instance, task);
|
||||
|
@ -277,7 +268,7 @@ void InstanceUpdateStatusString(Instance *instance) {
|
|||
}
|
||||
|
||||
void InstanceAddSingle(Instance *instance, ListEntry entry) {
|
||||
// Call with loadedFoldersMutex and message mutex.
|
||||
// Call with the message mutex acquired.
|
||||
|
||||
if (!InstanceAddInternal(instance, &entry)) {
|
||||
return; // Filtered out.
|
||||
|
@ -326,7 +317,7 @@ ES_MACRO_SORT(InstanceSortListContents, ListEntry, {
|
|||
}, uint16_t);
|
||||
|
||||
void InstanceAddContents(Instance *instance, HashTable *newEntries) {
|
||||
// Call with loadedFoldersMutex and message mutex.
|
||||
// Call with the message mutex acquired.
|
||||
|
||||
size_t oldListEntryCount = instance->listContents.Length();
|
||||
|
||||
|
|
|
@ -742,7 +742,7 @@ EsMessage *EsMessageReceive() {
|
|||
elements.Free();
|
||||
}
|
||||
|
||||
instance->commands.Free(false);
|
||||
instance->commands.Free();
|
||||
if (instance->fileStore) FileStoreCloseHandle(instance->fileStore);
|
||||
EsHeapFree(instance);
|
||||
EsHeapFree(message.message.instanceDestroy.instance);
|
||||
|
|
|
@ -116,6 +116,7 @@ struct InstalledApplication {
|
|||
uint64_t permissions;
|
||||
size_t openInstanceCount; // Only used if useSingleProcess is true.
|
||||
EsHandle singleProcessHandle;
|
||||
bool notified; // Temporary flag.
|
||||
};
|
||||
|
||||
struct CrashedTabInstance : EsInstance {
|
||||
|
@ -2010,19 +2011,31 @@ void DesktopMessage(EsMessage *message) {
|
|||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->application && (instance->application->permissions & APPLICATION_PERMISSION_ALL_FILES) && instance->processHandle) {
|
||||
if (instance->application && (instance->application->permissions & APPLICATION_PERMISSION_ALL_FILES)
|
||||
&& instance->processHandle && !instance->application->notified) {
|
||||
message->registerFileSystem.rootDirectory = EsSyscall(ES_SYSCALL_NODE_SHARE, rootDirectory, instance->processHandle, 0, 0);
|
||||
EsMessagePostRemote(instance->processHandle, message);
|
||||
if (instance->application->useSingleProcess) instance->application->notified = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
desktop.installedApplications[i]->notified = false;
|
||||
}
|
||||
} else if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->application && (instance->application->permissions & APPLICATION_PERMISSION_ALL_FILES) && instance->processHandle) {
|
||||
if (instance->application && (instance->application->permissions & APPLICATION_PERMISSION_ALL_FILES)
|
||||
&& instance->processHandle && !instance->application->notified) {
|
||||
EsMessagePostRemote(instance->processHandle, message);
|
||||
if (instance->application->useSingleProcess) instance->application->notified = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
desktop.installedApplications[i]->notified = false;
|
||||
}
|
||||
} else if (message->type == ES_MSG_DEVICE_CONNECTED) {
|
||||
desktop.connectedDevices.Add(message->device);
|
||||
} else if (message->type == ES_MSG_DEVICE_DISCONNECTED) {
|
||||
|
|
|
@ -349,7 +349,7 @@ bool HashStoreDelete(HashTable *table, HashStoreOptions *options, const void *ke
|
|||
|
||||
//////////////////////////////////////////
|
||||
|
||||
template <class K /* set to char * for long keys */, class V>
|
||||
template <class K /* set to char for long keys */, class V>
|
||||
struct HashStore {
|
||||
HashTable table;
|
||||
|
||||
|
@ -393,8 +393,8 @@ struct HashStore {
|
|||
return HashStoreDelete(&table, &options, k, bytes);
|
||||
}
|
||||
|
||||
inline void Free(bool variableLengthKeys) {
|
||||
HashTableFree(&table, variableLengthKeys);
|
||||
inline void Free() {
|
||||
HashTableFree(&table, sizeof(K) == 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue