diff options
Diffstat (limited to 'dep/efsw/src/efsw/FileWatcherWin32.cpp')
-rw-r--r-- | dep/efsw/src/efsw/FileWatcherWin32.cpp | 182 |
1 files changed, 102 insertions, 80 deletions
diff --git a/dep/efsw/src/efsw/FileWatcherWin32.cpp b/dep/efsw/src/efsw/FileWatcherWin32.cpp index fe78dd122cf..317506fb3e3 100644 --- a/dep/efsw/src/efsw/FileWatcherWin32.cpp +++ b/dep/efsw/src/efsw/FileWatcherWin32.cpp @@ -2,6 +2,7 @@ #include <efsw/FileSystem.hpp> #include <efsw/System.hpp> #include <efsw/String.hpp> +#include <efsw/Lock.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 @@ -18,23 +19,9 @@ FileWatcherWin32::FileWatcherWin32( FileWatcher * parent ) : FileWatcherWin32::~FileWatcherWin32() { - WatchVector::iterator iter = mWatches.begin(); - - mWatchesLock.lock(); - - for(; iter != mWatches.end(); ++iter) - { - DestroyWatch((*iter)); - } - - mHandles.clear(); - mWatches.clear(); - mInitOK = false; - - mWatchesLock.unlock(); - efSAFE_DELETE( mThread ); + removeAllWatches(); } WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) @@ -54,9 +41,14 @@ WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListen FileSystem::dirAddSlashAtEnd( dir ); - WatchID watchid = ++mLastWatchID; + Lock lock( mWatchesLock ); + + if ( pathInWatches( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, dir ); + } - mWatchesLock.lock(); + WatchID watchid = ++mLastWatchID; WatcherStructWin32 * watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(), recursive, FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE | @@ -70,11 +62,6 @@ WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListen return Errors::Log::createLastError( Errors::FileNotFound, dir ); } - if ( pathInWatches( dir ) ) - { - return Errors::Log::createLastError( Errors::FileRepeated, dir ); - } - // Add the handle to the handles vector watch->Watch->ID = watchid; watch->Watch->Watch = this; @@ -82,67 +69,81 @@ WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListen watch->Watch->DirName = new char[dir.length()+1]; strcpy(watch->Watch->DirName, dir.c_str()); - mHandles.push_back( watch->Watch->DirHandle ); - mWatches.push_back( watch ); - mWatchesLock.unlock(); + mWatchesNew.insert( watch ); + mWatches.insert( watch ); return watchid; } void FileWatcherWin32::removeWatch(const std::string& directory) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); - WatchVector::iterator iter = mWatches.begin(); + Watches::iterator iter = mWatches.begin(); for(; iter != mWatches.end(); ++iter) { if(directory == (*iter)->Watch->DirName) { - removeWatch((*iter)->Watch->ID); - return; + removeWatch(*iter); + break; } } - - mWatchesLock.unlock(); } void FileWatcherWin32::removeWatch(WatchID watchid) { - mWatchesLock.lock(); - - WatchVector::iterator iter = mWatches.begin(); + Lock lock( mWatchesLock ); - WatcherStructWin32* watch = NULL; + Watches::iterator iter = mWatches.begin(); for(; iter != mWatches.end(); ++iter) { // Find the watch ID if ( (*iter)->Watch->ID == watchid ) { - watch = (*iter); + removeWatch(*iter); + return; + } + } +} - mWatches.erase( iter ); +void FileWatcherWin32::removeWatch(WatcherStructWin32* watch) +{ + mWatchesRemoved.insert(watch); - // Remove handle from the handle vector - HandleVector::iterator it = mHandles.begin(); + if( NULL == mThread ) + { + removeWatches(); + } +} - for ( ; it != mHandles.end(); it++ ) - { - if ( watch->Watch->DirHandle == (*it) ) - { - mHandles.erase( it ); - break; - } - } +void FileWatcherWin32::removeWatches() +{ + Lock lock( mWatchesLock ); - DestroyWatch(watch); + Watches::iterator remWatchIter = mWatchesRemoved.begin(); - break; + for( ; remWatchIter != mWatchesRemoved.end(); ++remWatchIter ) + { + Watches::iterator iter = mWatches.find(*remWatchIter); + + if( iter != mWatches.end() ) + { + DestroyWatch(*iter); + + mWatches.erase( iter ); + } + + iter = mWatchesNew.find(*remWatchIter); + + if( iter != mWatchesNew.end() ) + { + mWatchesNew.erase( iter ); } } - mWatchesLock.unlock(); + mWatchesRemoved.clear(); } void FileWatcherWin32::watch() @@ -154,45 +155,47 @@ void FileWatcherWin32::watch() } } -void FileWatcherWin32::run() +void FileWatcherWin32::removeAllWatches() { - if ( mHandles.empty() ) + Lock lock( mWatchesLock ); + + Watches::iterator iter = mWatches.begin(); + + for( ; iter != mWatches.end(); ++iter ) { - return; + DestroyWatch((*iter)); } + mWatches.clear(); + mWatchesRemoved.clear(); + mWatchesNew.clear(); +} + +void FileWatcherWin32::run() +{ do { - if ( !mHandles.empty() ) + if ( !mWatches.empty() ) { - mWatchesLock.lock(); - - for ( std::size_t i = 0; i < mWatches.size(); i++ ) { - WatcherStructWin32 * watch = mWatches[ i ]; - - // If the overlapped struct was cancelled ( because the creator thread doesn't exists anymore ), - // we recreate the overlapped in the current thread and refresh the watch - if ( /*STATUS_CANCELED*/0xC0000120 == watch->Overlapped.Internal ) - { - watch->Overlapped = OVERLAPPED(); - RefreshWatch(watch); - } + Lock lock( mWatchesLock ); - // First ensure that the handle is the same, this means that the watch was not removed. - if ( HasOverlappedIoCompleted( &watch->Overlapped ) && mHandles[ i ] == watch->Watch->DirHandle ) + for( Watches::iterator iter = mWatches.begin() ; iter != mWatches.end(); ++iter ) { - DWORD bytes; + WatcherStructWin32 * watch = *iter; - if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) ) + if ( HasOverlappedIoCompleted( &watch->Overlapped ) ) { - WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped ); + DWORD bytes; + + if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) ) + { + WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped ); + } } } } - mWatchesLock.unlock(); - if ( mInitOK ) { System::sleep( 10 ); @@ -203,7 +206,18 @@ void FileWatcherWin32::run() // Wait for a new handle to be added System::sleep( 10 ); } + + removeWatches(); + + for ( Watches::iterator it = mWatchesNew.begin(); it != mWatchesNew.end(); ++it ) + { + RefreshWatch(*it); + } + + mWatchesNew.clear(); } while ( mInitOK ); + + removeAllWatches(); } void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename) @@ -232,7 +246,7 @@ void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, FileSystem::dirAddSlashAtEnd( opath ); FileSystem::dirAddSlashAtEnd( fpath ); - for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( (*it)->Watch->Directory == opath ) { @@ -254,28 +268,36 @@ void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, break; }; - watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction); + std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); + std::string realFilename = filename; + std::size_t sepPos = filename.find_last_of("/\\"); + + if ( sepPos != std::string::npos ) + { + folderPath += filename.substr( 0, sepPos ); + realFilename = filename.substr( sepPos + 1 ); + } + + watch->Listener->handleFileAction(watch->ID, folderPath, realFilename, fwAction); } std::list<std::string> FileWatcherWin32::directories() { std::list<std::string> dirs; - mWatchesLock.lock(); + Lock lock( mWatchesLock ); - for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { dirs.push_back( std::string( (*it)->Watch->DirName ) ); } - mWatchesLock.unlock(); - return dirs; } bool FileWatcherWin32::pathInWatches( const std::string& path ) { - for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( (*it)->Watch->DirName == path ) { |