From cfca06d7963fa0909f90483b42a6d7d194d01e08 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 26 Jul 2020 19:36:28 +0000 Subject: Vendor import of llvm-project master 2e10b7a39b9, the last commit before the llvmorg-12-init tag, from which release/11.x was branched. --- .../DirectoryWatcher/mac/DirectoryWatcher-mac.cpp | 53 +++++++++++++++------- 1 file changed, 37 insertions(+), 16 deletions(-) (limited to 'clang/lib/DirectoryWatcher/mac') diff --git a/clang/lib/DirectoryWatcher/mac/DirectoryWatcher-mac.cpp b/clang/lib/DirectoryWatcher/mac/DirectoryWatcher-mac.cpp index 7a60369a4da0a..bdc3895162898 100644 --- a/clang/lib/DirectoryWatcher/mac/DirectoryWatcher-mac.cpp +++ b/clang/lib/DirectoryWatcher/mac/DirectoryWatcher-mac.cpp @@ -14,10 +14,13 @@ #include "llvm/Support/Error.h" #include "llvm/Support/Path.h" #include +#include using namespace llvm; using namespace clang; +#if TARGET_OS_OSX + static void stopFSEventStream(FSEventStreamRef); namespace { @@ -43,24 +46,32 @@ namespace { class DirectoryWatcherMac : public clang::DirectoryWatcher { public: DirectoryWatcherMac( - FSEventStreamRef EventStream, + dispatch_queue_t Queue, FSEventStreamRef EventStream, std::function, bool)> Receiver, llvm::StringRef WatchedDirPath) - : EventStream(EventStream), Receiver(Receiver), + : Queue(Queue), EventStream(EventStream), Receiver(Receiver), WatchedDirPath(WatchedDirPath) {} ~DirectoryWatcherMac() override { - stopFSEventStream(EventStream); - EventStream = nullptr; - // Now it's safe to use Receiver as the only other concurrent use would have - // been in EventStream processing. - Receiver(DirectoryWatcher::Event( - DirectoryWatcher::Event::EventKind::WatcherGotInvalidated, ""), - false); + // FSEventStreamStop and Invalidate must be called after Start and + // SetDispatchQueue to follow FSEvents API contract. The call to Receiver + // also uses Queue to not race with the initial scan. + dispatch_sync(Queue, ^{ + stopFSEventStream(EventStream); + EventStream = nullptr; + Receiver( + DirectoryWatcher::Event( + DirectoryWatcher::Event::EventKind::WatcherGotInvalidated, ""), + false); + }); + + // Balance initial creation. + dispatch_release(Queue); } private: + dispatch_queue_t Queue; FSEventStreamRef EventStream; std::function, bool)> Receiver; const std::string WatchedDirPath; @@ -173,7 +184,7 @@ FSEventStreamRef createFSEventStream( if (::realpath(P.begin(), Buffer) != nullptr) RealPath = Buffer; else - RealPath = Path; + RealPath = Path.str(); } FSEventStreamContext Context; @@ -217,11 +228,11 @@ llvm::Expected> clang::DirectoryWatcher::creat assert(EventStream && "EventStream expected to be non-null"); std::unique_ptr Result = - std::make_unique(EventStream, Receiver, Path); + std::make_unique(Queue, EventStream, Receiver, Path); // We need to copy the data so the lifetime is ok after a const copy is made // for the block. - const std::string CopiedPath = Path; + const std::string CopiedPath = Path.str(); auto InitWork = ^{ // We need to start watching the directory before we start scanning in order @@ -230,10 +241,6 @@ llvm::Expected> clang::DirectoryWatcher::creat // inital scan and handling events ONLY AFTER the scan finishes. FSEventStreamSetDispatchQueue(EventStream, Queue); FSEventStreamStart(EventStream); - // We need to decrement the ref count for Queue as initialize() will return - // and FSEvents has incremented it. Since we have to wait for FSEvents to - // take ownership it's the easiest to do it here rather than main thread. - dispatch_release(Queue); Receiver(getAsFileEvents(scanDirectory(CopiedPath)), /*IsInitial=*/true); }; @@ -245,3 +252,17 @@ llvm::Expected> clang::DirectoryWatcher::creat return Result; } + +#else // TARGET_OS_OSX + +llvm::Expected> +clang::DirectoryWatcher::create( + StringRef Path, + std::function, bool)> Receiver, + bool WaitForInitialSync) { + return llvm::make_error( + "DirectoryWatcher is not implemented for this platform!", + llvm::inconvertibleErrorCode()); +} + +#endif // TARGET_OS_OSX -- cgit v1.2.3