views:

1500

answers:

3

There are a lot of programs, Visual Studio for instance, that can detect when an outside program modifies a file and then reload the file if the user wants chooses. Is there a relatively easy way to do this sort of thing in C++ (doesn't necessarily have to be platform independent)?

A: 

Sure, just like VC++ does. You get the last modified time when you open the file, and you periodically check it while you have the file open. If last_mod_time > saved_mod_time, it happened.

Charlie Martin
Polling is a very inefficient way to do this. As Alex noted, Windows does have notifications available (though of course I don't know if VS uses them).
Matthew Flaschen
@Matthew "Polling is a very inefficient way to do this." Nonsense. One stat(2) call every 5 minutes has epsilon impact. When you use the word "inefficient", quantify the time or cost it is, and compare that with the time you spend looking for "efficient" solutions. If, as in this case, the difference is on the order of 1e6, you're probably making a perverse optimization.
Charlie Martin
for checking a single file (as the original question mentions), polling is quick enough. if you want to act on any change on an unbounded-depth directory, it can quickly get out of hand.
Javier
One stat check per /file/. What if you want to monitor hundreds of files (not at all unreasonable for a dev working on a complex project) in a directory tree? As for time looking for the solution, it took me about 10 seconds to find the "Directory Change Notifications"/FindFirstChangeNotification API. So I don't think this is premature or perverse at all. I also don't think I need to give an exact cost when stating the obvious.
Matthew Flaschen
One variation on this that is possible is to only poll when the application gains focus. This works fine in the case that the file is only modified by the user. I'm not sure how much it costs to have a lot of simultaneous change registrations...and profiling it is not really possible, since such costs are continuous. I doubt it costs much, though. Even so, polling is not totally awful.
Brian
Gee, @Matthew, I wonder if anyone ever had to solve that problem before? But, real quick now, if a stat call takes 10 msec/file, amd you do it periodically, how many open files do you need to have before it consumes significant time. (Recall that a *closed* file never matters.) I get ROM 1000 files to consume 3 pct of the time. So, as to your other point, you're now concerned about optimizing a few tens of milliseconds for a wild edge case — even as wild an EMACS used as I am, I rarely have 50 files open, much less 1000. So yeah, I think a moment's estimation would have served you well.
Charlie Martin
In this particular case I'm doing this for a game (if you update the file that defines a stage for example, I want the stage to reload). Since even a frame of lag can be annoying I think I'll try to avoid polling (though I haven't had a chance to test either method yet, I'm going to default to the one that is likely faster). Thank you for the responses though.
Alex
+10  A: 

If you don't need to be platform-independent, an approach on Linux that may be less of a machine load than "polling" (checking periodically) is inotify, see http://en.wikipedia.org/wiki/Inotify and the many links from it for example. For Windows, see http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx .

Alex Martelli
Good answer! This really is an OS-level task that would be difficult to make cross-platform.
Justin Ethier
+11  A: 

There are several ways to do this depending on the platform. I would choose from the following choices:

Cross Platform

Trolltech's Qt has an object called QFileSystemWatcher which allows you to monitor files and directories. I'm sure there are other cross platform frameworks that give you this sort of capability too, but this one works fairly well in my experience.

Windows (Win32)

There is a Win32 api called FindFirstChangeNotification which does the job. There is a nice article which a small wrapper class for the api called How to get a notification if change occurs in a specified directory which will get you started.

Windows (.NET Framework)

Yes some people do use C++/CLI with the .NET Framework. System.IO.FileSystemWatcher is your class of choice. Microsoft has a nice article on how to monitor file system changes using this class.

OS X

The FSEvents API is new for OS X 10.5 and very full-featured.

Linux/UNIX

Use inotify as Alex mentioned in his answer.

Nick Haddad
Note: inotify is Linux specific, if you want some UNIX portable features you are pobably looking for something like libfam
Artyom
I think you're confusing C++ with C++/CLI. Similar name, different language. Other than that, this is a thorough and useful answer.
Matthew Flaschen