Thread safety for FanncyZonesData (#1281)

* FancyZones: make FancyZonesData thread-safe

* fixup: format affected sources

* fixup: clang-format case-style and format FancyZones.cpp

* fixup! add missing lock
This commit is contained in:
Andrey Nekrasov
2020-02-17 18:28:49 +03:00
committed by GitHub
parent cdf2f6b5b4
commit 1e6936a8c3
10 changed files with 1631 additions and 1533 deletions

View File

@@ -135,13 +135,10 @@ namespace JSONHelpers
jsonFilePath = result + L"\\" + std::wstring(FANCY_ZONES_DATA_FILE);
}
const std::wstring& FancyZonesData::GetPersistFancyZonesJSONPath() const
{
return jsonFilePath;
}
json::JsonObject FancyZonesData::GetPersistFancyZonesJSON()
{
std::scoped_lock lock{ dataLock };
std::wstring save_file_path = GetPersistFancyZonesJSONPath();
auto result = json::from_file(save_file_path);
@@ -155,12 +152,27 @@ namespace JSONHelpers
}
}
std::optional<DeviceInfoData> FancyZonesData::FindDeviceInfo(const std::wstring& zoneWindowId) const
{
std::scoped_lock lock{ dataLock };
auto it = deviceInfoMap.find(zoneWindowId);
return it != end(deviceInfoMap) ? std::optional{ it->second } : std::nullopt;
}
std::optional<CustomZoneSetData> FancyZonesData::FindCustomZoneSet(const std::wstring& guuid) const
{
std::scoped_lock lock{ dataLock };
auto it = customZoneSetsMap.find(guuid);
return it != end(customZoneSetsMap) ? std::optional{ it->second } : std::nullopt;
}
void FancyZonesData::AddDevice(const std::wstring& deviceId)
{
std::scoped_lock lock{ dataLock };
if (!deviceInfoMap.contains(deviceId))
{
// Creates default entry in map when ZoneWindow is created
deviceInfoMap[deviceId] = DeviceInfoData{ ZoneSetData{ L"null", ZoneSetLayoutType::Blank } };
deviceInfoMap[deviceId] = DeviceInfoData{ ZoneSetData{ L"null", ZoneSetLayoutType::Blank } };
MigrateDeviceInfoFromRegistry(deviceId);
}
@@ -168,6 +180,7 @@ namespace JSONHelpers
void FancyZonesData::CloneDeviceInfo(const std::wstring& source, const std::wstring& destination)
{
std::scoped_lock lock{ dataLock };
// Clone information from source device if destination device is uninitialized (Blank).
auto& destInfo = deviceInfoMap[destination];
if (destInfo.activeZoneSet.type == ZoneSetLayoutType::Blank)
@@ -178,6 +191,7 @@ namespace JSONHelpers
int FancyZonesData::GetAppLastZoneIndex(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const
{
std::scoped_lock lock{ dataLock };
auto processPath = get_process_path(window);
if (!processPath.empty())
{
@@ -188,7 +202,7 @@ namespace JSONHelpers
if (data.zoneSetUuid == zoneSetId && data.deviceId == deviceId)
{
return history->second.zoneIndex;
}
}
}
}
@@ -197,6 +211,7 @@ namespace JSONHelpers
bool FancyZonesData::RemoveAppLastZone(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId)
{
std::scoped_lock lock{ dataLock };
auto processPath = get_process_path(window);
if (!processPath.empty())
{
@@ -218,6 +233,7 @@ namespace JSONHelpers
bool FancyZonesData::SetAppLastZone(HWND window, const std::wstring& deviceId, const std::wstring& zoneSetId, int zoneIndex)
{
std::scoped_lock lock{ dataLock };
auto processPath = get_process_path(window);
if (processPath.empty())
{
@@ -231,6 +247,7 @@ namespace JSONHelpers
void FancyZonesData::SetActiveZoneSet(const std::wstring& deviceId, const ZoneSetData& data)
{
std::scoped_lock lock{ dataLock };
auto it = deviceInfoMap.find(deviceId);
if (it != deviceInfoMap.end())
{
@@ -240,12 +257,14 @@ namespace JSONHelpers
void FancyZonesData::SerializeDeviceInfoToTmpFile(const DeviceInfoJSON& deviceInfo, std::wstring_view tmpFilePath) const
{
std::scoped_lock lock{ dataLock };
json::JsonObject deviceInfoJson = DeviceInfoJSON::ToJson(deviceInfo);
json::to_file(tmpFilePath, deviceInfoJson);
}
void FancyZonesData::ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath)
{
std::scoped_lock lock{ dataLock };
if (std::filesystem::exists(tmpFilePath))
{
if (auto zoneSetJson = json::from_file(tmpFilePath); zoneSetJson.has_value())
@@ -266,6 +285,7 @@ namespace JSONHelpers
bool FancyZonesData::ParseCustomZoneSetFromTmpFile(std::wstring_view tmpFilePath)
{
std::scoped_lock lock{ dataLock };
bool res = true;
if (std::filesystem::exists(tmpFilePath))
{
@@ -291,6 +311,7 @@ namespace JSONHelpers
bool FancyZonesData::ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
{
std::scoped_lock lock{ dataLock };
bool res = true;
if (std::filesystem::exists(tmpFilePath))
{
@@ -317,6 +338,7 @@ namespace JSONHelpers
bool FancyZonesData::ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON)
{
std::scoped_lock lock{ dataLock };
try
{
auto appLastZones = fancyZonesDataJSON.GetNamedArray(L"app-zone-history");
@@ -344,6 +366,7 @@ namespace JSONHelpers
json::JsonArray FancyZonesData::SerializeAppZoneHistory() const
{
std::scoped_lock lock{ dataLock };
json::JsonArray appHistoryArray;
for (const auto& [appPath, appZoneHistoryData] : appZoneHistoryMap)
@@ -356,6 +379,7 @@ namespace JSONHelpers
bool FancyZonesData::ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON)
{
std::scoped_lock lock{ dataLock };
try
{
auto devices = fancyZonesDataJSON.GetNamedArray(L"devices");
@@ -382,11 +406,13 @@ namespace JSONHelpers
json::JsonArray FancyZonesData::SerializeDeviceInfos() const
{
std::scoped_lock lock{ dataLock };
json::JsonArray DeviceInfosJSON{};
for (const auto& [deviceID, deviceData] : deviceInfoMap)
{
if (deviceData.activeZoneSet.type != ZoneSetLayoutType::Blank) {
if (deviceData.activeZoneSet.type != ZoneSetLayoutType::Blank)
{
DeviceInfosJSON.Append(DeviceInfoJSON::DeviceInfoJSON::ToJson(DeviceInfoJSON{ deviceID, deviceData }));
}
}
@@ -396,6 +422,7 @@ namespace JSONHelpers
bool FancyZonesData::ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON)
{
std::scoped_lock lock{ dataLock };
try
{
auto customZoneSets = fancyZonesDataJSON.GetNamedArray(L"custom-zone-sets");
@@ -418,6 +445,7 @@ namespace JSONHelpers
json::JsonArray FancyZonesData::SerializeCustomZoneSets() const
{
std::scoped_lock lock{ dataLock };
json::JsonArray customZoneSetsJSON{};
for (const auto& [zoneSetId, zoneSetData] : customZoneSetsMap)
@@ -430,6 +458,7 @@ namespace JSONHelpers
void FancyZonesData::CustomZoneSetsToJsonFile(std::wstring_view filePath) const
{
std::scoped_lock lock{ dataLock };
const auto& customZoneSetsJson = SerializeCustomZoneSets();
json::JsonObject root{};
root.SetNamedValue(L"custom-zone-sets", customZoneSetsJson);
@@ -438,6 +467,7 @@ namespace JSONHelpers
void FancyZonesData::LoadFancyZonesData()
{
std::scoped_lock lock{ dataLock };
std::wstring jsonFilePath = GetPersistFancyZonesJSONPath();
if (!std::filesystem::exists(jsonFilePath))
@@ -461,6 +491,7 @@ namespace JSONHelpers
void FancyZonesData::SaveFancyZonesData() const
{
std::scoped_lock lock{ dataLock };
json::JsonObject root{};
root.SetNamedValue(L"app-zone-history", SerializeAppZoneHistory());
@@ -474,6 +505,7 @@ namespace JSONHelpers
{
std::wregex ex(L"^[0-9]{3,4}_[0-9]{3,4}$");
std::scoped_lock lock{ dataLock };
wchar_t key[256];
StringCchPrintf(key, ARRAYSIZE(key), L"%s", RegistryHelpers::REG_SETTINGS);
HKEY hkey;
@@ -521,6 +553,7 @@ namespace JSONHelpers
void FancyZonesData::MigrateDeviceInfoFromRegistry(const std::wstring& deviceId)
{
std::scoped_lock lock{ dataLock };
wchar_t key[256];
StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", RegistryHelpers::REG_SETTINGS, deviceId.c_str());
@@ -546,6 +579,7 @@ namespace JSONHelpers
void FancyZonesData::MigrateCustomZoneSetsFromRegistry()
{
std::scoped_lock lock{ dataLock };
wchar_t key[256];
StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", RegistryHelpers::REG_SETTINGS, L"Layouts");
HKEY hkey;
@@ -574,8 +608,7 @@ namespace JSONHelpers
}
switch (zoneSetData.type)
{
case CustomLayoutType::Grid:
{
case CustomLayoutType::Grid: {
int j = 5;
GridLayoutInfo zoneSetInfo(GridLayoutInfo::Minimal{ .rows = data[j++], .columns = data[j++] });
@@ -599,8 +632,7 @@ namespace JSONHelpers
zoneSetData.info = zoneSetInfo;
break;
}
case CustomLayoutType::Canvas:
{
case CustomLayoutType::Canvas: {
CanvasLayoutInfo info;
int j = 5;
@@ -880,8 +912,7 @@ namespace JSONHelpers
result.SetNamedValue(L"name", json::value(customZoneSet.data.name));
switch (customZoneSet.data.type)
{
case CustomLayoutType::Canvas:
{
case CustomLayoutType::Canvas: {
result.SetNamedValue(L"type", json::value(L"canvas"));
CanvasLayoutInfo info = std::get<CanvasLayoutInfo>(customZoneSet.data.info);
@@ -889,8 +920,7 @@ namespace JSONHelpers
break;
}
case CustomLayoutType::Grid:
{
case CustomLayoutType::Grid: {
result.SetNamedValue(L"type", json::value(L"grid"));
GridLayoutInfo gridInfo = std::get<GridLayoutInfo>(customZoneSet.data.info);