Skip to content

Commit 7da2884

Browse files
committed
Add locks for win32s & uwps
1 parent 9f84a2d commit 7da2884

File tree

3 files changed

+83
-30
lines changed

3 files changed

+83
-30
lines changed

Plugins/Flow.Launcher.Plugin.Program/Main.cs

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, I
2727
internal static List<UWPApp> _uwps { get; private set; }
2828
internal static Settings _settings { get; private set; }
2929

30+
internal static SemaphoreSlim _win32sLock = new(1, 1);
31+
internal static SemaphoreSlim _uwpsLock = new(1, 1);
32+
3033
internal static PluginInitContext Context { get; private set; }
3134

3235
private static readonly List<Result> emptyResults = new();
@@ -82,8 +85,11 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
8285
{
8386
var result = await cache.GetOrCreateAsync(query.Search, async entry =>
8487
{
85-
var resultList = await Task.Run(() =>
88+
var resultList = await Task.Run(async () =>
8689
{
90+
await _win32sLock.WaitAsync(token);
91+
await _uwpsLock.WaitAsync(token);
92+
8793
try
8894
{
8995
// Collect all UWP Windows app directories
@@ -95,22 +101,26 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
95101
.ToArray() : null;
96102

97103
return _win32s.Cast<IProgram>()
98-
.Concat(_uwps)
99-
.AsParallel()
100-
.WithCancellation(token)
101-
.Where(HideUninstallersFilter)
102-
.Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories))
103-
.Where(p => p.Enabled)
104-
.Select(p => p.Result(query.Search, Context.API))
105-
.Where(r => r?.Score > 0)
106-
.ToList();
104+
.Concat(_uwps)
105+
.AsParallel()
106+
.WithCancellation(token)
107+
.Where(HideUninstallersFilter)
108+
.Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories))
109+
.Where(p => p.Enabled)
110+
.Select(p => p.Result(query.Search, Context.API))
111+
.Where(r => r?.Score > 0)
112+
.ToList();
107113
}
108114
catch (OperationCanceledException)
109115
{
110116
Log.Debug("|Flow.Launcher.Plugin.Program.Main|Query operation cancelled");
111117
return emptyResults;
112118
}
113-
119+
finally
120+
{
121+
_uwpsLock.Release();
122+
_win32sLock.Release();
123+
}
114124
}, token);
115125

116126
resultList = resultList.Any() ? resultList : emptyResults;
@@ -236,14 +246,25 @@ static void MoveFile(string sourcePath, string destinationPath)
236246
var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache");
237247
MoveFile(oldUWPCacheFile, newUWPCacheFile);
238248

249+
await _win32sLock.WaitAsync();
239250
_win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List<Win32>());
251+
_win32sLock.Release();
252+
253+
await _uwpsLock.WaitAsync();
240254
_uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List<UWPApp>());
255+
_uwpsLock.Release();
241256
});
257+
await _win32sLock.WaitAsync();
258+
await _uwpsLock.WaitAsync();
259+
242260
Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Count}>");
243261
Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Count}>");
244262

245263
bool cacheEmpty = !_win32s.Any() || !_uwps.Any();
246264

265+
_win32sLock.Release();
266+
_uwpsLock.Release();
267+
247268
if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now)
248269
{
249270
_ = Task.Run(async () =>
@@ -267,11 +288,13 @@ static void WatchProgramUpdate()
267288
public static async Task IndexWin32ProgramsAsync()
268289
{
269290
var win32S = Win32.All(_settings);
291+
await _win32sLock.WaitAsync();
270292
_win32s.Clear();
271293
foreach (var win32 in win32S)
272294
{
273295
_win32s.Add(win32);
274296
}
297+
_win32sLock.Release();
275298
ResetCache();
276299
await Context.API.SaveCacheBinaryStorageAsync<List<Win32>>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
277300
_settings.LastIndexTime = DateTime.Now;
@@ -280,11 +303,13 @@ public static async Task IndexWin32ProgramsAsync()
280303
public static async Task IndexUwpProgramsAsync()
281304
{
282305
var uwps = UWPPackage.All(_settings);
306+
await _uwpsLock.WaitAsync();
283307
_uwps.Clear();
284308
foreach (var uwp in uwps)
285309
{
286310
_uwps.Add(uwp);
287311
}
312+
_uwpsLock.Release();
288313
ResetCache();
289314
await Context.API.SaveCacheBinaryStorageAsync<List<UWPApp>>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
290315
_settings.LastIndexTime = DateTime.Now;
@@ -358,26 +383,36 @@ public List<Result> LoadContextMenus(Result selectedResult)
358383
return menuOptions;
359384
}
360385

361-
private static void DisableProgram(IProgram programToDelete)
386+
private static async Task DisableProgram(IProgram programToDelete)
362387
{
363388
if (_settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
364389
return;
365390

391+
await _uwpsLock.WaitAsync();
366392
if (_uwps.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
367393
{
368394
var program = _uwps.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
369395
program.Enabled = false;
370396
_settings.DisabledProgramSources.Add(new ProgramSource(program));
397+
_uwpsLock.Release();
398+
399+
// Reindex UWP programs
371400
_ = Task.Run(() =>
372401
{
373402
_ = IndexUwpProgramsAsync();
374403
});
404+
return;
375405
}
376-
else if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
406+
407+
await _win32sLock.WaitAsync();
408+
if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
377409
{
378410
var program = _win32s.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
379411
program.Enabled = false;
380412
_settings.DisabledProgramSources.Add(new ProgramSource(program));
413+
_win32sLock.Release();
414+
415+
// Reindex Win32 programs
381416
_ = Task.Run(() =>
382417
{
383418
_ = IndexWin32ProgramsAsync();

Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.Linq;
3+
using System.Threading.Tasks;
34
using Flow.Launcher.Plugin.Program.Views.Models;
45

56
namespace Flow.Launcher.Plugin.Program.Views.Commands
@@ -15,21 +16,24 @@ internal static List<ProgramSource> LoadProgramSources()
1516
.ToList();
1617
}
1718

18-
internal static void DisplayAllPrograms()
19+
internal static async Task DisplayAllProgramsAsync()
1920
{
21+
await Main._win32sLock.WaitAsync();
2022
var win32 = Main._win32s
2123
.Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
2224
.Select(x => new ProgramSource(x));
25+
ProgramSetting.ProgramSettingDisplayList.AddRange(win32);
26+
Main._win32sLock.Release();
2327

28+
await Main._uwpsLock.WaitAsync();
2429
var uwp = Main._uwps
2530
.Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
2631
.Select(x => new ProgramSource(x));
27-
28-
ProgramSetting.ProgramSettingDisplayList.AddRange(win32);
2932
ProgramSetting.ProgramSettingDisplayList.AddRange(uwp);
33+
Main._uwpsLock.Release();
3034
}
3135

32-
internal static void SetProgramSourcesStatus(List<ProgramSource> selectedProgramSourcesToDisable, bool status)
36+
internal static async Task SetProgramSourcesStatusAsync(List<ProgramSource> selectedProgramSourcesToDisable, bool status)
3337
{
3438
foreach(var program in ProgramSetting.ProgramSettingDisplayList)
3539
{
@@ -39,21 +43,25 @@ internal static void SetProgramSourcesStatus(List<ProgramSource> selectedProgram
3943
}
4044
}
4145

42-
foreach(var program in Main._win32s)
46+
await Main._win32sLock.WaitAsync();
47+
foreach (var program in Main._win32s)
4348
{
4449
if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status))
4550
{
4651
program.Enabled = status;
4752
}
4853
}
54+
Main._win32sLock.Release();
4955

56+
await Main._uwpsLock.WaitAsync();
5057
foreach (var program in Main._uwps)
5158
{
5259
if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status))
5360
{
5461
program.Enabled = status;
5562
}
5663
}
64+
Main._uwpsLock.Release();
5765
}
5866

5967
internal static void StoreDisabledInSettings()
@@ -72,12 +80,22 @@ internal static void RemoveDisabledFromSettings()
7280
Main._settings.DisabledProgramSources.RemoveAll(t1 => t1.Enabled);
7381
}
7482

75-
internal static bool IsReindexRequired(this List<ProgramSource> selectedItems)
83+
internal static async Task<bool> IsReindexRequiredAsync(this List<ProgramSource> selectedItems)
7684
{
7785
// Not in cache
78-
if (selectedItems.Any(t1 => t1.Enabled && !Main._uwps.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
86+
await Main._win32sLock.WaitAsync();
87+
await Main._uwpsLock.WaitAsync();
88+
try
89+
{
90+
if (selectedItems.Any(t1 => t1.Enabled && !Main._uwps.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
7991
&& selectedItems.Any(t1 => t1.Enabled && !Main._win32s.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)))
80-
return true;
92+
return true;
93+
}
94+
finally
95+
{
96+
Main._win32sLock.Release();
97+
Main._uwpsLock.Release();
98+
}
8199

82100
// ProgramSources holds list of user added directories,
83101
// so when we enable/disable we need to reindex to show/not show the programs

Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ private void btnEditProgramSource_OnClick(object sender, RoutedEventArgs e)
183183
EditProgramSource(selectedProgramSource);
184184
}
185185

186-
private void EditProgramSource(ProgramSource selectedProgramSource)
186+
private async void EditProgramSource(ProgramSource selectedProgramSource)
187187
{
188188
if (selectedProgramSource == null)
189189
{
@@ -202,13 +202,13 @@ private void EditProgramSource(ProgramSource selectedProgramSource)
202202
{
203203
if (selectedProgramSource.Enabled)
204204
{
205-
ProgramSettingDisplay.SetProgramSourcesStatus(new List<ProgramSource> { selectedProgramSource },
205+
await ProgramSettingDisplay.SetProgramSourcesStatusAsync(new List<ProgramSource> { selectedProgramSource },
206206
true); // sync status in win32, uwp and disabled
207207
ProgramSettingDisplay.RemoveDisabledFromSettings();
208208
}
209209
else
210210
{
211-
ProgramSettingDisplay.SetProgramSourcesStatus(new List<ProgramSource> { selectedProgramSource },
211+
await ProgramSettingDisplay.SetProgramSourcesStatusAsync(new List<ProgramSource> { selectedProgramSource },
212212
false);
213213
ProgramSettingDisplay.StoreDisabledInSettings();
214214
}
@@ -277,14 +277,14 @@ private void programSourceView_Drop(object sender, DragEventArgs e)
277277
}
278278
}
279279

280-
private void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
280+
private async void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
281281
{
282-
ProgramSettingDisplay.DisplayAllPrograms();
282+
await ProgramSettingDisplay.DisplayAllProgramsAsync();
283283

284284
ViewRefresh();
285285
}
286286

287-
private void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
287+
private async void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
288288
{
289289
var selectedItems = programSourceView
290290
.SelectedItems.Cast<ProgramSource>()
@@ -311,18 +311,18 @@ private void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
311311
}
312312
else if (HasMoreOrEqualEnabledItems(selectedItems))
313313
{
314-
ProgramSettingDisplay.SetProgramSourcesStatus(selectedItems, false);
314+
await ProgramSettingDisplay.SetProgramSourcesStatusAsync(selectedItems, false);
315315

316316
ProgramSettingDisplay.StoreDisabledInSettings();
317317
}
318318
else
319319
{
320-
ProgramSettingDisplay.SetProgramSourcesStatus(selectedItems, true);
320+
await ProgramSettingDisplay.SetProgramSourcesStatusAsync(selectedItems, true);
321321

322322
ProgramSettingDisplay.RemoveDisabledFromSettings();
323323
}
324324

325-
if (selectedItems.IsReindexRequired())
325+
if (await selectedItems.IsReindexRequiredAsync())
326326
ReIndexing();
327327

328328
programSourceView.SelectedItems.Clear();

0 commit comments

Comments
 (0)