diff options
author | Brad King <brad.king@kitware.com> | 2004-11-03 12:23:18 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2004-11-03 12:23:18 (GMT) |
commit | d46d8df0edfcfac46390319db8213601a5cd4260 (patch) | |
tree | 86f2c559e3983463981ea30e59fa25193207dfb2 /Source/cmGeneratedFileStream.h | |
parent | 3050e231b35c7b8b3e1dfcc37275dddb3b5d7445 (diff) | |
download | CMake-d46d8df0edfcfac46390319db8213601a5cd4260.zip CMake-d46d8df0edfcfac46390319db8213601a5cd4260.tar.gz CMake-d46d8df0edfcfac46390319db8213601a5cd4260.tar.bz2 |
ENH: Re-implemented cmGeneratedFileStream to look like a real stream and replace the destination file atomically. This will avoid problems with the process being terminated while generating a file.
Diffstat (limited to 'Source/cmGeneratedFileStream.h')
-rw-r--r-- | Source/cmGeneratedFileStream.h | 155 |
1 files changed, 49 insertions, 106 deletions
diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h index 97ef705..b12461f 100644 --- a/Source/cmGeneratedFileStream.h +++ b/Source/cmGeneratedFileStream.h @@ -9,8 +9,8 @@ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ @@ -18,122 +18,65 @@ #define cmGeneratedFileStream_h #include "cmStandardIncludes.h" -#include "cmSystemTools.h" + +// This is the first base class of cmGeneratedFileStream. It will be +// created before and destroyed after the ofstream portion and can +// therefore be used to manage the temporary file. +class cmGeneratedFileStreamBase +{ +protected: + // The constructor prepares the temporary output file. + cmGeneratedFileStreamBase(const char* name, bool copy_if_different); + + // The destructor renames the temporary output file to the real name. + ~cmGeneratedFileStreamBase(); + + // Internal file replacement implementation. + int RenameFile(const char* oldname, const char* newname); + + // The name of the final destination file for the output. + std::string m_Name; + + // The name of the temporary file. + std::string m_TempName; + + // Whether to do a copy-if-different. + bool m_CopyIfDifferent; + + // Whether the destination file should be replaced. + bool m_Okay; +}; /** \class cmGeneratedFileStream - * \brief Output stream for generated files that does copy-if-different. + * \brief Output stream for generated files. * - * Many files generated by CMake don't change each time they are generated. - * This class can be used in place of std::ofstream to open a file and - * write output to it. The class will automatically write output to a - * temporary file and copy it over an existing file only if the generated - * file has changed. + * File generation should be atomic so that if CMake is killed then a + * generated file is either the original version or the complete new + * version. This stream is used to make sure file generation is + * atomic. Optionally the output file is only replaced if its + * contents have changed to prevent the file modification time from + * being updated. */ -class cmGeneratedFileStream +class cmGeneratedFileStream: private cmGeneratedFileStreamBase, + public std::ofstream { public: /** * The constructor takes the name of the file to be generated. It - * automatically generates a name for the temporary file. - */ - cmGeneratedFileStream(const char* name): - m_Name(name), - m_TempName(m_Name+".tmp"), - m_Stream(m_TempName.c_str()), - m_Copied(false), - m_AlwaysCopy(false) - {} - - /** - * The destructor ensures that the file has been closed and copied if - * it has changed. - */ - ~cmGeneratedFileStream() { this->DoCopy(); } - - /** - * Get the real output stream. + * automatically generates a name for the temporary file. The + * second argument specifies whether the copy-if-different check + * should be done. If the file cannot be opened an error message is + * produced unless the third argument is set to true. */ - std::ostream& GetStream() { return m_Stream; } - - /** - * Allow a test for whether the file is open. - */ - operator bool() { return m_Stream.good(); } - - /** - * Close the file stream. This will cause the copy-if-different to the - * real file name to occur. - */ - void close() { this->DoCopy(); } - /** - * If always copy is true, then copy the file all the time without - * checking for differences. The default is false. - */ - bool SetAlwaysCopy(bool v) { m_AlwaysCopy = v; return v;} -private: - /** - * The name of the real file where output will be copied if it has changed. - */ - std::string m_Name; - - /** - * The name of the temporary file. - */ - std::string m_TempName; - - /** - * The real output stream used to write to the file. - */ - std::ofstream m_Stream; - - /** - * Whether the temporary file has already been copied to the real file. - */ - bool m_Copied; + cmGeneratedFileStream(const char* name, bool copy_if_different, + bool quiet = false); /** - * If always copy is true, then copy the file all the time without - * checking for differences. The default is false. - */ - bool m_AlwaysCopy; - - /** - * Closes the temporary file and does the copy-if-different to the - * real file. + * The destructor checks the stream status to be sure the temporary + * file was successfully written before allowing the original to be + * replaced. */ - void DoCopy() - { - if(!m_Copied) - { - m_Stream.close(); - if(m_AlwaysCopy) - { - cmSystemTools::cmCopyFile(m_TempName.c_str(), m_Name.c_str()); - } - else - { - cmSystemTools::CopyFileIfDifferent(m_TempName.c_str(), - m_Name.c_str()); - } - cmSystemTools::RemoveFile(m_TempName.c_str()); - m_Copied = true; - } - } + ~cmGeneratedFileStream(); }; - -/** - * Allow a cmGeneratedFileStream to be used just as a real std::ostream - * would be. - */ -template <class T> -std::ostream& operator << (cmGeneratedFileStream& l, const T& r) -{ - std::ostream& os = l.GetStream(); - os << r; - return os; -} - - - #endif |