summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2023-01-09 22:10:08 +0100
committerRoman Smrž <roman.smrz@seznam.cz>2023-01-14 23:08:37 +0100
commit10cb2e8956b47343666550dda55996cd7cfa6fbd (patch)
treea1e62884951329aad5fc76a7ae4f1a1953378102 /src
parent9ac0b00342c559cc4ad50061176ce2fd10482caa (diff)
Storage: call watcher callbacks without holding lock
Diffstat (limited to 'src')
-rw-r--r--src/storage.cpp26
1 files changed, 19 insertions, 7 deletions
diff --git a/src/storage.cpp b/src/storage.cpp
index 9b49e96..2e948b0 100644
--- a/src/storage.cpp
+++ b/src/storage.cpp
@@ -367,15 +367,27 @@ void FilesystemStorage::inotifyWatch()
event = (const struct inotify_event *) ptr;
if (event->mask & IN_MOVED_TO) {
- scoped_lock lock(watcherLock);
- UUID type = watchMap[event->wd];
- if (auto mbid = UUID::fromString(event->name)) {
- if (auto mbref = headRef(type, *mbid)) {
- auto range = watchers.equal_range(type);
- for (auto it = range.first; it != range.second; it++)
- std::get<1>(it->second)(*mbid, *mbref);
+ vector<function<void(UUID id, const Digest &)>> callbacks;
+ optional<UUID> mbid;
+ optional<Digest> mbref;
+
+ {
+ // Copy relevant callbacks to temporary array, so they
+ // can be called without holding the watcherLock.
+
+ scoped_lock lock(watcherLock);
+ UUID type = watchMap[event->wd];
+ if ((mbid = UUID::fromString(event->name))) {
+ if ((mbref = headRef(type, *mbid))) {
+ auto range = watchers.equal_range(type);
+ for (auto it = range.first; it != range.second; it++)
+ callbacks.push_back(std::get<1>(it->second));
+ }
}
}
+
+ for (const auto & cb : callbacks)
+ cb(*mbid, *mbref);
}
}
}