aboutsummaryrefslogtreecommitdiff
path: root/src/3rdParty/efsw/FileWatcherFSEvents.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdParty/efsw/FileWatcherFSEvents.cpp')
-rw-r--r--[-rwxr-xr-x]src/3rdParty/efsw/FileWatcherFSEvents.cpp114
1 files changed, 61 insertions, 53 deletions
diff --git a/src/3rdParty/efsw/FileWatcherFSEvents.cpp b/src/3rdParty/efsw/FileWatcherFSEvents.cpp
index bcfdbe6..70ec2b1 100755..100644
--- a/src/3rdParty/efsw/FileWatcherFSEvents.cpp
+++ b/src/3rdParty/efsw/FileWatcherFSEvents.cpp
@@ -41,6 +41,32 @@ bool FileWatcherFSEvents::isGranular() {
41 return getOSXReleaseNumber() >= 11; 41 return getOSXReleaseNumber() >= 11;
42} 42}
43 43
44static std::string convertCFStringToStdString( CFStringRef cfString ) {
45 // Try to get the C string pointer directly
46 const char* cStr = CFStringGetCStringPtr( cfString, kCFStringEncodingUTF8 );
47
48 if ( cStr ) {
49 // If the pointer is valid, directly return a std::string from it
50 return std::string( cStr );
51 } else {
52 // If not, manually convert it
53 CFIndex length = CFStringGetLength( cfString );
54 CFIndex maxSize = CFStringGetMaximumSizeForEncoding( length, kCFStringEncodingUTF8 ) +
55 1; // +1 for null terminator
56
57 char* buffer = new char[maxSize];
58
59 if ( CFStringGetCString( cfString, buffer, maxSize, kCFStringEncodingUTF8 ) ) {
60 std::string result( buffer );
61 delete[] buffer;
62 return result;
63 } else {
64 delete[] buffer;
65 return "";
66 }
67 }
68}
69
44void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef /*streamRef*/, void* userData, 70void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef /*streamRef*/, void* userData,
45 size_t numEvents, void* eventPaths, 71 size_t numEvents, void* eventPaths,
46 const FSEventStreamEventFlags eventFlags[], 72 const FSEventStreamEventFlags eventFlags[],
@@ -51,8 +77,24 @@ void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef /*streamRef*/,
51 events.reserve( numEvents ); 77 events.reserve( numEvents );
52 78
53 for ( size_t i = 0; i < numEvents; i++ ) { 79 for ( size_t i = 0; i < numEvents; i++ ) {
54 events.push_back( FSEvent( std::string( ( (char**)eventPaths )[i] ), (long)eventFlags[i], 80 if ( isGranular() ) {
55 (Uint64)eventIds[i] ) ); 81 CFDictionaryRef pathInfoDict =
82 static_cast<CFDictionaryRef>( CFArrayGetValueAtIndex( (CFArrayRef)eventPaths, i ) );
83 CFStringRef path = static_cast<CFStringRef>(
84 CFDictionaryGetValue( pathInfoDict, kFSEventStreamEventExtendedDataPathKey ) );
85 CFNumberRef cfInode = static_cast<CFNumberRef>(
86 CFDictionaryGetValue( pathInfoDict, kFSEventStreamEventExtendedFileIDKey ) );
87
88 if ( cfInode ) {
89 unsigned long inode = 0;
90 CFNumberGetValue( cfInode, kCFNumberLongType, &inode );
91 events.push_back( FSEvent( convertCFStringToStdString( path ), (long)eventFlags[i],
92 (Uint64)eventIds[i], inode ) );
93 }
94 } else {
95 events.push_back( FSEvent( std::string( ( (char**)eventPaths )[i] ),
96 (long)eventFlags[i], (Uint64)eventIds[i] ) );
97 }
56 } 98 }
57 99
58 watcher->handleActions( events ); 100 watcher->handleActions( events );
@@ -63,7 +105,7 @@ void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef /*streamRef*/,
63} 105}
64 106
65FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher* parent ) : 107FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher* parent ) :
66 FileWatcherImpl( parent ), mRunLoopRef( NULL ), mLastWatchID( 0 ), mThread( NULL ) { 108 FileWatcherImpl( parent ), mLastWatchID( 0 ) {
67 mInitOK = true; 109 mInitOK = true;
68 110
69 watch(); 111 watch();
@@ -72,10 +114,7 @@ FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher* parent ) :
72FileWatcherFSEvents::~FileWatcherFSEvents() { 114FileWatcherFSEvents::~FileWatcherFSEvents() {
73 mInitOK = false; 115 mInitOK = false;
74 116
75 if ( mRunLoopRef.load() ) 117 mWatchCond.notify_all();
76 CFRunLoopStop( mRunLoopRef.load() );
77
78 efSAFE_DELETE( mThread );
79 118
80 WatchMap::iterator iter = mWatches.begin(); 119 WatchMap::iterator iter = mWatches.begin();
81 120
@@ -84,18 +123,11 @@ FileWatcherFSEvents::~FileWatcherFSEvents() {
84 123
85 efSAFE_DELETE( watch ); 124 efSAFE_DELETE( watch );
86 } 125 }
87
88 mWatches.clear();
89} 126}
90 127
91WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher, 128WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher,
92 bool recursive ) { 129 bool recursive, const std::vector<WatcherOption>& options ) {
93 /// Wait to the RunLoopRef to be ready 130 std::string dir( FileSystem::getRealPath( directory ) );
94 while ( NULL == mRunLoopRef.load() ) {
95 System::sleep( 1 );
96 }
97
98 std::string dir( directory );
99 131
100 FileInfo fi( dir ); 132 FileInfo fi( dir );
101 133
@@ -135,12 +167,18 @@ WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchLi
135 pWatch->Directory = dir; 167 pWatch->Directory = dir;
136 pWatch->Recursive = recursive; 168 pWatch->Recursive = recursive;
137 pWatch->FWatcher = this; 169 pWatch->FWatcher = this;
170 pWatch->ModifiedFlags =
171 getOptionValue( options, Option::MacModifiedFilter, efswFSEventsModified );
172 pWatch->SanitizeEvents = getOptionValue( options, Option::MacSanitizeEvents, 0 ) != 0;
138 173
139 pWatch->init(); 174 pWatch->init();
140 175
141 Lock lock( mWatchesLock ); 176 {
142 mWatches.insert( std::make_pair( mLastWatchID, pWatch ) ); 177 Lock lock( mWatchesLock );
178 mWatches.insert( std::make_pair( mLastWatchID, pWatch ) );
179 }
143 180
181 mWatchCond.notify_all();
144 return pWatch->ID; 182 return pWatch->ID;
145} 183}
146 184
@@ -174,50 +212,20 @@ void FileWatcherFSEvents::removeWatch( WatchID watchid ) {
174 efSAFE_DELETE( watch ); 212 efSAFE_DELETE( watch );
175} 213}
176 214
177void FileWatcherFSEvents::watch() { 215void FileWatcherFSEvents::watch() {}
178 if ( NULL == mThread ) {
179 mThread = new Thread( &FileWatcherFSEvents::run, this );
180 mThread->launch();
181 }
182}
183
184void FileWatcherFSEvents::run() {
185 mRunLoopRef = CFRunLoopGetCurrent();
186
187 while ( mInitOK ) {
188 mNeedInitMutex.lock();
189
190 if ( !mNeedInit.empty() ) {
191 for ( std::vector<WatcherFSEvents*>::iterator it = mNeedInit.begin();
192 it != mNeedInit.end(); ++it ) {
193 ( *it )->initAsync();
194 }
195
196 mNeedInit.clear();
197 }
198
199 mNeedInitMutex.unlock();
200
201 if ( mWatches.empty() ) {
202 System::sleep( 100 );
203 } else {
204 CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.5, kCFRunLoopRunTimedOut );
205 }
206 }
207
208 mRunLoopRef = NULL;
209}
210 216
211void FileWatcherFSEvents::handleAction( Watcher* /*watch*/, const std::string& /*filename*/, 217void FileWatcherFSEvents::handleAction( Watcher* /*watch*/, const std::string& /*filename*/,
212 unsigned long /*action*/, std::string /*oldFilename*/ ) { 218 unsigned long /*action*/, std::string /*oldFilename*/ ) {
213 /// Not used 219 /// Not used
214} 220}
215 221
216std::list<std::string> FileWatcherFSEvents::directories() { 222std::vector<std::string> FileWatcherFSEvents::directories() {
217 std::list<std::string> dirs; 223 std::vector<std::string> dirs;
218 224
219 Lock lock( mWatchesLock ); 225 Lock lock( mWatchesLock );
220 226
227 dirs.reserve( mWatches.size() );
228
221 for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { 229 for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) {
222 dirs.push_back( std::string( it->second->Directory ) ); 230 dirs.push_back( std::string( it->second->Directory ) );
223 } 231 }