xref: /glogg/src/inotifywatchtowerdriver.h (revision 6e2e573c451ec24d720c967fab68538eaa3f3ab5)
1 #ifndef INOTIFYWATCHTOWERDRIVER_H
2 #define INOTIFYWATCHTOWERDRIVER_H
3 
4 #include <memory>
5 #include <mutex>
6 #include <vector>
7 
8 template <typename Driver>
9 class ObservedFile;
10 template <typename Driver>
11 class ObservedFileList;
12 
13 class INotifyWatchTowerDriver {
14   public:
15     class FileId {
16       public:
17         friend class INotifyWatchTowerDriver;
18 
19         FileId() { wd_ = -1; }
20         bool operator==( const FileId& other ) const
21         { return wd_ == other.wd_; }
22       private:
23         FileId( int wd ) { wd_ = wd; }
24         int wd_;
25     };
26     class DirId {
27       public:
28         friend class INotifyWatchTowerDriver;
29 
30         DirId() { wd_ = -1; }
31         bool operator==( const DirId& other ) const
32         { return wd_ == other.wd_; }
33         bool valid() const
34         { return (wd_ != -1); }
35       private:
36         DirId( int wd ) { wd_ = wd; }
37         int wd_;
38     };
39     class SymlinkId {
40       public:
41         friend class INotifyWatchTowerDriver;
42 
43         SymlinkId() { wd_ = -1; }
44         bool operator==( const SymlinkId& other ) const
45         { return wd_ == other.wd_; }
46       private:
47         SymlinkId( int wd ) { wd_ = wd; }
48         int wd_;
49     };
50 
51 #ifdef HAS_TEMPLATE_ALIASES
52     using INotifyObservedFile = ObservedFile<INotifyWatchTowerDriver>;
53     using INotifyObservedFileList = ObservedFileList<INotifyWatchTowerDriver>;
54 #else
55     typedef ObservedFile<INotifyWatchTowerDriver> INotifyObservedFile;
56     typedef ObservedFileList<INotifyWatchTowerDriver> INotifyObservedFileList;
57 #endif
58 
59     // Default constructor
60     INotifyWatchTowerDriver();
61     ~INotifyWatchTowerDriver();
62 
63     // No copy/assign/move please
64     INotifyWatchTowerDriver( const INotifyWatchTowerDriver& ) = delete;
65     INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver& ) = delete;
66     INotifyWatchTowerDriver( const INotifyWatchTowerDriver&& ) = delete;
67     INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver&& ) = delete;
68 
69     FileId addFile( const std::string& file_name );
70     SymlinkId addSymlink( const std::string& file_name );
71     DirId addDir( const std::string& file_name );
72 
73     void removeFile( const FileId& file_id );
74     void removeSymlink( const SymlinkId& symlink_id );
75     void removeDir( const DirId& dir_id );
76 
77     // Wait for an event for the OS, treat it and
78     // return a list of files to notify about.
79     // This must be called with the lock on the list held,
80     // the function will unlock it temporary whilst blocking.
81     // Also returns a list of file that need readding
82     // (because of renames/symlink...)
83     std::vector<INotifyObservedFile*> waitAndProcessEvents(
84             INotifyObservedFileList* list,
85             std::unique_lock<std::mutex>* list_mutex,
86             std::vector<INotifyObservedFile*>* files_needing_readding );
87 
88     // Interrupt waitAndProcessEvents if it is blocking.
89     void interruptWait();
90 
91   private:
92     // Only written at initialisation so no protection needed.
93     const int inotify_fd_;
94 
95     // Breaking pipe
96     int breaking_pipe_read_fd_;
97     int breaking_pipe_write_fd_;
98 
99     // Private member functions
100     size_t processINotifyEvent( const struct inotify_event* event,
101             INotifyObservedFileList* list,
102             std::vector<INotifyObservedFile*>* files_to_notify,
103             std::vector<INotifyObservedFile*>* files_needing_readding );
104 };
105 
106 #endif
107