aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-10-11 14:31:13 +0200
committerShauren <shauren.trinity@gmail.com>2025-10-11 14:31:13 +0200
commit8fcec269170f209f79590b3a22f2c85f551cf17b (patch)
tree7ddc8d65759a34ec4f56dc72704fe8901ded01af
parent35c1d2e98917c4eb2504301cf13e5f2ef50dc725 (diff)
Dep/efsw: Update to SpartanJ/efsw@f94a6616aba85fc9375fdff7ee69609d223a0672
-rw-r--r--dep/PackageList.txt2
-rw-r--r--dep/efsw/CMakeLists.txt14
-rw-r--r--dep/efsw/include/efsw/efsw.h157
-rw-r--r--dep/efsw/include/efsw/efsw.hpp37
-rw-r--r--dep/efsw/src/efsw/Debug.hpp6
-rw-r--r--dep/efsw/src/efsw/FileSystem.cpp25
-rw-r--r--dep/efsw/src/efsw/FileSystem.hpp4
-rw-r--r--dep/efsw/src/efsw/FileWatcherCWrapper.cpp36
-rw-r--r--dep/efsw/src/efsw/FileWatcherFSEvents.cpp59
-rw-r--r--dep/efsw/src/efsw/FileWatcherFSEvents.hpp21
-rw-r--r--dep/efsw/src/efsw/FileWatcherGeneric.cpp2
-rw-r--r--dep/efsw/src/efsw/FileWatcherInotify.cpp97
-rw-r--r--dep/efsw/src/efsw/FileWatcherInotify.hpp3
-rw-r--r--dep/efsw/src/efsw/FileWatcherKqueue.cpp2
-rw-r--r--dep/efsw/src/efsw/FileWatcherWin32.cpp8
-rw-r--r--dep/efsw/src/efsw/FileWatcherWin32.hpp4
-rw-r--r--dep/efsw/src/efsw/Lock.hpp14
-rw-r--r--dep/efsw/src/efsw/Mutex.cpp20
-rw-r--r--dep/efsw/src/efsw/Mutex.hpp25
-rw-r--r--dep/efsw/src/efsw/String.hpp3
-rw-r--r--dep/efsw/src/efsw/Thread.cpp41
-rw-r--r--dep/efsw/src/efsw/Thread.hpp107
-rw-r--r--dep/efsw/src/efsw/WatcherFSEvents.cpp75
-rw-r--r--dep/efsw/src/efsw/WatcherFSEvents.hpp45
-rw-r--r--dep/efsw/src/efsw/WatcherInotify.hpp1
-rw-r--r--dep/efsw/src/efsw/WatcherKqueue.cpp3
-rw-r--r--dep/efsw/src/efsw/WatcherWin32.cpp190
-rw-r--r--dep/efsw/src/efsw/WatcherWin32.hpp7
-rw-r--r--dep/efsw/src/efsw/platform/platformimpl.hpp4
-rw-r--r--dep/efsw/src/efsw/platform/posix/MutexImpl.cpp28
-rw-r--r--dep/efsw/src/efsw/platform/posix/MutexImpl.hpp30
-rw-r--r--dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp62
-rw-r--r--dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp39
-rw-r--r--dep/efsw/src/efsw/platform/win/MutexImpl.cpp25
-rw-r--r--dep/efsw/src/efsw/platform/win/MutexImpl.hpp33
-rw-r--r--dep/efsw/src/efsw/platform/win/ThreadImpl.cpp56
-rw-r--r--dep/efsw/src/efsw/platform/win/ThreadImpl.hpp42
-rw-r--r--dep/efsw/src/test/efsw-test.c48
-rw-r--r--dep/efsw/src/test/efsw-test.cpp2
39 files changed, 625 insertions, 752 deletions
diff --git a/dep/PackageList.txt b/dep/PackageList.txt
index 10625227d45..64ee91997f4 100644
--- a/dep/PackageList.txt
+++ b/dep/PackageList.txt
@@ -10,7 +10,7 @@ Boost Process (Proposed for boost, but its not an official part of it yet. Used
efsw (Entropia File System Watcher - crossplatform file system watcher)
https://github.com/SpartanJ/efsw
- Version: 1.3.1+ 36c1c7004a34b6f40719f0830bcfb10325415451
+ Version: 1.5.0+ f94a6616aba85fc9375fdff7ee69609d223a0672
fmt (a small, safe and fast formatting library)
https://github.com/fmtlib/fmt
diff --git a/dep/efsw/CMakeLists.txt b/dep/efsw/CMakeLists.txt
index 9817525931c..555f1b303a0 100644
--- a/dep/efsw/CMakeLists.txt
+++ b/dep/efsw/CMakeLists.txt
@@ -22,14 +22,12 @@ if (BUILD_SHARED_LIBS)
src/efsw/FileWatcherImpl.hpp
src/efsw/Lock.hpp
src/efsw/Log.cpp
- src/efsw/Mutex.cpp
src/efsw/Mutex.hpp
src/efsw/sophist.h
src/efsw/String.cpp
src/efsw/String.hpp
src/efsw/System.cpp
src/efsw/System.hpp
- src/efsw/Thread.cpp
src/efsw/Thread.hpp
src/efsw/Utf.hpp
src/efsw/Watcher.cpp
@@ -43,22 +41,14 @@ if (BUILD_SHARED_LIBS)
list (APPEND EFSW_CPP_SOURCE
src/efsw/platform/win/FileSystemImpl.cpp
src/efsw/platform/win/FileSystemImpl.hpp
- src/efsw/platform/win/MutexImpl.cpp
- src/efsw/platform/win/MutexImpl.hpp
src/efsw/platform/win/SystemImpl.cpp
- src/efsw/platform/win/SystemImpl.hpp
- src/efsw/platform/win/ThreadImpl.cpp
- src/efsw/platform/win/ThreadImpl.hpp)
+ src/efsw/platform/win/SystemImpl.hpp)
else ()
list (APPEND EFSW_CPP_SOURCE
src/efsw/platform/posix/FileSystemImpl.cpp
src/efsw/platform/posix/FileSystemImpl.hpp
- src/efsw/platform/posix/MutexImpl.cpp
- src/efsw/platform/posix/MutexImpl.hpp
src/efsw/platform/posix/SystemImpl.cpp
- src/efsw/platform/posix/SystemImpl.hpp
- src/efsw/platform/posix/ThreadImpl.cpp
- src/efsw/platform/posix/ThreadImpl.hpp)
+ src/efsw/platform/posix/SystemImpl.hpp)
endif()
if (APPLE)
diff --git a/dep/efsw/include/efsw/efsw.h b/dep/efsw/include/efsw/efsw.h
index ecb9ec41c26..56f24d03452 100644
--- a/dep/efsw/include/efsw/efsw.h
+++ b/dep/efsw/include/efsw/efsw.h
@@ -1,7 +1,7 @@
/**
@author Sepul Sepehr Taghdisian
- Copyright (c) 2013 Martin Lucas Golini
+ Copyright (c) 2024 Martín Lucas Golini
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -32,31 +32,31 @@
extern "C" {
#endif
-#if defined(_WIN32)
- #ifdef EFSW_DYNAMIC
- // Windows platforms
- #ifdef EFSW_EXPORTS
- // From DLL side, we must export
- #define EFSW_API __declspec(dllexport)
- #else
- // From client application side, we must import
- #define EFSW_API __declspec(dllimport)
- #endif
- #else
- // No specific directive needed for static build
- #ifndef EFSW_API
- #define EFSW_API
- #endif
- #endif
+#if defined( _WIN32 )
+#ifdef EFSW_DYNAMIC
+// Windows platforms
+#ifdef EFSW_EXPORTS
+// From DLL side, we must export
+#define EFSW_API __declspec( dllexport )
#else
- #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS )
- #define EFSW_API __attribute__ ((visibility("default")))
- #endif
-
- // Other platforms don't need to define anything
- #ifndef EFSW_API
- #define EFSW_API
- #endif
+// From client application side, we must import
+#define EFSW_API __declspec( dllimport )
+#endif
+#else
+// No specific directive needed for static build
+#ifndef EFSW_API
+#define EFSW_API
+#endif
+#endif
+#else
+#if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS )
+#define EFSW_API __attribute__( ( visibility( "default" ) ) )
+#endif
+
+// Other platforms don't need to define anything
+#ifndef EFSW_API
+#define EFSW_API
+#endif
#endif
/// Type for a watch id
@@ -65,27 +65,24 @@ typedef long efsw_watchid;
/// Type for watcher
typedef void* efsw_watcher;
-enum efsw_action
-{
- EFSW_ADD = 1, /// Sent when a file is created or renamed
- EFSW_DELETE = 2, /// Sent when a file is deleted or renamed
- EFSW_MODIFIED = 3, /// Sent when a file is modified
- EFSW_MOVED = 4 /// Sent when a file is moved
+enum efsw_action {
+ EFSW_ADD = 1, /// Sent when a file is created or renamed
+ EFSW_DELETE = 2, /// Sent when a file is deleted or renamed
+ EFSW_MODIFIED = 3, /// Sent when a file is modified
+ EFSW_MOVED = 4 /// Sent when a file is moved
};
-enum efsw_error
-{
- EFSW_NOTFOUND = -1,
- EFSW_REPEATED = -2,
- EFSW_OUTOFSCOPE = -3,
- EFSW_NOTREADABLE = -4,
- EFSW_REMOTE = -5,
- EFSW_WATCHER_FAILED = -6,
- EFSW_UNSPECIFIED = -7
+enum efsw_error {
+ EFSW_NOTFOUND = -1,
+ EFSW_REPEATED = -2,
+ EFSW_OUTOFSCOPE = -3,
+ EFSW_NOTREADABLE = -4,
+ EFSW_REMOTE = -5,
+ EFSW_WATCHER_FAILED = -6,
+ EFSW_UNSPECIFIED = -7
};
-enum efsw_option
-{
+enum efsw_option {
/// For Windows, the default buffer size of 63*1024 bytes sometimes is not enough and
/// file system events may be dropped. For that, using a different (bigger) buffer size
/// can be defined here, but note that this does not work for network drives,
@@ -95,19 +92,37 @@ enum efsw_option
/// For Windows, per default all events are captured but we might only be interested
/// in a subset; the value of the option should be set to a bitwise or'ed set of
/// FILE_NOTIFY_CHANGE_* flags.
- EFSW_OPT_WIN_NOTIFY_FILTER = 2
+ EFSW_OPT_WIN_NOTIFY_FILTER = 2,
+ /// For macOS (FSEvents backend), per default all modified event types are capture but we might
+ // only be interested in a subset; the value of the option should be set to a set of bitwise
+ // from:
+ // kFSEventStreamEventFlagItemFinderInfoMod
+ // kFSEventStreamEventFlagItemModified
+ // kFSEventStreamEventFlagItemInodeMetaMod
+ // Default configuration will set the 3 flags
+ EFSW_OPT_MAC_MODIFIED_FILTER = 3,
+ /// macOS sometimes informs incorrect or old file states that may confuse the consumer
+ /// The events sanitizer will try to sanitize incorrectly reported events in favor of reducing
+ /// the number of events reported. This will have an small performance and memory impact as a
+ /// consequence.
+ EFSW_OPT_MAC_SANITIZE_EVENTS = 4,
+ /// Linux does not support natively recursive watchers. This means that when using recursive
+ /// watches efsw registers new watchers for each directory. If new file are created between
+ /// the time efsw takes to register the new directory those events might be missed. To avoid
+ /// missing new file notifications efsw will trigger synthetic new file events for existing
+ /// files in the new directroy watched. This might have the unintended consequence of sending
+ /// duplicated created events due to the system also emitting this event.
+ LINUX_PRODUCE_SYNTHETIC_EVENTS = 5,
};
/// Basic interface for listening for file events.
-typedef void (*efsw_pfn_fileaction_callback) (
- efsw_watcher watcher,
- efsw_watchid watchid,
- const char* dir,
- const char* filename,
- enum efsw_action action,
- const char* old_filename,
- void* param
-);
+typedef void ( *efsw_pfn_fileaction_callback )( efsw_watcher watcher, efsw_watchid watchid,
+ const char* dir, const char* filename,
+ enum efsw_action action, const char* old_filename,
+ void* param );
+
+typedef void ( *efsw_pfn_handle_missed_fileactions )( efsw_watcher watcher, efsw_watchid watchid,
+ const char* dir );
typedef struct {
enum efsw_option option;
@@ -118,10 +133,10 @@ typedef struct {
* Creates a new file-watcher
* @param generic_mode Force the use of the Generic file watcher
*/
-efsw_watcher EFSW_API efsw_create(int generic_mode);
+efsw_watcher EFSW_API efsw_create( int generic_mode );
/// Release the file-watcher and unwatch any directories
-void EFSW_API efsw_release(efsw_watcher watcher);
+void EFSW_API efsw_release( efsw_watcher watcher );
/// Retrieve last error occured by file-watcher
EFSW_API const char* efsw_getlasterror();
@@ -131,47 +146,49 @@ EFSW_API void efsw_clearlasterror();
/// Add a directory watch
/// On error returns WatchID with Error type.
-efsw_watchid EFSW_API efsw_addwatch(efsw_watcher watcher, const char* directory,
- efsw_pfn_fileaction_callback callback_fn, int recursive, void* param);
+efsw_watchid EFSW_API efsw_addwatch( efsw_watcher watcher, const char* directory,
+ efsw_pfn_fileaction_callback callback_fn, int recursive,
+ void* param );
/// Add a directory watch, specifying options
/// @param options Pointer to an array of watcher options
/// @param nr_options Number of options referenced by \p options
-efsw_watchid EFSW_API efsw_addwatch_withoptions(efsw_watcher watcher, const char* directory,
- efsw_pfn_fileaction_callback callback_fn, int recursive, efsw_watcher_option *options,
- int options_number, void* param);
+efsw_watchid EFSW_API efsw_addwatch_withoptions(
+ efsw_watcher watcher, const char* directory, efsw_pfn_fileaction_callback callback_fn,
+ int recursive, efsw_watcher_option* options, int options_number, void* param,
+ efsw_pfn_handle_missed_fileactions callback_fn_missed_file_actions );
/// Remove a directory watch. This is a brute force search O(nlogn).
-void EFSW_API efsw_removewatch(efsw_watcher watcher, const char* directory);
+void EFSW_API efsw_removewatch( efsw_watcher watcher, const char* directory );
/// Remove a directory watch. This is a map lookup O(logn).
-void EFSW_API efsw_removewatch_byid(efsw_watcher watcher, efsw_watchid watchid);
+void EFSW_API efsw_removewatch_byid( efsw_watcher watcher, efsw_watchid watchid );
/// Starts watching ( in other thread )
-void EFSW_API efsw_watch(efsw_watcher watcher);
+void EFSW_API efsw_watch( efsw_watcher watcher );
/**
* Allow recursive watchers to follow symbolic links to other directories
* followSymlinks is disabled by default
*/
-void EFSW_API efsw_follow_symlinks(efsw_watcher watcher, int enable);
+void EFSW_API efsw_follow_symlinks( efsw_watcher watcher, int enable );
/** @return If can follow symbolic links to directorioes */
-int EFSW_API efsw_follow_symlinks_isenabled(efsw_watcher watcher);
+int EFSW_API efsw_follow_symlinks_isenabled( efsw_watcher watcher );
/**
* When enable this it will allow symlinks to watch recursively out of the pointed directory.
* follorSymlinks must be enabled to this work.
- * For example, added symlink to /home/folder, and the symlink points to /, this by default is not allowed,
- * it's only allowed to symlink anything from /home/ and deeper. This is to avoid great levels of recursion.
- * Enabling this could lead in infinite recursion, and crash the watcher ( it will try not to avoid this ).
- * Buy enabling out of scope links, it will allow this behavior.
+ * For example, added symlink to /home/folder, and the symlink points to /, this by default is not
+ * allowed, it's only allowed to symlink anything from /home/ and deeper. This is to avoid great
+ * levels of recursion. Enabling this could lead in infinite recursion, and crash the watcher ( it
+ * will try not to avoid this ). Buy enabling out of scope links, it will allow this behavior.
* allowOutOfScopeLinks are disabled by default.
*/
-void EFSW_API efsw_allow_outofscopelinks(efsw_watcher watcher, int allow);
+void EFSW_API efsw_allow_outofscopelinks( efsw_watcher watcher, int allow );
/// @return Returns if out of scope links are allowed
-int EFSW_API efsw_outofscopelinks_isallowed(efsw_watcher watcher);
+int EFSW_API efsw_outofscopelinks_isallowed( efsw_watcher watcher );
#ifdef __cplusplus
}
diff --git a/dep/efsw/include/efsw/efsw.hpp b/dep/efsw/include/efsw/efsw.hpp
index cb78ef3797f..60d00296913 100644
--- a/dep/efsw/include/efsw/efsw.hpp
+++ b/dep/efsw/include/efsw/efsw.hpp
@@ -1,7 +1,7 @@
/**
@author Martín Lucas Golini
- Copyright (c) 2013 Martín Lucas Golini
+ Copyright (c) 2024 Martín Lucas Golini
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -28,7 +28,6 @@
#ifndef ESFW_HPP
#define ESFW_HPP
-#include <vector>
#include <string>
#include <vector>
@@ -135,7 +134,27 @@ enum Option {
/// For Windows, per default all events are captured but we might only be interested
/// in a subset; the value of the option should be set to a bitwise or'ed set of
/// FILE_NOTIFY_CHANGE_* flags.
- WinNotifyFilter = 2
+ WinNotifyFilter = 2,
+ /// For macOS (FSEvents backend), per default all modified event types are capture but we might
+ /// only be interested in a subset; the value of the option should be set to a set of bitwise
+ /// from:
+ /// kFSEventStreamEventFlagItemFinderInfoMod
+ /// kFSEventStreamEventFlagItemModified
+ /// kFSEventStreamEventFlagItemInodeMetaMod
+ /// Default configuration will set the 3 flags
+ MacModifiedFilter = 3,
+ /// macOS sometimes informs incorrect or old file states that may confuse the consumer
+ /// The events sanitizer will try to sanitize incorrectly reported events in favor of reducing
+ /// the number of events reported. This will have an small performance and memory impact as a
+ /// consequence.
+ MacSanitizeEvents = 4,
+ /// Linux does not support natively recursive watchers. This means that when using recursive
+ /// watches efsw registers new watchers for each directory. If new file are created between
+ /// the time efsw takes to register the new directory those events might be missed. To avoid
+ /// missing new file notifications efsw will trigger synthetic created file events for existing
+ /// files in the new directroy watched. This might have the unintended consequence of sending
+ /// duplicated created events due to the system also emitting this event.
+ LinuxProduceSyntheticEvents = 5,
};
}
typedef Options::Option Option;
@@ -168,8 +187,8 @@ class EFSW_API FileWatcher {
/// @param recursive Set this to true to include subdirectories
/// @param options Allows customization of a watcher
/// @return Returns the watch id for the directory or, on error, a WatchID with Error type.
- WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive,
- const std::vector<WatcherOption> &options );
+ WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive,
+ const std::vector<WatcherOption>& options );
/// Remove a directory watch. This is a brute force search O(nlogn).
void removeWatch( const std::string& directory );
@@ -226,13 +245,19 @@ class FileWatchListener {
virtual void handleFileAction( WatchID watchid, const std::string& dir,
const std::string& filename, Action action,
std::string oldFilename = "" ) = 0;
+
+ /// Handles that have missed file actions
+ /// @param watchid The watch id for the directory
+ /// @param dir The directory
+ virtual void handleMissedFileActions( WatchID /*watchid*/,
+ const std::string& /*dir*/ ) {}
};
/// Optional, typically platform specific parameter for customization of a watcher.
/// @class WatcherOption
class WatcherOption {
public:
- WatcherOption(Option option, int value) : mOption(option), mValue(value) {};
+ WatcherOption( Option option, int value ) : mOption( option ), mValue( value ){};
Option mOption;
int mValue;
};
diff --git a/dep/efsw/src/efsw/Debug.hpp b/dep/efsw/src/efsw/Debug.hpp
index 78d35573b62..fefaec4d7e8 100644
--- a/dep/efsw/src/efsw/Debug.hpp
+++ b/dep/efsw/src/efsw/Debug.hpp
@@ -49,8 +49,10 @@ void efPRINTC( unsigned int cond, const char* format, ... );
#define efDEBUGC( cond, format, args... ) \
{}
#else
-#define efDEBUG
-#define efDEBUGC
+#define efDEBUG( ... ) \
+ {}
+#define efDEBUGC( ... ) \
+ {}
#endif
#endif
diff --git a/dep/efsw/src/efsw/FileSystem.cpp b/dep/efsw/src/efsw/FileSystem.cpp
index b6d2d63ddce..1ed346ca17f 100644
--- a/dep/efsw/src/efsw/FileSystem.cpp
+++ b/dep/efsw/src/efsw/FileSystem.cpp
@@ -1,11 +1,19 @@
#include <cstring>
#include <efsw/FileSystem.hpp>
#include <efsw/platform/platformimpl.hpp>
+#include <climits>
#if EFSW_OS == EFSW_OS_MACOSX
#include <CoreFoundation/CoreFoundation.h>
#endif
+#if EFSW_OS == EFSW_OS_WIN
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#endif
+
namespace efsw {
bool FileSystem::isDirectory( const std::string& path ) {
@@ -133,4 +141,21 @@ std::string FileSystem::getCurrentWorkingDirectory() {
return Platform::FileSystem::getCurrentWorkingDirectory();
}
+std::string FileSystem::getRealPath( const std::string& path ) {
+ std::string realPath;
+#if defined( EFSW_PLATFORM_POSIX )
+ char dir[PATH_MAX];
+ realpath( path.c_str(), &dir[0] );
+ realPath = std::string( dir );
+#elif EFSW_OS == EFSW_OS_WIN
+ wchar_t dir[_MAX_PATH + 1];
+ GetFullPathNameW( String::fromUtf8( path ).toWideString().c_str(), _MAX_PATH, &dir[0],
+ nullptr );
+ realPath = String( dir ).toUtf8();
+#else
+#warning FileSystem::getRealPath() not implemented on this platform.
+#endif
+ return realPath;
+}
+
} // namespace efsw
diff --git a/dep/efsw/src/efsw/FileSystem.hpp b/dep/efsw/src/efsw/FileSystem.hpp
index 6c24386c585..1d66ece4972 100644
--- a/dep/efsw/src/efsw/FileSystem.hpp
+++ b/dep/efsw/src/efsw/FileSystem.hpp
@@ -3,7 +3,6 @@
#include <efsw/FileInfo.hpp>
#include <efsw/base.hpp>
-#include <map>
namespace efsw {
@@ -34,6 +33,9 @@ class FileSystem {
static bool changeWorkingDirectory( const std::string& path );
static std::string getCurrentWorkingDirectory();
+
+ static std::string getRealPath( const std::string& path );
+
};
} // namespace efsw
diff --git a/dep/efsw/src/efsw/FileWatcherCWrapper.cpp b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp
index 860d7d50c8b..258f8e04473 100644
--- a/dep/efsw/src/efsw/FileWatcherCWrapper.cpp
+++ b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp
@@ -10,10 +10,12 @@ class Watcher_CAPI : public efsw::FileWatchListener {
efsw_watcher mWatcher;
efsw_pfn_fileaction_callback mFn;
void* mParam;
+ efsw_pfn_handle_missed_fileactions mFnMissedFa;
public:
- Watcher_CAPI( efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param ) :
- mWatcher( watcher ), mFn( fn ), mParam( param ) {}
+ Watcher_CAPI( efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param,
+ efsw_pfn_handle_missed_fileactions fnfa ) :
+ mWatcher( watcher ), mFn( fn ), mParam( param ), mFnMissedFa( fnfa ) {}
void handleFileAction( efsw::WatchID watchid, const std::string& dir,
const std::string& filename, efsw::Action action,
@@ -21,6 +23,12 @@ class Watcher_CAPI : public efsw::FileWatchListener {
mFn( mWatcher, watchid, dir.c_str(), filename.c_str(), (enum efsw_action)action,
oldFilename.c_str(), mParam );
}
+
+ void handleMissedFileActions( efsw::WatchID watchid, const std::string& dir ) {
+ if ( mFnMissedFa ) {
+ mFnMissedFa( mWatcher, watchid, dir.c_str() );
+ }
+ }
};
/*************************************************************************************************
@@ -28,12 +36,12 @@ class Watcher_CAPI : public efsw::FileWatchListener {
*/
static std::vector<Watcher_CAPI*> g_callbacks;
-Watcher_CAPI* find_callback( efsw_watcher watcher, efsw_pfn_fileaction_callback fn ) {
+Watcher_CAPI* find_callback( efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param ) {
for ( std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); i != g_callbacks.end();
++i ) {
Watcher_CAPI* callback = *i;
- if ( callback->mFn == fn && callback->mWatcher == watcher )
+ if ( callback->mFn == fn && callback->mWatcher == watcher && callback->mParam == param )
return *i;
}
@@ -77,25 +85,27 @@ EFSW_API void efsw_clearlasterror() {
efsw_watchid efsw_addwatch( efsw_watcher watcher, const char* directory,
efsw_pfn_fileaction_callback callback_fn, int recursive, void* param ) {
- return efsw_addwatch_withoptions( watcher, directory, callback_fn, recursive, 0, 0, param );
+ return efsw_addwatch_withoptions( watcher, directory, callback_fn, recursive, 0, 0, param,
+ nullptr );
}
-efsw_watchid efsw_addwatch_withoptions(efsw_watcher watcher, const char* directory,
- efsw_pfn_fileaction_callback callback_fn, int recursive,
- efsw_watcher_option *options, int options_number,
- void* param) {
- Watcher_CAPI* callback = find_callback( watcher, callback_fn );
+efsw_watchid
+efsw_addwatch_withoptions( efsw_watcher watcher, const char* directory,
+ efsw_pfn_fileaction_callback callback_fn, int recursive,
+ efsw_watcher_option* options, int options_number, void* param,
+ efsw_pfn_handle_missed_fileactions callback_fn_missed_file_actions ) {
+ Watcher_CAPI* callback = find_callback( watcher, callback_fn, param );
if ( callback == NULL ) {
- callback = new Watcher_CAPI( watcher, callback_fn, param );
+ callback = new Watcher_CAPI( watcher, callback_fn, param, callback_fn_missed_file_actions );
g_callbacks.push_back( callback );
}
std::vector<efsw::WatcherOption> watcher_options{};
for ( int i = 0; i < options_number; i++ ) {
efsw_watcher_option* option = &options[i];
- watcher_options.emplace_back( efsw::WatcherOption{
- static_cast<efsw::Option>(option->option), option->value } );
+ watcher_options.emplace_back(
+ efsw::WatcherOption{ static_cast<efsw::Option>( option->option ), option->value } );
}
return ( (efsw::FileWatcher*)watcher )
diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.cpp b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp
index 0fa745242cf..70ec2b18233 100644
--- a/dep/efsw/src/efsw/FileWatcherFSEvents.cpp
+++ b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp
@@ -41,7 +41,33 @@ bool FileWatcherFSEvents::isGranular() {
return getOSXReleaseNumber() >= 11;
}
-void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef streamRef, void* userData,
+static std::string convertCFStringToStdString( CFStringRef cfString ) {
+ // Try to get the C string pointer directly
+ const char* cStr = CFStringGetCStringPtr( cfString, kCFStringEncodingUTF8 );
+
+ if ( cStr ) {
+ // If the pointer is valid, directly return a std::string from it
+ return std::string( cStr );
+ } else {
+ // If not, manually convert it
+ CFIndex length = CFStringGetLength( cfString );
+ CFIndex maxSize = CFStringGetMaximumSizeForEncoding( length, kCFStringEncodingUTF8 ) +
+ 1; // +1 for null terminator
+
+ char* buffer = new char[maxSize];
+
+ if ( CFStringGetCString( cfString, buffer, maxSize, kCFStringEncodingUTF8 ) ) {
+ std::string result( buffer );
+ delete[] buffer;
+ return result;
+ } else {
+ delete[] buffer;
+ return "";
+ }
+ }
+}
+
+void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef /*streamRef*/, void* userData,
size_t numEvents, void* eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[] ) {
@@ -51,8 +77,24 @@ void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef streamRef, void
events.reserve( numEvents );
for ( size_t i = 0; i < numEvents; i++ ) {
- events.push_back( FSEvent( std::string( ( (char**)eventPaths )[i] ), (long)eventFlags[i],
- (Uint64)eventIds[i] ) );
+ if ( isGranular() ) {
+ CFDictionaryRef pathInfoDict =
+ static_cast<CFDictionaryRef>( CFArrayGetValueAtIndex( (CFArrayRef)eventPaths, i ) );
+ CFStringRef path = static_cast<CFStringRef>(
+ CFDictionaryGetValue( pathInfoDict, kFSEventStreamEventExtendedDataPathKey ) );
+ CFNumberRef cfInode = static_cast<CFNumberRef>(
+ CFDictionaryGetValue( pathInfoDict, kFSEventStreamEventExtendedFileIDKey ) );
+
+ if ( cfInode ) {
+ unsigned long inode = 0;
+ CFNumberGetValue( cfInode, kCFNumberLongType, &inode );
+ events.push_back( FSEvent( convertCFStringToStdString( path ), (long)eventFlags[i],
+ (Uint64)eventIds[i], inode ) );
+ }
+ } else {
+ events.push_back( FSEvent( std::string( ( (char**)eventPaths )[i] ),
+ (long)eventFlags[i], (Uint64)eventIds[i] ) );
+ }
}
watcher->handleActions( events );
@@ -84,8 +126,8 @@ FileWatcherFSEvents::~FileWatcherFSEvents() {
}
WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher,
- bool recursive, const std::vector<WatcherOption> &options ) {
- std::string dir( directory );
+ bool recursive, const std::vector<WatcherOption>& options ) {
+ std::string dir( FileSystem::getRealPath( directory ) );
FileInfo fi( dir );
@@ -125,6 +167,9 @@ WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchLi
pWatch->Directory = dir;
pWatch->Recursive = recursive;
pWatch->FWatcher = this;
+ pWatch->ModifiedFlags =
+ getOptionValue( options, Option::MacModifiedFilter, efswFSEventsModified );
+ pWatch->SanitizeEvents = getOptionValue( options, Option::MacSanitizeEvents, 0 ) != 0;
pWatch->init();
@@ -169,8 +214,8 @@ void FileWatcherFSEvents::removeWatch( WatchID watchid ) {
void FileWatcherFSEvents::watch() {}
-void FileWatcherFSEvents::handleAction( Watcher* watch, const std::string& filename,
- unsigned long action, std::string oldFilename ) {
+void FileWatcherFSEvents::handleAction( Watcher* /*watch*/, const std::string& /*filename*/,
+ unsigned long /*action*/, std::string /*oldFilename*/ ) {
/// Not used
}
diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.hpp b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp
index 5ad182ed43f..daa538cc6fd 100644
--- a/dep/efsw/src/efsw/FileWatcherFSEvents.hpp
+++ b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp
@@ -16,27 +16,6 @@
namespace efsw {
-/* OSX < 10.7 has no file events */
-/* So i declare the events constants */
-enum FSEventEvents {
- efswFSEventStreamCreateFlagNoDefer = 0x00000002,
- efswFSEventStreamCreateFlagFileEvents = 0x00000010,
- efswFSEventStreamEventFlagItemCreated = 0x00000100,
- efswFSEventStreamEventFlagItemRemoved = 0x00000200,
- efswFSEventStreamEventFlagItemInodeMetaMod = 0x00000400,
- efswFSEventStreamEventFlagItemRenamed = 0x00000800,
- efswFSEventStreamEventFlagItemModified = 0x00001000,
- efswFSEventStreamEventFlagItemFinderInfoMod = 0x00002000,
- efswFSEventStreamEventFlagItemChangeOwner = 0x00004000,
- efswFSEventStreamEventFlagItemXattrMod = 0x00008000,
- efswFSEventStreamEventFlagItemIsFile = 0x00010000,
- efswFSEventStreamEventFlagItemIsDir = 0x00020000,
- efswFSEventStreamEventFlagItemIsSymlink = 0x00040000,
- efswFSEventsModified = efswFSEventStreamEventFlagItemFinderInfoMod |
- efswFSEventStreamEventFlagItemModified |
- efswFSEventStreamEventFlagItemInodeMetaMod
-};
-
/// Implementation for Win32 based on ReadDirectoryChangesW.
/// @class FileWatcherFSEvents
class FileWatcherFSEvents : public FileWatcherImpl {
diff --git a/dep/efsw/src/efsw/FileWatcherGeneric.cpp b/dep/efsw/src/efsw/FileWatcherGeneric.cpp
index 3f3c52e47fb..e0d393056a0 100644
--- a/dep/efsw/src/efsw/FileWatcherGeneric.cpp
+++ b/dep/efsw/src/efsw/FileWatcherGeneric.cpp
@@ -101,7 +101,7 @@ void FileWatcherGeneric::removeWatch( WatchID watchid ) {
void FileWatcherGeneric::watch() {
if ( NULL == mThread ) {
- mThread = new Thread( &FileWatcherGeneric::run, this );
+ mThread = new Thread([this]{run();});
mThread->launch();
}
}
diff --git a/dep/efsw/src/efsw/FileWatcherInotify.cpp b/dep/efsw/src/efsw/FileWatcherInotify.cpp
index 29be12b6262..cb751ba88ee 100644
--- a/dep/efsw/src/efsw/FileWatcherInotify.cpp
+++ b/dep/efsw/src/efsw/FileWatcherInotify.cpp
@@ -7,6 +7,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
+#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -69,15 +70,17 @@ FileWatcherInotify::~FileWatcherInotify() {
}
WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher,
- bool recursive, const std::vector<WatcherOption>& ) {
+ bool recursive, const std::vector<WatcherOption>& options ) {
if ( !mInitOK )
return Errors::Log::createLastError( Errors::Unspecified, directory );
Lock initLock( mInitLock );
- return addWatch( directory, watcher, recursive, NULL );
+ bool syntheticEvents = getOptionValue( options, Options::LinuxProduceSyntheticEvents, 0 ) != 0;
+ return addWatch( directory, watcher, recursive, syntheticEvents, NULL );
}
WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher,
- bool recursive, WatcherInotify* parent ) {
+ bool recursive, bool syntheticEvents, WatcherInotify* parent,
+ bool fromInternalEvent ) {
std::string dir( directory );
FileSystem::dirAddSlashAtEnd( dir );
@@ -137,6 +140,7 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis
pWatch->Directory = dir;
pWatch->Recursive = recursive;
pWatch->Parent = parent;
+ pWatch->syntheticEvents = syntheticEvents;
{
Lock lock( mWatchesLock );
@@ -151,6 +155,18 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis
if ( pWatch->Recursive ) {
std::map<std::string, FileInfo> files = FileSystem::filesInfoFromPath( pWatch->Directory );
+
+ if ( fromInternalEvent && parent != NULL && syntheticEvents ) {
+ for ( const auto& file : files ) {
+ if ( file.second.isRegularFile() || file.second.isDirectory() ||
+ file.second.isLink() ) {
+ pWatch->Listener->handleFileAction(
+ pWatch->ID, pWatch->Directory,
+ FileSystem::fileNameFromPath( file.second.Filepath ), Actions::Add );
+ }
+ }
+ }
+
std::map<std::string, FileInfo>::iterator it = files.begin();
for ( ; it != files.end(); ++it ) {
@@ -160,7 +176,8 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis
const FileInfo& cfi = it->second;
if ( cfi.isDirectory() && cfi.isReadable() ) {
- addWatch( cfi.Filepath, watcher, recursive, pWatch );
+ addWatch( cfi.Filepath, watcher, recursive, syntheticEvents, pWatch,
+ fromInternalEvent );
}
}
}
@@ -244,7 +261,7 @@ void FileWatcherInotify::removeWatch( WatchID watchid ) {
void FileWatcherInotify::watch() {
if ( NULL == mThread ) {
- mThread = new Thread( &FileWatcherInotify::run, this );
+ mThread = new Thread( [this] { run(); } );
mThread->launch();
}
}
@@ -267,10 +284,10 @@ Watcher* FileWatcherInotify::watcherContainsDirectory( std::string dir ) {
void FileWatcherInotify::run() {
char* buff = new char[BUFF_SIZE];
memset( buff, 0, BUFF_SIZE );
- WatchMap::iterator wit;
+ WatcherInotify* curWatcher = NULL;
WatcherInotify* currentMoveFrom = NULL;
- u_int32_t currentMoveCookie = -1;
+ uint32_t currentMoveCookie = -1;
bool lastWasMovedFrom = false;
std::string prevOldFileName;
@@ -294,16 +311,21 @@ void FileWatcherInotify::run() {
struct inotify_event* pevent = (struct inotify_event*)&buff[i];
{
+ curWatcher = NULL;
+
{
Lock lock( mWatchesLock );
- wit = mWatches.find( pevent->wd );
+ auto wit = mWatches.find( pevent->wd );
+
+ if ( wit != mWatches.end() )
+ curWatcher = wit->second;
}
- if ( wit != mWatches.end() ) {
- handleAction( wit->second, (char*)pevent->name, pevent->mask );
+ if ( curWatcher ) {
+ handleAction( curWatcher, (char*)pevent->name, pevent->mask );
- if ( ( pevent->mask & IN_MOVED_TO ) && wit->second == currentMoveFrom &&
+ if ( ( pevent->mask & IN_MOVED_TO ) && curWatcher == currentMoveFrom &&
pevent->cookie == currentMoveCookie ) {
/// make pair success
currentMoveFrom = NULL;
@@ -316,14 +338,30 @@ void FileWatcherInotify::run() {
std::make_pair( currentMoveFrom, prevOldFileName ) );
}
- currentMoveFrom = wit->second;
+ currentMoveFrom = curWatcher;
currentMoveCookie = pevent->cookie;
} else {
/// Keep track of the IN_MOVED_FROM events to know
/// if the IN_MOVED_TO event is also fired
if ( currentMoveFrom ) {
- mMovedOutsideWatches.push_back(
- std::make_pair( currentMoveFrom, prevOldFileName ) );
+ if ( std::find_if( mMovedOutsideWatches.begin(),
+ mMovedOutsideWatches.end(),
+ [currentMoveFrom](
+ const std::pair<WatcherInotify*,
+ std::string>& moved ) {
+ return moved.first == currentMoveFrom;
+ } ) == mMovedOutsideWatches.end() ) {
+ mMovedOutsideWatches.push_back(
+ std::make_pair( currentMoveFrom, prevOldFileName ) );
+ } else {
+ efDEBUG( "Info: Tried to add watch to the moved outside "
+ "watches but it was already there, Watch ID: %d - "
+ "Address: %p - Path: \"%s\" - prevOldFileName: "
+ "\"%s\"\n",
+ pevent->wd, currentMoveFrom,
+ currentMoveFrom->Directory.c_str(),
+ prevOldFileName.c_str() );
+ }
}
currentMoveFrom = NULL;
@@ -343,8 +381,18 @@ void FileWatcherInotify::run() {
// Here means no event received
// If last event is IN_MOVED_FROM, we assume no IN_MOVED_TO
if ( currentMoveFrom ) {
- mMovedOutsideWatches.push_back(
- std::make_pair( currentMoveFrom, currentMoveFrom->OldFileName ) );
+ if ( std::find_if(
+ mMovedOutsideWatches.begin(), mMovedOutsideWatches.end(),
+ [currentMoveFrom]( const std::pair<WatcherInotify*, std::string>& moved ) {
+ return moved.first == currentMoveFrom;
+ } ) == mMovedOutsideWatches.end() ) {
+ mMovedOutsideWatches.push_back(
+ std::make_pair( currentMoveFrom, currentMoveFrom->OldFileName ) );
+ } else {
+ efDEBUG( "Warning: Tried to add watch to the moved outside "
+ "watches but it was already there, Watch Address: %p\n",
+ currentMoveFrom );
+ }
}
currentMoveFrom = NULL;
@@ -378,8 +426,8 @@ void FileWatcherInotify::run() {
continue;
}
- Watcher* watch = ( *it ).first;
- const std::string& oldFileName = ( *it ).second;
+ Watcher* watch = it->first;
+ const std::string& oldFileName = it->second;
/// Check if the file move was a folder already being watched
std::vector<Watcher*> eraseWatches;
@@ -387,8 +435,8 @@ void FileWatcherInotify::run() {
{
Lock lock( mWatchesLock );
- for ( ; wit != mWatches.end(); ++wit ) {
- Watcher* oldWatch = wit->second;
+ for ( auto wit : mWatches ) {
+ Watcher* oldWatch = wit.second;
if ( oldWatch != watch &&
-1 != String::strStartsWith( watch->Directory + oldFileName + "/",
@@ -448,8 +496,9 @@ void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath )
}
if ( !found ) {
- addWatch( fpath, watch->Listener, watch->Recursive,
- static_cast<WatcherInotify*>( watch ) );
+ WatcherInotify* iWatch = static_cast<WatcherInotify*>( watch );
+ addWatch( fpath, watch->Listener, watch->Recursive, iWatch->syntheticEvents,
+ static_cast<WatcherInotify*>( watch ), true );
}
}
}
@@ -464,7 +513,9 @@ void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filena
std::string fpath( watch->Directory + filename );
- if ( ( IN_CLOSE_WRITE & action ) || ( IN_MODIFY & action ) ) {
+ if ( IN_Q_OVERFLOW & action ) {
+ watch->Listener->handleMissedFileActions( watch->ID, watch->Directory );
+ } else if ( ( IN_CLOSE_WRITE & action ) || ( IN_MODIFY & action ) ) {
watch->Listener->handleFileAction( watch->ID, watch->Directory, filename,
Actions::Modified );
} else if ( IN_MOVED_TO & action ) {
diff --git a/dep/efsw/src/efsw/FileWatcherInotify.hpp b/dep/efsw/src/efsw/FileWatcherInotify.hpp
index 84174a0676a..26d2c0b28e3 100644
--- a/dep/efsw/src/efsw/FileWatcherInotify.hpp
+++ b/dep/efsw/src/efsw/FileWatcherInotify.hpp
@@ -65,7 +65,8 @@ class FileWatcherInotify : public FileWatcherImpl {
std::vector<std::pair<WatcherInotify*, std::string>> mMovedOutsideWatches;
WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive,
- WatcherInotify* parent = NULL );
+ bool syntheticEvents, WatcherInotify* parent = NULL,
+ bool fromInternalEvent = false );
bool pathInWatches( const std::string& path ) override;
diff --git a/dep/efsw/src/efsw/FileWatcherKqueue.cpp b/dep/efsw/src/efsw/FileWatcherKqueue.cpp
index 32ef3dc82c8..41b4357e6ae 100644
--- a/dep/efsw/src/efsw/FileWatcherKqueue.cpp
+++ b/dep/efsw/src/efsw/FileWatcherKqueue.cpp
@@ -162,7 +162,7 @@ bool FileWatcherKqueue::isAddingWatcher() const {
void FileWatcherKqueue::watch() {
if ( NULL == mThread ) {
- mThread = new Thread( &FileWatcherKqueue::run, this );
+ mThread = new Thread([this]{run();});
mThread->launch();
}
}
diff --git a/dep/efsw/src/efsw/FileWatcherWin32.cpp b/dep/efsw/src/efsw/FileWatcherWin32.cpp
index 37f43cc27da..1dd96aa7945 100644
--- a/dep/efsw/src/efsw/FileWatcherWin32.cpp
+++ b/dep/efsw/src/efsw/FileWatcherWin32.cpp
@@ -26,7 +26,8 @@ FileWatcherWin32::~FileWatcherWin32() {
removeAllWatches();
- CloseHandle( mIOCP );
+ if ( mIOCP )
+ CloseHandle( mIOCP );
}
WatchID FileWatcherWin32::addWatch( const std::string& directory, FileWatchListener* watcher,
@@ -112,7 +113,7 @@ void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) {
void FileWatcherWin32::watch() {
if ( NULL == mThread ) {
- mThread = new Thread( &FileWatcherWin32::run, this );
+ mThread = new Thread([this]{run();});
mThread->launch();
}
}
@@ -143,7 +144,8 @@ void FileWatcherWin32::run() {
break;
} else {
Lock lock( mWatchesLock );
- WatchCallback( numOfBytes, ov );
+ if (mWatches.find( (WatcherStructWin32*)ov ) != mWatches.end())
+ WatchCallback( numOfBytes, ov );
}
}
} else {
diff --git a/dep/efsw/src/efsw/FileWatcherWin32.hpp b/dep/efsw/src/efsw/FileWatcherWin32.hpp
index de3f9538dcd..3f6f419bdbd 100644
--- a/dep/efsw/src/efsw/FileWatcherWin32.hpp
+++ b/dep/efsw/src/efsw/FileWatcherWin32.hpp
@@ -7,7 +7,7 @@
#include <efsw/WatcherWin32.hpp>
#include <map>
-#include <set>
+#include <unordered_set>
#include <vector>
namespace efsw {
@@ -17,7 +17,7 @@ namespace efsw {
class FileWatcherWin32 : public FileWatcherImpl {
public:
/// type for a map from WatchID to WatcherWin32 pointer
- typedef std::set<WatcherStructWin32*> Watches;
+ typedef std::unordered_set<WatcherStructWin32*> Watches;
FileWatcherWin32( FileWatcher* parent );
diff --git a/dep/efsw/src/efsw/Lock.hpp b/dep/efsw/src/efsw/Lock.hpp
index e8c522abf0d..714f3aa64b2 100644
--- a/dep/efsw/src/efsw/Lock.hpp
+++ b/dep/efsw/src/efsw/Lock.hpp
@@ -1,21 +1,11 @@
#ifndef EFSW_LOCK_HPP
#define EFSW_LOCK_HPP
+#include <mutex>
#include <efsw/Mutex.hpp>
namespace efsw {
-
-/** Simple mutex class */
-class Lock {
- public:
- explicit Lock( Mutex& mutex ) : mMutex( mutex ) { mMutex.lock(); }
-
- ~Lock() { mMutex.unlock(); }
-
- private:
- Mutex& mMutex;
-};
-
+ using Lock = std::unique_lock<Mutex>;
} // namespace efsw
#endif
diff --git a/dep/efsw/src/efsw/Mutex.cpp b/dep/efsw/src/efsw/Mutex.cpp
deleted file mode 100644
index c961db18124..00000000000
--- a/dep/efsw/src/efsw/Mutex.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <efsw/Mutex.hpp>
-#include <efsw/platform/platformimpl.hpp>
-
-namespace efsw {
-
-Mutex::Mutex() : mMutexImpl( new Platform::MutexImpl() ) {}
-
-Mutex::~Mutex() {
- efSAFE_DELETE( mMutexImpl );
-}
-
-void Mutex::lock() {
- mMutexImpl->lock();
-}
-
-void Mutex::unlock() {
- mMutexImpl->unlock();
-}
-
-} // namespace efsw
diff --git a/dep/efsw/src/efsw/Mutex.hpp b/dep/efsw/src/efsw/Mutex.hpp
index d98ad17c237..c1fca753863 100644
--- a/dep/efsw/src/efsw/Mutex.hpp
+++ b/dep/efsw/src/efsw/Mutex.hpp
@@ -1,31 +1,10 @@
#ifndef EFSW_MUTEX_HPP
#define EFSW_MUTEX_HPP
-#include <efsw/base.hpp>
+#include <mutex>
namespace efsw {
-
-namespace Platform {
-class MutexImpl;
-}
-
-/** Simple mutex class */
-class Mutex {
- public:
- Mutex();
-
- ~Mutex();
-
- /** Lock the mutex */
- void lock();
-
- /** Unlock the mutex */
- void unlock();
-
- private:
- Platform::MutexImpl* mMutexImpl;
-};
-
+ using Mutex = std::recursive_mutex;
} // namespace efsw
#endif
diff --git a/dep/efsw/src/efsw/String.hpp b/dep/efsw/src/efsw/String.hpp
index 65bce3328c2..b42b945354b 100644
--- a/dep/efsw/src/efsw/String.hpp
+++ b/dep/efsw/src/efsw/String.hpp
@@ -11,7 +11,6 @@
#include <cstdlib>
#include <cstring>
#include <efsw/base.hpp>
-#include <fstream>
#include <iostream>
#include <locale>
#include <sstream>
@@ -24,7 +23,7 @@ namespace efsw {
* **/
class String {
public:
- typedef Uint32 StringBaseType;
+ typedef char32_t StringBaseType;
typedef std::basic_string<StringBaseType> StringType;
typedef StringType::iterator Iterator; //! Iterator type
typedef StringType::const_iterator ConstIterator; //! Constant iterator type
diff --git a/dep/efsw/src/efsw/Thread.cpp b/dep/efsw/src/efsw/Thread.cpp
deleted file mode 100644
index cfa88b482d3..00000000000
--- a/dep/efsw/src/efsw/Thread.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <efsw/Thread.hpp>
-#include <efsw/platform/platformimpl.hpp>
-
-namespace efsw {
-
-Thread::Thread() : mThreadImpl( NULL ), mEntryPoint( NULL ) {}
-
-Thread::~Thread() {
- wait();
-
- efSAFE_DELETE( mEntryPoint );
-}
-
-void Thread::launch() {
- wait();
-
- mThreadImpl = new Platform::ThreadImpl( this );
-}
-
-void Thread::wait() {
- if ( mThreadImpl ) {
- mThreadImpl->wait();
-
- efSAFE_DELETE( mThreadImpl );
- }
-}
-
-void Thread::terminate() {
- if ( mThreadImpl ) {
- mThreadImpl->terminate();
-
- efSAFE_DELETE( mThreadImpl );
- }
-}
-
-void Thread::run() {
- if ( mEntryPoint )
- mEntryPoint->run();
-}
-
-} // namespace efsw
diff --git a/dep/efsw/src/efsw/Thread.hpp b/dep/efsw/src/efsw/Thread.hpp
index b60373c2075..5a5d470e10b 100644
--- a/dep/efsw/src/efsw/Thread.hpp
+++ b/dep/efsw/src/efsw/Thread.hpp
@@ -2,99 +2,48 @@
#define EFSW_THREAD_HPP
#include <efsw/base.hpp>
+#include <functional>
+#include <memory>
+#include <thread>
namespace efsw {
-namespace Platform {
-class ThreadImpl;
-}
-namespace Private {
-struct ThreadFunc;
-}
-
/** @brief Thread manager class */
class Thread {
public:
- typedef void ( *FuncType )( void* );
-
- template <typename F> Thread( F function );
-
- template <typename F, typename A> Thread( F function, A argument );
- template <typename C> Thread( void ( C::*function )(), C* object );
+ Thread(std::function<void()> fun)
+ : mFun{std::move(fun)}
+ {
+ }
- virtual ~Thread();
+ ~Thread()
+ {
+ wait();
+ }
/** Launch the thread */
- virtual void launch();
+ void launch()
+ {
+ if (!mThread)
+ mThread.reset(new std::thread{std::move(mFun)});
+ }
/** Wait the thread until end */
- void wait();
-
- /** Terminate the thread */
- void terminate();
-
- protected:
- Thread();
-
- private:
- friend class Platform::ThreadImpl;
-
- /** The virtual function to run in the thread */
- virtual void run();
-
- Platform::ThreadImpl* mThreadImpl; ///< OS-specific implementation of the thread
- Private::ThreadFunc* mEntryPoint; ///< Abstraction of the function to run
-};
-
-//! NOTE: Taken from SFML2 threads
-namespace Private {
-
-// Base class for abstract thread functions
-struct ThreadFunc {
- virtual ~ThreadFunc() {}
- virtual void run() = 0;
+ void wait()
+ {
+ if (mThread)
+ {
+ mThread->join();
+ mThread.reset();
+ }
+ }
+private:
+
+ std::unique_ptr<std::thread> mThread;
+ std::function<void()> mFun;
};
-// Specialization using a functor (including free functions) with no argument
-template <typename T> struct ThreadFunctor : ThreadFunc {
- ThreadFunctor( T functor ) : m_functor( functor ) {}
- virtual void run() { m_functor(); }
- T m_functor;
-};
-
-// Specialization using a functor (including free functions) with one argument
-template <typename F, typename A> struct ThreadFunctorWithArg : ThreadFunc {
- ThreadFunctorWithArg( F function, A arg ) : m_function( function ), m_arg( arg ) {}
- virtual void run() { m_function( m_arg ); }
- F m_function;
- A m_arg;
-};
-
-// Specialization using a member function
-template <typename C> struct ThreadMemberFunc : ThreadFunc {
- ThreadMemberFunc( void ( C::*function )(), C* object ) :
- m_function( function ), m_object( object ) {}
- virtual void run() { ( m_object->*m_function )(); }
- void ( C::*m_function )();
- C* m_object;
-};
-
-} // namespace Private
-
-template <typename F>
-Thread::Thread( F functor ) :
- mThreadImpl( NULL ), mEntryPoint( new Private::ThreadFunctor<F>( functor ) ) {}
-
-template <typename F, typename A>
-Thread::Thread( F function, A argument ) :
- mThreadImpl( NULL ),
- mEntryPoint( new Private::ThreadFunctorWithArg<F efCOMMA A>( function, argument ) ) {}
-
-template <typename C>
-Thread::Thread( void ( C::*function )(), C* object ) :
- mThreadImpl( NULL ), mEntryPoint( new Private::ThreadMemberFunc<C>( function, object ) ) {}
-
} // namespace efsw
#endif
diff --git a/dep/efsw/src/efsw/WatcherFSEvents.cpp b/dep/efsw/src/efsw/WatcherFSEvents.cpp
index 3621df746b5..bc982bf7e1d 100644
--- a/dep/efsw/src/efsw/WatcherFSEvents.cpp
+++ b/dep/efsw/src/efsw/WatcherFSEvents.cpp
@@ -10,13 +10,6 @@ namespace efsw {
WatcherFSEvents::WatcherFSEvents() :
Watcher(), FWatcher( NULL ), FSStream( NULL ), WatcherGen( NULL ) {}
-WatcherFSEvents::WatcherFSEvents( WatchID id, std::string directory, FileWatchListener* listener,
- bool recursive, WatcherFSEvents* parent ) :
- Watcher( id, directory, listener, recursive ),
- FWatcher( NULL ),
- FSStream( NULL ),
- WatcherGen( NULL ) {}
-
WatcherFSEvents::~WatcherFSEvents() {
if ( NULL != FSStream ) {
FSEventStreamStop( FSStream );
@@ -35,7 +28,9 @@ void WatcherFSEvents::init() {
Uint32 streamFlags = kFSEventStreamCreateFlagNone;
if ( FileWatcherFSEvents::isGranular() ) {
- streamFlags = efswFSEventStreamCreateFlagFileEvents | efswFSEventStreamCreateFlagNoDefer;
+ streamFlags = efswFSEventStreamCreateFlagFileEvents | efswFSEventStreamCreateFlagNoDefer |
+ efswFSEventStreamCreateFlagUseExtendedData |
+ efswFSEventStreamCreateFlagUseCFTypes;
} else {
WatcherGen = new WatcherGeneric( ID, Directory, Listener, FWatcher.load(), Recursive );
}
@@ -48,13 +43,13 @@ void WatcherFSEvents::init() {
ctx.release = NULL;
ctx.copyDescription = NULL;
- dispatch_queue_t queue = dispatch_queue_create(NULL, NULL);
+ dispatch_queue_t queue = dispatch_queue_create( NULL, NULL );
FSStream =
FSEventStreamCreate( kCFAllocatorDefault, &FileWatcherFSEvents::FSEventCallback, &ctx,
CFDirectoryArray, kFSEventStreamEventIdSinceNow, 0., streamFlags );
- FSEventStreamSetDispatchQueue(FSStream, queue);
+ FSEventStreamSetDispatchQueue( FSStream, queue );
FSEventStreamStart( FSStream );
@@ -66,27 +61,37 @@ void WatcherFSEvents::sendFileAction( WatchID watchid, const std::string& dir,
const std::string& filename, Action action,
std::string oldFilename ) {
Listener->handleFileAction( watchid, FileSystem::precomposeFileName( dir ),
- FileSystem::precomposeFileName( filename ), action, FileSystem::precomposeFileName( oldFilename ) );
+ FileSystem::precomposeFileName( filename ), action,
+ FileSystem::precomposeFileName( oldFilename ) );
+}
+
+void WatcherFSEvents::sendMissedFileActions( WatchID watchid,
+ const std::string& dir) {
+ Listener->handleMissedFileActions( watchid,
+ FileSystem::precomposeFileName( dir ) );
}
void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path,
- std::string& dirPath, std::string& filePath ) {
- if ( flags & efswFSEventStreamEventFlagItemCreated ) {
- if ( FileInfo::exists( path ) ) {
- sendFileAction( ID, dirPath, filePath, Actions::Add );
- }
+ std::string& dirPath, std::string& filePath, Uint64 inode ) {
+ if ( ( flags & efswFSEventStreamEventFlagItemCreated ) && FileInfo::exists( path ) &&
+ ( !SanitizeEvents || FilesAdded.find( inode ) != FilesAdded.end() ) ) {
+ sendFileAction( ID, dirPath, filePath, Actions::Add );
+
+ if ( SanitizeEvents )
+ FilesAdded.insert( inode );
}
- if ( flags & efswFSEventsModified ) {
+ if ( flags & ModifiedFlags ) {
sendFileAction( ID, dirPath, filePath, Actions::Modified );
}
- if ( flags & efswFSEventStreamEventFlagItemRemoved ) {
+ if ( ( flags & efswFSEventStreamEventFlagItemRemoved ) && !FileInfo::exists( path ) ) {
// Since i don't know the order, at least i try to keep the data consistent with the real
// state
- if ( !FileInfo::exists( path ) ) {
- sendFileAction( ID, dirPath, filePath, Actions::Delete );
- }
+ sendFileAction( ID, dirPath, filePath, Actions::Delete );
+
+ if ( SanitizeEvents )
+ FilesAdded.erase( inode );
}
}
@@ -98,7 +103,16 @@ void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) {
if ( event.Flags &
( kFSEventStreamEventFlagUserDropped | kFSEventStreamEventFlagKernelDropped |
- kFSEventStreamEventFlagEventIdsWrapped | kFSEventStreamEventFlagHistoryDone |
+ kFSEventStreamEventFlagMustScanSubDirs) ) {
+ efDEBUG( "Rescan/Drop event for watch: %s - flags: 0x%x\n", Directory.c_str(), event.Flags );
+ std::string dirPath = Directory;
+ FileSystem::dirRemoveSlashAtEnd( dirPath );
+ sendMissedFileActions(ID, dirPath );
+ continue;
+ }
+
+ if ( event.Flags &
+ ( kFSEventStreamEventFlagEventIdsWrapped | kFSEventStreamEventFlagHistoryDone |
kFSEventStreamEventFlagMount | kFSEventStreamEventFlagUnmount |
kFSEventStreamEventFlagRootChanged ) ) {
continue;
@@ -128,19 +142,20 @@ void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) {
// been added modified and erased, but i can't know if first was erased and then added
// and modified, or added, then modified and then erased. I don't know what they were
// thinking by doing this...
- efDEBUG( "Event in: %s - flags: %ld\n", event.Path.c_str(), event.Flags );
+ efDEBUG( "Event in: %s - flags: 0x%x\n", event.Path.c_str(), event.Flags );
if ( event.Flags & efswFSEventStreamEventFlagItemRenamed ) {
if ( ( i + 1 < esize ) &&
( events[i + 1].Flags & efswFSEventStreamEventFlagItemRenamed ) &&
- ( events[i + 1].Id == event.Id + 1 ) ) {
+ ( events[i + 1].inode == event.inode ) ) {
FSEvent& nEvent = events[i + 1];
std::string newDir( FileSystem::pathRemoveFileName( nEvent.Path ) );
std::string newFilepath( FileSystem::fileNameFromPath( nEvent.Path ) );
if ( event.Path != nEvent.Path ) {
if ( dirPath == newDir ) {
- if ( !FileInfo::exists( event.Path ) ) {
+ if ( !FileInfo::exists( event.Path ) ||
+ 0 == strcasecmp( event.Path.c_str(), nEvent.Path.c_str() ) ) {
sendFileAction( ID, dirPath, newFilepath, Actions::Moved,
filePath );
} else {
@@ -151,12 +166,12 @@ void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) {
sendFileAction( ID, dirPath, filePath, Actions::Delete );
sendFileAction( ID, newDir, newFilepath, Actions::Add );
- if ( nEvent.Flags & efswFSEventsModified ) {
+ if ( nEvent.Flags & ModifiedFlags ) {
sendFileAction( ID, newDir, newFilepath, Actions::Modified );
}
}
} else {
- handleAddModDel( nEvent.Flags, nEvent.Path, dirPath, filePath );
+ handleAddModDel( nEvent.Flags, nEvent.Path, dirPath, filePath, event.inode );
}
if ( nEvent.Flags & ( efswFSEventStreamEventFlagItemCreated |
@@ -172,14 +187,14 @@ void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) {
} else if ( FileInfo::exists( event.Path ) ) {
sendFileAction( ID, dirPath, filePath, Actions::Add );
- if ( event.Flags & efswFSEventsModified ) {
+ if ( event.Flags & ModifiedFlags ) {
sendFileAction( ID, dirPath, filePath, Actions::Modified );
}
} else {
sendFileAction( ID, dirPath, filePath, Actions::Delete );
}
} else {
- handleAddModDel( event.Flags, event.Path, dirPath, filePath );
+ handleAddModDel( event.Flags, event.Path, dirPath, filePath, event.inode );
}
} else {
efDEBUG( "Directory: %s changed\n", event.Path.c_str() );
@@ -189,7 +204,7 @@ void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) {
}
void WatcherFSEvents::process() {
- std::set<std::string>::iterator it = DirsChanged.begin();
+ std::unordered_set<std::string>::iterator it = DirsChanged.begin();
for ( ; it != DirsChanged.end(); it++ ) {
if ( !FileWatcherFSEvents::isGranular() ) {
diff --git a/dep/efsw/src/efsw/WatcherFSEvents.hpp b/dep/efsw/src/efsw/WatcherFSEvents.hpp
index a18c06d40b9..fe17ed4db17 100644
--- a/dep/efsw/src/efsw/WatcherFSEvents.hpp
+++ b/dep/efsw/src/efsw/WatcherFSEvents.hpp
@@ -9,29 +9,51 @@
#include <CoreServices/CoreServices.h>
#include <efsw/FileInfo.hpp>
#include <efsw/WatcherGeneric.hpp>
-#include <set>
+#include <unordered_set>
#include <vector>
namespace efsw {
+/* OSX < 10.7 has no file events */
+/* So i declare the events constants */
+enum FSEventEvents {
+ efswFSEventStreamCreateFlagUseCFTypes = 0x00000001,
+ efswFSEventStreamCreateFlagNoDefer = 0x00000002,
+ efswFSEventStreamCreateFlagFileEvents = 0x00000010,
+ efswFSEventStreamCreateFlagUseExtendedData = 0x00000040,
+ efswFSEventStreamEventFlagItemCreated = 0x00000100,
+ efswFSEventStreamEventFlagItemRemoved = 0x00000200,
+ efswFSEventStreamEventFlagItemInodeMetaMod = 0x00000400,
+ efswFSEventStreamEventFlagItemRenamed = 0x00000800,
+ efswFSEventStreamEventFlagItemModified = 0x00001000,
+ efswFSEventStreamEventFlagItemFinderInfoMod = 0x00002000,
+ efswFSEventStreamEventFlagItemChangeOwner = 0x00004000,
+ efswFSEventStreamEventFlagItemXattrMod = 0x00008000,
+ efswFSEventStreamEventFlagItemIsFile = 0x00010000,
+ efswFSEventStreamEventFlagItemIsDir = 0x00020000,
+ efswFSEventStreamEventFlagItemIsSymlink = 0x00040000,
+ efswFSEventsModified = efswFSEventStreamEventFlagItemFinderInfoMod |
+ efswFSEventStreamEventFlagItemModified |
+ efswFSEventStreamEventFlagItemInodeMetaMod
+};
+
class FileWatcherFSEvents;
class FSEvent {
public:
- FSEvent( std::string path, long flags, Uint64 id ) : Path( path ), Flags( flags ), Id( id ) {}
+ FSEvent( std::string path, long flags, Uint64 id, Uint64 inode = 0 ) :
+ Path( path ), Flags( flags ), Id( id ), inode( inode ) {}
std::string Path;
- long Flags;
- Uint64 Id;
+ long Flags{ 0 };
+ Uint64 Id{ 0 };
+ Uint64 inode{ 0 };
};
class WatcherFSEvents : public Watcher {
public:
WatcherFSEvents();
- WatcherFSEvents( WatchID id, std::string directory, FileWatchListener* listener, bool recursive,
- WatcherFSEvents* parent = NULL );
-
~WatcherFSEvents();
void init();
@@ -42,17 +64,22 @@ class WatcherFSEvents : public Watcher {
Atomic<FileWatcherFSEvents*> FWatcher;
FSEventStreamRef FSStream;
+ Uint64 ModifiedFlags{ efswFSEventsModified };
+ bool SanitizeEvents{ false };
protected:
void handleAddModDel( const Uint32& flags, const std::string& path, std::string& dirPath,
- std::string& filePath );
+ std::string& filePath, Uint64 inode );
WatcherGeneric* WatcherGen;
- std::set<std::string> DirsChanged;
+ std::unordered_set<std::string> DirsChanged;
+ std::unordered_set<Uint64> FilesAdded;
void sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename,
Action action, std::string oldFilename = "" );
+
+ void sendMissedFileActions( WatchID watchid, const std::string& dir);
};
} // namespace efsw
diff --git a/dep/efsw/src/efsw/WatcherInotify.hpp b/dep/efsw/src/efsw/WatcherInotify.hpp
index d43935c5009..ec55ed0e73e 100644
--- a/dep/efsw/src/efsw/WatcherInotify.hpp
+++ b/dep/efsw/src/efsw/WatcherInotify.hpp
@@ -16,6 +16,7 @@ class WatcherInotify : public Watcher {
WatchID InotifyID;
FileInfo DirInfo;
+ bool syntheticEvents{ false };
};
} // namespace efsw
diff --git a/dep/efsw/src/efsw/WatcherKqueue.cpp b/dep/efsw/src/efsw/WatcherKqueue.cpp
index 397264162e5..424b9890e0d 100644
--- a/dep/efsw/src/efsw/WatcherKqueue.cpp
+++ b/dep/efsw/src/efsw/WatcherKqueue.cpp
@@ -354,7 +354,8 @@ void WatcherKqueue::watch() {
bool needScan = false;
// Then we get the the events of the current folder
- while ( ( nev = kevent( mKqueue, &mChangeList[0], mChangeListCount + 1, &event, 1,
+ while ( !mChangeList.empty() &&
+ ( nev = kevent( mKqueue, mChangeList.data(), mChangeListCount + 1, &event, 1,
&mWatcher->mTimeOut ) ) != 0 ) {
// An error ocurred?
if ( nev == -1 ) {
diff --git a/dep/efsw/src/efsw/WatcherWin32.cpp b/dep/efsw/src/efsw/WatcherWin32.cpp
index ad206e35f71..d8d47aa7c5e 100644
--- a/dep/efsw/src/efsw/WatcherWin32.cpp
+++ b/dep/efsw/src/efsw/WatcherWin32.cpp
@@ -1,4 +1,5 @@
#include <efsw/Debug.hpp>
+#include <efsw/FileSystem.hpp>
#include <efsw/String.hpp>
#include <efsw/WatcherWin32.hpp>
@@ -8,30 +9,95 @@
namespace efsw {
-/// Unpacks events and passes them to a user defined callback.
-void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ) {
+struct EFSW_FILE_NOTIFY_EXTENDED_INFORMATION_EX {
+ DWORD NextEntryOffset;
+ DWORD Action;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastModificationTime;
+ LARGE_INTEGER LastChangeTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER AllocatedLength;
+ LARGE_INTEGER FileSize;
+ DWORD FileAttributes;
+ DWORD ReparsePointTag;
+ LARGE_INTEGER FileId;
+ LARGE_INTEGER ParentFileId;
+ DWORD FileNameLength;
+ WCHAR FileName[1];
+};
- if ( NULL == lpOverlapped ) {
- return;
+typedef EFSW_FILE_NOTIFY_EXTENDED_INFORMATION_EX* EFSW_PFILE_NOTIFY_EXTENDED_INFORMATION_EX;
+
+typedef BOOL( WINAPI* EFSW_LPREADDIRECTORYCHANGESEXW )( HANDLE hDirectory, LPVOID lpBuffer,
+ DWORD nBufferLength, BOOL bWatchSubtree,
+ DWORD dwNotifyFilter, LPDWORD lpBytesReturned,
+ LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
+ DWORD ReadDirectoryNotifyInformationClass );
+
+static EFSW_LPREADDIRECTORYCHANGESEXW pReadDirectoryChangesExW = NULL;
+
+#define EFSW_ReadDirectoryNotifyExtendedInformation 2
+
+static void initReadDirectoryChangesEx() {
+ static bool hasInit = false;
+ if ( !hasInit ) {
+ hasInit = true;
+
+ HMODULE hModule = GetModuleHandleW( L"Kernel32.dll" );
+ if ( !hModule )
+ return;
+
+ pReadDirectoryChangesExW =
+ (EFSW_LPREADDIRECTORYCHANGESEXW)GetProcAddress( hModule, "ReadDirectoryChangesExW" );
}
+}
+void WatchCallbackOld( WatcherWin32* pWatch ) {
PFILE_NOTIFY_INFORMATION pNotify;
- WatcherStructWin32* tWatch = (WatcherStructWin32*)lpOverlapped;
- WatcherWin32* pWatch = tWatch->Watch;
size_t offset = 0;
+ do {
+ bool skip = false;
- if ( dwNumberOfBytesTransfered == 0 ) {
- if ( nullptr != pWatch && !pWatch->StopNow ) {
- RefreshWatch( tWatch );
- } else {
- return;
+ pNotify = (PFILE_NOTIFY_INFORMATION)&pWatch->Buffer[offset];
+ offset += pNotify->NextEntryOffset;
+ int count =
+ WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName,
+ pNotify->FileNameLength / sizeof( WCHAR ), NULL, 0, NULL, NULL );
+ if ( count == 0 )
+ continue;
+
+ std::string nfile( count, '\0' );
+
+ count = WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName,
+ pNotify->FileNameLength / sizeof( WCHAR ), &nfile[0], count,
+ NULL, NULL );
+
+ if ( FILE_ACTION_MODIFIED == pNotify->Action ) {
+ FileInfo fifile( std::string( pWatch->DirName ) + nfile );
+
+ if ( pWatch->LastModifiedEvent.file.ModificationTime == fifile.ModificationTime &&
+ pWatch->LastModifiedEvent.file.Size == fifile.Size &&
+ pWatch->LastModifiedEvent.fileName == nfile ) {
+ skip = true;
+ }
+
+ pWatch->LastModifiedEvent.fileName = nfile;
+ pWatch->LastModifiedEvent.file = fifile;
}
- }
+ if ( !skip ) {
+ pWatch->Watch->handleAction( pWatch, nfile, pNotify->Action );
+ }
+ } while ( pNotify->NextEntryOffset != 0 );
+}
+
+void WatchCallbackEx( WatcherWin32* pWatch ) {
+ EFSW_PFILE_NOTIFY_EXTENDED_INFORMATION_EX pNotify;
+ size_t offset = 0;
do {
bool skip = false;
- pNotify = (PFILE_NOTIFY_INFORMATION)&pWatch->Buffer[offset];
+ pNotify = (EFSW_PFILE_NOTIFY_EXTENDED_INFORMATION_EX)&pWatch->Buffer[offset];
offset += pNotify->NextEntryOffset;
int count =
WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName,
@@ -56,12 +122,63 @@ void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOve
pWatch->LastModifiedEvent.fileName = nfile;
pWatch->LastModifiedEvent.file = fifile;
+ } else if ( FILE_ACTION_RENAMED_OLD_NAME == pNotify->Action ) {
+ pWatch->OldFiles.emplace_back( nfile, pNotify->FileId );
+ skip = true;
+ } else if ( FILE_ACTION_RENAMED_NEW_NAME == pNotify->Action ) {
+ std::string oldFile;
+ LARGE_INTEGER oldFileId{};
+
+ for ( auto it = pWatch->OldFiles.begin(); it != pWatch->OldFiles.end(); ++it ) {
+ if ( it->second.QuadPart == pNotify->FileId.QuadPart ) {
+ oldFile = it->first;
+ oldFileId = it->second;
+ it = pWatch->OldFiles.erase( it );
+ break;
+ }
+ }
+
+ if ( oldFile.empty() ) {
+ pWatch->Watch->handleAction( pWatch, nfile, FILE_ACTION_ADDED );
+ skip = true;
+ } else {
+ pWatch->Watch->handleAction( pWatch, oldFile, FILE_ACTION_RENAMED_OLD_NAME );
+ }
}
if ( !skip ) {
pWatch->Watch->handleAction( pWatch, nfile, pNotify->Action );
}
} while ( pNotify->NextEntryOffset != 0 );
+}
+
+/// Unpacks events and passes them to a user defined callback.
+void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ) {
+ if ( NULL == lpOverlapped ) {
+ return;
+ }
+
+ WatcherStructWin32* tWatch = (WatcherStructWin32*)lpOverlapped;
+ WatcherWin32* pWatch = tWatch->Watch;
+
+ if ( dwNumberOfBytesTransfered == 0 ) {
+ if ( nullptr != pWatch && !pWatch->StopNow ) {
+ /// Missed file actions due to buffer overflowed
+ std::string dir = pWatch->DirName;
+ FileSystem::dirRemoveSlashAtEnd( dir );
+ pWatch->Listener->handleMissedFileActions( pWatch->ID, dir );
+ RefreshWatch( tWatch );
+ } else {
+ return;
+ }
+ }
+
+ // Fork watch depending on the Windows API supported
+ if ( pWatch->Extended ) {
+ WatchCallbackEx( pWatch );
+ } else {
+ WatchCallbackOld( pWatch );
+ }
if ( !pWatch->StopNow ) {
RefreshWatch( tWatch );
@@ -69,17 +186,40 @@ void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOve
}
/// Refreshes the directory monitoring.
-bool RefreshWatch( WatcherStructWin32* pWatch ) {
- bool bRet = ReadDirectoryChangesW( pWatch->Watch->DirHandle, pWatch->Watch->Buffer.data(),
- pWatch->Watch->Buffer.size(), pWatch->Watch->Recursive,
- pWatch->Watch->NotifyFilter, NULL, &pWatch->Overlapped, NULL ) != 0;
+RefreshResult RefreshWatch( WatcherStructWin32* pWatch ) {
+ initReadDirectoryChangesEx();
+
+ bool bRet = false;
+ RefreshResult ret = RefreshResult::Failed;
+ pWatch->Watch->Extended = false;
+
+ if ( pReadDirectoryChangesExW ) {
+ bRet = pReadDirectoryChangesExW( pWatch->Watch->DirHandle, pWatch->Watch->Buffer.data(),
+ (DWORD)pWatch->Watch->Buffer.size(), pWatch->Watch->Recursive,
+ pWatch->Watch->NotifyFilter, NULL, &pWatch->Overlapped,
+ NULL, EFSW_ReadDirectoryNotifyExtendedInformation ) != 0;
+ if ( bRet ) {
+ ret = RefreshResult::SucessEx;
+ pWatch->Watch->Extended = true;
+ }
+ }
+
+ if ( !bRet ) {
+ bRet = ReadDirectoryChangesW( pWatch->Watch->DirHandle, pWatch->Watch->Buffer.data(),
+ (DWORD)pWatch->Watch->Buffer.size(), pWatch->Watch->Recursive,
+ pWatch->Watch->NotifyFilter, NULL, &pWatch->Overlapped,
+ NULL ) != 0;
+
+ if ( bRet )
+ ret = RefreshResult::Success;
+ }
if ( !bRet ) {
std::string error = std::to_string( GetLastError() );
Errors::Log::createLastError( Errors::WatcherFailed, error );
}
- return bRet;
+ return ret;
}
/// Stops monitoring a directory.
@@ -91,19 +231,17 @@ void DestroyWatch( WatcherStructWin32* pWatch ) {
CloseHandle( pWatch->Watch->DirHandle );
efSAFE_DELETE_ARRAY( pWatch->Watch->DirName );
efSAFE_DELETE( pWatch->Watch );
+ efSAFE_DELETE( pWatch );
}
}
/// Starts monitoring a directory.
WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive,
DWORD bufferSize, DWORD notifyFilter, HANDLE iocp ) {
- WatcherStructWin32* tWatch;
- size_t ptrsize = sizeof( *tWatch );
- tWatch = static_cast<WatcherStructWin32*>(
- HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize ) );
-
+ WatcherStructWin32* tWatch = new WatcherStructWin32();
WatcherWin32* pWatch = new WatcherWin32(bufferSize);
- tWatch->Watch = pWatch;
+ if (tWatch)
+ tWatch->Watch = pWatch;
pWatch->DirHandle = CreateFileW(
szDirectory, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
@@ -114,14 +252,14 @@ WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive,
pWatch->NotifyFilter = notifyFilter;
pWatch->Recursive = recursive;
- if ( RefreshWatch( tWatch ) ) {
+ if ( RefreshResult::Failed != RefreshWatch( tWatch ) ) {
return tWatch;
}
}
CloseHandle( pWatch->DirHandle );
efSAFE_DELETE( pWatch->Watch );
- HeapFree( GetProcessHeap(), 0, tWatch );
+ efSAFE_DELETE( tWatch );
return NULL;
}
diff --git a/dep/efsw/src/efsw/WatcherWin32.hpp b/dep/efsw/src/efsw/WatcherWin32.hpp
index ae050b730df..ea1e8e4558c 100644
--- a/dep/efsw/src/efsw/WatcherWin32.hpp
+++ b/dep/efsw/src/efsw/WatcherWin32.hpp
@@ -22,6 +22,8 @@ namespace efsw {
class WatcherWin32;
+enum RefreshResult { Failed, Success, SucessEx };
+
/// Internal watch data
struct WatcherStructWin32 {
OVERLAPPED Overlapped;
@@ -33,7 +35,7 @@ struct sLastModifiedEvent {
std::string fileName;
};
-bool RefreshWatch( WatcherStructWin32* pWatch );
+RefreshResult RefreshWatch( WatcherStructWin32* pWatch );
void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped );
@@ -51,6 +53,7 @@ class WatcherWin32 : public Watcher {
lParam( 0 ),
NotifyFilter( 0 ),
StopNow( false ),
+ Extended( false ),
Watch( NULL ),
DirName( NULL ) {
Buffer.resize(dwBufferSize);
@@ -62,9 +65,11 @@ class WatcherWin32 : public Watcher {
LPARAM lParam;
DWORD NotifyFilter;
bool StopNow;
+ bool Extended;
FileWatcherImpl* Watch;
char* DirName;
sLastModifiedEvent LastModifiedEvent;
+ std::vector<std::pair<std::string, LARGE_INTEGER>> OldFiles;
};
} // namespace efsw
diff --git a/dep/efsw/src/efsw/platform/platformimpl.hpp b/dep/efsw/src/efsw/platform/platformimpl.hpp
index 54425806985..f4942418c00 100644
--- a/dep/efsw/src/efsw/platform/platformimpl.hpp
+++ b/dep/efsw/src/efsw/platform/platformimpl.hpp
@@ -4,13 +4,9 @@
#include <efsw/base.hpp>
#if defined( EFSW_PLATFORM_POSIX )
-#include <efsw/platform/posix/ThreadImpl.hpp>
-#include <efsw/platform/posix/MutexImpl.hpp>
#include <efsw/platform/posix/SystemImpl.hpp>
#include <efsw/platform/posix/FileSystemImpl.hpp>
#elif EFSW_PLATFORM == EFSW_PLATFORM_WIN32
-#include <efsw/platform/win/ThreadImpl.hpp>
-#include <efsw/platform/win/MutexImpl.hpp>
#include <efsw/platform/win/SystemImpl.hpp>
#include <efsw/platform/win/FileSystemImpl.hpp>
#else
diff --git a/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp b/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp
deleted file mode 100644
index 2233798284c..00000000000
--- a/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <efsw/platform/posix/MutexImpl.hpp>
-
-#if defined( EFSW_PLATFORM_POSIX )
-
-namespace efsw { namespace Platform {
-
-MutexImpl::MutexImpl() {
- pthread_mutexattr_t attributes;
- pthread_mutexattr_init( &attributes );
- pthread_mutexattr_settype( &attributes, PTHREAD_MUTEX_RECURSIVE );
- pthread_mutex_init( &mMutex, &attributes );
-}
-
-MutexImpl::~MutexImpl() {
- pthread_mutex_destroy( &mMutex );
-}
-
-void MutexImpl::lock() {
- pthread_mutex_lock( &mMutex );
-}
-
-void MutexImpl::unlock() {
- pthread_mutex_unlock( &mMutex );
-}
-
-}} // namespace efsw::Platform
-
-#endif
diff --git a/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp b/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp
deleted file mode 100644
index a33d827966f..00000000000
--- a/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef EFSW_MUTEXIMPLPOSIX_HPP
-#define EFSW_MUTEXIMPLPOSIX_HPP
-
-#include <efsw/base.hpp>
-
-#if defined( EFSW_PLATFORM_POSIX )
-
-#include <pthread.h>
-
-namespace efsw { namespace Platform {
-
-class MutexImpl {
- public:
- MutexImpl();
-
- ~MutexImpl();
-
- void lock();
-
- void unlock();
-
- private:
- pthread_mutex_t mMutex;
-};
-
-}} // namespace efsw::Platform
-
-#endif
-
-#endif
diff --git a/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp b/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp
deleted file mode 100644
index 0f96bca7e55..00000000000
--- a/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#include <efsw/Thread.hpp>
-#include <efsw/platform/posix/ThreadImpl.hpp>
-
-#if defined( EFSW_PLATFORM_POSIX )
-
-#include <cassert>
-#include <efsw/Debug.hpp>
-#include <iostream>
-
-namespace efsw { namespace Platform {
-
-ThreadImpl::ThreadImpl( efsw::Thread* owner ) : mIsActive( false ) {
- mIsActive = pthread_create( &mThread, NULL, &ThreadImpl::entryPoint, owner ) == 0;
-
- if ( !mIsActive ) {
- efDEBUG( "Failed to create thread\n" );
- }
-}
-
-ThreadImpl::~ThreadImpl() {
- terminate();
-}
-
-void ThreadImpl::wait() {
- // Wait for the thread to finish, no timeout
- if ( mIsActive ) {
- assert( pthread_equal( pthread_self(), mThread ) == 0 );
-
- mIsActive = pthread_join( mThread, NULL ) != 0;
- }
-}
-
-void ThreadImpl::terminate() {
- if ( mIsActive ) {
-#if !defined( __ANDROID__ ) && !defined( ANDROID )
- pthread_cancel( mThread );
-#else
- pthread_kill( mThread, SIGUSR1 );
-#endif
-
- mIsActive = false;
- }
-}
-
-void* ThreadImpl::entryPoint( void* userData ) {
-// Tell the thread to handle cancel requests immediatly
-#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
- pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );
-#endif
-
- // The Thread instance is stored in the user data
- Thread* owner = static_cast<Thread*>( userData );
-
- // Forward to the owner
- owner->run();
-
- return NULL;
-}
-
-}} // namespace efsw::Platform
-
-#endif
diff --git a/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp b/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp
deleted file mode 100644
index 2e02f9ac89d..00000000000
--- a/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef EFSW_THREADIMPLPOSIX_HPP
-#define EFSW_THREADIMPLPOSIX_HPP
-
-#include <efsw/base.hpp>
-
-#if defined( EFSW_PLATFORM_POSIX )
-
-#include <efsw/Atomic.hpp>
-#include <pthread.h>
-
-namespace efsw {
-
-class Thread;
-
-namespace Platform {
-
-class ThreadImpl {
- public:
- explicit ThreadImpl( efsw::Thread* owner );
-
- ~ThreadImpl();
-
- void wait();
-
- void terminate();
-
- protected:
- static void* entryPoint( void* userData );
-
- pthread_t mThread;
- Atomic<bool> mIsActive;
-};
-
-} // namespace Platform
-} // namespace efsw
-
-#endif
-
-#endif
diff --git a/dep/efsw/src/efsw/platform/win/MutexImpl.cpp b/dep/efsw/src/efsw/platform/win/MutexImpl.cpp
deleted file mode 100644
index 62b7f836e51..00000000000
--- a/dep/efsw/src/efsw/platform/win/MutexImpl.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <efsw/platform/win/MutexImpl.hpp>
-
-#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
-
-namespace efsw { namespace Platform {
-
-MutexImpl::MutexImpl() {
- InitializeCriticalSection( &mMutex );
-}
-
-MutexImpl::~MutexImpl() {
- DeleteCriticalSection( &mMutex );
-}
-
-void MutexImpl::lock() {
- EnterCriticalSection( &mMutex );
-}
-
-void MutexImpl::unlock() {
- LeaveCriticalSection( &mMutex );
-}
-
-}} // namespace efsw::Platform
-
-#endif
diff --git a/dep/efsw/src/efsw/platform/win/MutexImpl.hpp b/dep/efsw/src/efsw/platform/win/MutexImpl.hpp
deleted file mode 100644
index 7b064920f81..00000000000
--- a/dep/efsw/src/efsw/platform/win/MutexImpl.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef EFSW_MUTEXIMPLWIN_HPP
-#define EFSW_MUTEXIMPLWIN_HPP
-
-#include <efsw/base.hpp>
-
-#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-
-namespace efsw { namespace Platform {
-
-class MutexImpl {
- public:
- MutexImpl();
-
- ~MutexImpl();
-
- void lock();
-
- void unlock();
-
- private:
- CRITICAL_SECTION mMutex;
-};
-
-}} // namespace efsw::Platform
-
-#endif
-
-#endif
diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp
deleted file mode 100644
index 463934c9009..00000000000
--- a/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-#include <assert.h>
-#include <efsw/Thread.hpp>
-#include <efsw/platform/win/ThreadImpl.hpp>
-
-#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
-
-#include <efsw/Debug.hpp>
-
-namespace efsw { namespace Platform {
-
-ThreadImpl::ThreadImpl( efsw::Thread* owner ) {
- mThread = reinterpret_cast<HANDLE>(
- _beginthreadex( NULL, 0, &ThreadImpl::entryPoint, owner, 0, &mThreadId ) );
-
- if ( !mThread ) {
- efDEBUG( "Failed to create thread\n" );
- }
-}
-
-ThreadImpl::~ThreadImpl() {
- if ( mThread ) {
- CloseHandle( mThread );
- }
-}
-
-void ThreadImpl::wait() {
- // Wait for the thread to finish, no timeout
- if ( mThread ) {
- assert( mThreadId != GetCurrentThreadId() ); // A thread cannot wait for itself!
-
- WaitForSingleObject( mThread, INFINITE );
- }
-}
-
-void ThreadImpl::terminate() {
- if ( mThread ) {
- TerminateThread( mThread, 0 );
- }
-}
-
-unsigned int __stdcall ThreadImpl::entryPoint( void* userData ) {
- // The Thread instance is stored in the user data
- Thread* owner = static_cast<Thread*>( userData );
-
- // Forward to the owner
- owner->run();
-
- // Optional, but it is cleaner
- _endthreadex( 0 );
-
- return 0;
-}
-
-}} // namespace efsw::Platform
-
-#endif
diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp
deleted file mode 100644
index 455f24c2783..00000000000
--- a/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef EFSW_THREADIMPLWIN_HPP
-#define EFSW_THREADIMPLWIN_HPP
-
-#include <efsw/base.hpp>
-
-#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <process.h>
-#include <windows.h>
-
-namespace efsw {
-
-class Thread;
-
-namespace Platform {
-
-class ThreadImpl {
- public:
- explicit ThreadImpl( efsw::Thread* owner );
-
- ~ThreadImpl();
-
- void wait();
-
- void terminate();
-
- protected:
- static unsigned int __stdcall entryPoint( void* userData );
-
- HANDLE mThread;
- unsigned int mThreadId;
-};
-
-} // namespace Platform
-} // namespace efsw
-
-#endif
-
-#endif
diff --git a/dep/efsw/src/test/efsw-test.c b/dep/efsw/src/test/efsw-test.c
index 54a3e21bba5..143f35f87ec 100644
--- a/dep/efsw/src/test/efsw-test.c
+++ b/dep/efsw/src/test/efsw-test.c
@@ -8,9 +8,9 @@
#include <time.h>
#ifdef _WIN32
- #include <Windows.h>
+#include <Windows.h>
#else
- #include <unistd.h>
+#include <unistd.h>
#endif
const char PATH_SEPARATOR =
@@ -32,10 +32,10 @@ void sleepMsecs( int msecs ) {
Sleep( msecs );
#else
sleep( msecs );
-#endif
+#endif
}
-const char * getActionName( enum efsw_action action ) {
+const char* getActionName( enum efsw_action action ) {
switch ( action ) {
case EFSW_ADD:
return "Add";
@@ -50,16 +50,15 @@ const char * getActionName( enum efsw_action action ) {
}
}
-void handleFileAction( efsw_watcher watcher, efsw_watchid watchid,
- const char* dir, const char* filename,
- enum efsw_action action, const char* oldFilename,
- void* param ) {
+void handleFileAction( efsw_watcher watcher, efsw_watchid watchid, const char* dir,
+ const char* filename, enum efsw_action action, const char* oldFilename,
+ void* param ) {
if ( strlen( oldFilename ) == 0 ) {
- printf( "Watch ID %ld DIR (%s) FILE (%s) has event %s\n",
- watchid, dir, filename, getActionName( action ));
+ printf( "Watch ID %ld DIR (%s) FILE (%s) has event %s\n", watchid, dir, filename,
+ getActionName( action ) );
} else {
- printf( "Watch ID %ld DIR (%s) FILE (from file %s to %s) has event %s\n",
- watchid, dir, oldFilename, filename, getActionName( action ));
+ printf( "Watch ID %ld DIR (%s) FILE (from file %s to %s) has event %s\n", watchid, dir,
+ oldFilename, filename, getActionName( action ) );
}
}
@@ -87,17 +86,17 @@ int main( int argc, char** argv ) {
signal( SIGINT, sigend );
signal( SIGTERM, sigend );
- printf("Press ^C to exit demo\n");
+ printf( "Press ^C to exit demo\n" );
bool commonTest = true;
bool useGeneric = false;
- char *path = 0;
+ char* path = 0;
if ( argc >= 2 ) {
path = argv[1];
struct stat s;
- if( stat(path,&s) == 0 && (s.st_mode & S_IFDIR) == S_IFDIR ) {
+ if ( stat( path, &s ) == 0 && ( s.st_mode & S_IFDIR ) == S_IFDIR ) {
commonTest = false;
}
@@ -115,24 +114,25 @@ int main( int argc, char** argv ) {
if ( commonTest ) {
char cwd[256];
- getcwd( cwd, sizeof(cwd) );
+ getcwd( cwd, sizeof( cwd ) );
printf( "CurPath: %s\n", cwd );
/// starts watching
efsw_watch( fileWatcher );
/// add a watch to the system
- char path1[256];
- sprintf(path1, "%s%ctest", cwd, PATH_SEPARATOR );
- handleWatchID( efsw_addwatch_withoptions( fileWatcher, path1, handleFileAction, true, 0, 0, 0 ) );
+ char path1[512];
+ snprintf( path1, sizeof( path1 ), "%s%ctest", cwd, PATH_SEPARATOR );
+ handleWatchID( efsw_addwatch_withoptions( fileWatcher, path1, handleFileAction, true, 0, 0,
+ 0, NULL ) );
/// adds another watch after started watching...
sleepMsecs( 100 );
- char path2[256];
- sprintf(path2, "%s%ctest2", cwd, PATH_SEPARATOR );
- efsw_watchid watchID = handleWatchID(
- efsw_addwatch_withoptions( fileWatcher, path2, handleFileAction, true, 0, 0, 0 ) );
+ char path2[512];
+ snprintf( path2, sizeof( path2 ), "%s%ctest2", cwd, PATH_SEPARATOR );
+ efsw_watchid watchID = handleWatchID( efsw_addwatch_withoptions(
+ fileWatcher, path2, handleFileAction, true, 0, 0, 0, NULL ) );
/// delete the watch
if ( watchID > 0 ) {
@@ -159,6 +159,6 @@ int main( int argc, char** argv ) {
}
efsw_release( fileWatcher );
-
+
return 0;
}
diff --git a/dep/efsw/src/test/efsw-test.cpp b/dep/efsw/src/test/efsw-test.cpp
index d51d68d7599..bf1fc6481bf 100644
--- a/dep/efsw/src/test/efsw-test.cpp
+++ b/dep/efsw/src/test/efsw-test.cpp
@@ -99,7 +99,7 @@ int main( int argc, char** argv ) {
std::cout << "CurPath: " << CurPath.c_str() << std::endl;
- /// starts watching
+ /// starts watching
fileWatcher.watch();
/// add a watch to the system