1 /* Copyright 2012-present Facebook, Inc. 2 * Licensed under the Apache License, Version 2.0 */ 3 #pragma once 4 #include <chrono> 5 #include <condition_variable> 6 #include "thirdparty/libart/src/art.h" 7 #include "watchman_synchronized.h" 8 9 #define W_PENDING_RECURSIVE 1 10 #define W_PENDING_VIA_NOTIFY 2 11 #define W_PENDING_CRAWL_ONLY 4 12 13 struct watchman_pending_fs { 14 // We own the next entry and will destroy that chain when we 15 // are destroyed. 16 std::shared_ptr<watchman_pending_fs> next; 17 std::weak_ptr<watchman_pending_fs> prev; 18 w_string path; 19 struct timeval now; 20 int flags; 21 22 watchman_pending_fs( 23 const w_string& path, 24 const struct timeval& now, 25 int flags); 26 }; 27 28 struct PendingCollectionBase { 29 PendingCollectionBase( 30 std::condition_variable& cond, 31 std::atomic<bool>& pinged); 32 PendingCollectionBase(const PendingCollectionBase&) = delete; 33 PendingCollectionBase(PendingCollectionBase&&) = default; 34 ~PendingCollectionBase(); 35 36 void drain(); 37 bool add(const w_string& path, struct timeval now, int flags); 38 bool add( 39 struct watchman_dir* dir, 40 const char* name, 41 struct timeval now, 42 int flags); 43 void append(PendingCollectionBase* src); 44 45 /* Moves the head of the chain of items to the caller. 46 * The tree is cleared and the caller owns the whole chain */ 47 std::shared_ptr<watchman_pending_fs> stealItems(); 48 49 uint32_t size() const; 50 void ping(); 51 bool checkAndResetPinged(); 52 53 private: 54 std::condition_variable& cond_; 55 std::atomic<bool>& pinged_; 56 art_tree<std::shared_ptr<watchman_pending_fs>, w_string> tree_; 57 std::shared_ptr<watchman_pending_fs> pending_; 58 59 struct iterContext { 60 const w_string& root; 61 PendingCollectionBase& coll; 62 63 int operator()( 64 const w_string& key, 65 std::shared_ptr<watchman_pending_fs>& p); 66 67 iterContext(const w_string& root, PendingCollectionBase& coll); 68 }; 69 friend struct iterContext; 70 71 void maybePruneObsoletedChildren(w_string path, int flags); 72 inline void consolidateItem(watchman_pending_fs* p, int flags); 73 bool isObsoletedByContainingDir(const w_string& path); 74 inline void linkHead(std::shared_ptr<watchman_pending_fs>&& p); 75 inline void unlinkItem(std::shared_ptr<watchman_pending_fs>& p); 76 }; 77 78 class PendingCollection 79 : public watchman::Synchronized<PendingCollectionBase, std::mutex> { 80 std::condition_variable cond_; 81 std::atomic<bool> pinged_; 82 83 public: 84 PendingCollection(); 85 LockedPtr lockAndWait(std::chrono::milliseconds timeoutms, bool& pinged); 86 87 // Ping without requiring the lock to be held 88 void ping(); 89 }; 90