| Update of /cvsroot/sheepengine/sheep/src/common/misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31142/src/common/misc Modified Files: binarystream.cpp binarystream.h binarystream.inl config.h consoleprogressmonitor.cpp consoleprogressmonitor.h minmax.h misc.h pentiumrtsc.cpp pentiumrtsc.inl threadutils.cpp types.h Added Files: iprogressmonitor.cpp iprogressmonitor.h iprogressmonitor.inl stopwatch.cpp stopwatch.h stopwatch.inl Removed Files: progressmonitor.cpp progressmonitor.h progressmonitor.inl Log Message: dictoon's remaining changes : - htmlstream removed - ProgressMonitor renamed to IProgressMonitor - ConsoleProgressMonitor no longer single-line - misc const improvements - BinaryStream rewritten - Stopwatch class Index: config.h =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/config.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** config.h 13 May 2004 23:12:25 -0000 1.4 --- config.h 30 Oct 2004 15:55:07 -0000 1.5 *************** *** 24,36 **** #define SHEEP_MISC_CONFIG_H ! // --------------------------------------------------------------------------- // Microsoft Visual C++ 6.0 specifics. ! // --------------------------------------------------------------------------- #if _MSC_VER <= 1200 //! Disable C4786 warning message: ! //! 'identifier' : identifier was truncated to 'number' characters in the debug ! //! information. #pragma warning(disable : 4786) --- 24,36 ---- #define SHEEP_MISC_CONFIG_H ! // -------------------------------------------------------------------------- // Microsoft Visual C++ 6.0 specifics. ! // -------------------------------------------------------------------------- #if _MSC_VER <= 1200 //! Disable C4786 warning message: ! //! 'identifier' : identifier was truncated to 'number' characters in the ! //! debug information. #pragma warning(disable : 4786) *************** *** 38,44 **** #define for if(0) ; else for ! // --------------------------------------------------------------------------- // Microsoft Visual C++ 7.1 (Visual Studio 2003) specifics. ! // --------------------------------------------------------------------------- #elif _MSC_VER <= 1310 --- 38,44 ---- #define for if(0) ; else for ! // -------------------------------------------------------------------------- // Microsoft Visual C++ 7.1 (Visual Studio 2003) specifics. ! // -------------------------------------------------------------------------- #elif _MSC_VER <= 1310 --- progressmonitor.inl DELETED --- --- NEW FILE: iprogressmonitor.h --- /* Sheep - A Rigid Body Dynamics Engine Copyright (C) 2001-2004 Francois Beaune Contact: http://toxicengine.sourceforge.net/ This file is part of Sheep. Sheep is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Sheep is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Sheep; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SHEEP_MISC_IPROGRESSMONITOR_H #define SHEEP_MISC_IPROGRESSMONITOR_H #include "common/math/real.h" #include <cassert> #include <string> namespace sheep { class IProgressMonitor { public: //! Initializes the progress monitor by calling the Reset() method. IProgressMonitor(); virtual ~IProgressMonitor() {} //! Resets the progress monitor. virtual void Reset(); //! Starts a new job. Cumulated duration of all jobs must be equal //! to 1.0. Triggers the update callback. virtual void StartJob( Real range_min, Real range_max, Real duration = 1.0 ); //! Ends the current job. Triggers the update callback. virtual void EndJob(); //! This method must be called when all jobs are done. It calls //! EndJob() if necessary. Triggers the update callback. virtual void Done(); //! Changes the current message. void SetMessage(const std::string &message); //! Returns the current message. const std::string &GetMessage() const; //! Sets the current job's progress. 'progress' must lies in //! [range_min, range_max]. Triggers the update callback. void SetJobProgress(Real progress); //! Returns the total progress. This is the value that should be //! displayed. Real GetProgress() const; //! Returns true if all jobs are done, false otherwise. bool IsDone() const; //! Typically implemented using GetProgress(), IsDone() and //! GetMessage() methods. virtual void UpdateCallback() = 0; protected: Real m_job_start; //!< Start time of the current job. Real m_job_duration; //!< Duration of the current job. Real m_job_range_min; //!< Lower bound of current job range. Real m_job_range_max; //!< Upper bound of current job range. Real m_job_progress_scale; //!< m_job_duration / //! (m_job_range_max-m_job_range_min). bool m_job_done; //!< Is the current job done? std::string m_message; //!< Current message. Real m_progress; //!< Total progress. bool m_done; //!< Are all jobs done? Real m_last_update; //!< Time of the last update. }; #include "iprogressmonitor.inl" } #endif // !SHEEP_MISC_IPROGRESSMONITOR_H --- progressmonitor.cpp DELETED --- --- NEW FILE: iprogressmonitor.inl --- /* Sheep - A Rigid Body Dynamics Engine Copyright (C) 2001-2004 Francois Beaune Contact: http://toxicengine.sourceforge.net/ This file is part of Sheep. Sheep is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Sheep is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Sheep; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ inline const std::string &IProgressMonitor::GetMessage() const { return m_message; } inline void IProgressMonitor::SetJobProgress(Real progress) { assert(!m_job_done); assert(!m_done); assert(progress >= m_job_range_min); assert(progress <= m_job_range_max); m_progress = m_job_start + (progress - m_job_range_min) * m_job_progress_scale; UpdateCallback(); } inline Real IProgressMonitor::GetProgress() const { return m_progress; } inline bool IProgressMonitor::IsDone() const { return m_done; } Index: misc.h =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/misc.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** misc.h 13 May 2004 23:12:25 -0000 1.3 --- misc.h 30 Oct 2004 15:55:07 -0000 1.4 *************** *** 24,27 **** --- 24,28 ---- #define SHEEP_MISC_MISC_H + #include "apppath.h" #include "binarystream.h" #include "commandlineparser.h" *************** *** 30,33 **** --- 31,35 ---- #include "htmlstream.h" #include "iclonable.h" + #include "iprogressmonitor.h" #include "isingleton.h" #include "itask.h" *************** *** 36,42 **** #include "pentiumrtsc.h" #endif // _MSC_VER ! #include "progressmonitor.h" #include "stringutils.h" #include "taskmanager.h" #include "types.h" #include "xercesmanager.h" --- 38,45 ---- #include "pentiumrtsc.h" #endif // _MSC_VER ! #include "stopwatch.h" #include "stringutils.h" #include "taskmanager.h" + #include "threadutils.h" #include "types.h" #include "xercesmanager.h" Index: binarystream.cpp =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/binarystream.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** binarystream.cpp 13 May 2004 23:12:25 -0000 1.5 --- binarystream.cpp 30 Oct 2004 15:55:07 -0000 1.6 *************** *** 23,27 **** #include "binarystream.h" // include first ! #include <algorithm> // std::min<>() using namespace sheep; --- 23,34 ---- #include "binarystream.h" // include first ! #include "common/misc/minmax.h" ! ! //#define VERBOSE ! ! #ifdef VERBOSE ! #include <iomanip> ! #include <iostream> ! #endif // VERBOSE using namespace sheep; *************** *** 29,33 **** //! Default buffer size, in bytes. ! const int DEFAULT_BUFFER_SIZE = 65536; BinaryStream::BinaryStream() { --- 36,40 ---- //! Default buffer size, in bytes. ! const int DefaultBufferSize = 65536; BinaryStream::BinaryStream() { *************** *** 35,39 **** } ! BinaryStream::BinaryStream(const std::string &filename, StreamMode mode, Endianness endianness /*= NativeEndian*/) --- 42,46 ---- } ! BinaryStream::BinaryStream(const string &filename, StreamMode mode, Endianness endianness /*= NativeEndian*/) *************** *** 47,51 **** } ! void BinaryStream::Open(const std::string &filename, StreamMode mode, Endianness endianness /*= NativeEndian*/) --- 54,58 ---- } ! void BinaryStream::Open(const string &filename, StreamMode mode, Endianness endianness /*= NativeEndian*/) *************** *** 55,75 **** m_mode = mode; ! if(mode == InputStream) m_file = fopen(filename.c_str(), "rb"); else m_file = fopen(filename.c_str(), "wb"); SetEndianness(endianness); ! SetBufferSize(DEFAULT_BUFFER_SIZE); } ! void BinaryStream::Close() throw(WriteException) { if(m_file) { if(m_mode == OutputStream) flush_output_buffer(); fclose(m_file); m_file = 0; ! delete m_buffer_base; m_buffer_base = 0; } --- 62,97 ---- m_mode = mode; ! if(m_mode == InputStream) m_file = fopen(filename.c_str(), "rb"); else m_file = fopen(filename.c_str(), "wb"); + /* if(m_file == 0) { + if(m_mode == InputStream) + throw FileOpenException(); + else throw FileCreateException(); + }*/ + SetEndianness(endianness); ! SetBufferSize(DefaultBufferSize); ! ! m_file_pos = 0; ! m_buffer_file_pos = 0; } ! void BinaryStream::Close() ! throw(WriteException) ! { if(m_file) { + // In output mode, write pending buffered data to disk + // before closing the file. if(m_mode == OutputStream) flush_output_buffer(); + // Close the file. fclose(m_file); m_file = 0; ! // Deallocate the input/output buffer. ! delete[] m_buffer_base; m_buffer_base = 0; } *************** *** 83,96 **** assert(size > 0); ! delete m_buffer_base; ! m_buffer_base = new char[size]; ! if(m_mode == InputStream) ! m_buffer_end = m_buffer_base; ! else m_buffer_end = m_buffer_base + size; m_buffer_ptr = m_buffer_base; ! m_buffer_size = size; } --- 105,125 ---- assert(size > 0); ! // Delete the buffer and reallocate it with the new size. ! // The content of the buffer is lost. ! delete[] m_buffer_base; m_buffer_base = new char[size]; ! // Save the buffer size. ! m_buffer_size = size; + // Rewind to the beginning of the buffer. m_buffer_ptr = m_buffer_base; ! ! // Empty the buffer. ! m_buffer_end = m_buffer_base; ! } ! ! int BinaryStream::GetBufferSize() const { ! return m_buffer_size; } *************** *** 101,139 **** } ! void BinaryStream::Seek(long offset, SeekOrigin origin) throw(SeekException) { assert(m_file); - assert(m_mode == InputStream); assert(m_buffer_base); switch(origin) { case SeekFromBeginning: ! fseek(m_file, offset, SEEK_SET); break; case SeekFromCurrent: ! fseek(m_file, offset, SEEK_CUR); ! break; ! case SeekFromEnd: ! fseek(m_file, offset, SEEK_END); break; } ! if(ferror(m_file)) ! throw SeekException(); ! invalidate_input_buffer(); } ! long BinaryStream::Tell() const throw(SeekException) { assert(m_file); ! const long position = ftell(m_file); ! ! if(ferror(m_file)) ! throw SeekException(); ! return position; } ! void BinaryStream::Write(const void *data, size_t size) throw(WriteException) { assert(m_file); assert(m_mode == OutputStream); --- 130,223 ---- } ! void BinaryStream::Seek(int64 offset, SeekOrigin origin) ! throw(SeekException) ! { assert(m_file); assert(m_buffer_base); + int64 buffer_position; + switch(origin) { case SeekFromBeginning: ! buffer_position = offset - m_buffer_file_pos; break; case SeekFromCurrent: ! buffer_position = ! m_buffer_file_pos + offset + ! static_cast<int64>(m_buffer_ptr - m_buffer_base); break; + default:; } ! if(origin == SeekFromEnd || ! buffer_position < 0 || ! buffer_position > static_cast<int64>(m_buffer_end - m_buffer_base)) ! { ! // Seeking outside of the buffer bounds, or seeking using ! // SeekFromEnd mode. ! int64 buffer_offset; // used only when origin is SeekFromCurrent ! ! if(m_mode == InputStream) { ! // Compute the offset due to input buffering. ! buffer_offset = ! static_cast<int64>(m_buffer_ptr - m_buffer_base); ! // Invalidate the input buffer. ! invalidate_input_buffer(); ! } else { ! assert(m_mode == OutputStream); ! // No offset due to output buffering. ! buffer_offset = 0; ! // Flush the output buffer to disk. ! flush_output_buffer(); ! } ! ! // Move the file pointer to the specified position. ! switch(origin) { ! case SeekFromBeginning: ! fseek(m_file, static_cast<long>(offset), SEEK_SET); ! m_file_pos = offset; ! break; ! case SeekFromCurrent: ! // This is a relative move: take into account the offset in the ! // input buffer. ! fseek(m_file, static_cast<long>(offset + buffer_offset), ! SEEK_CUR); ! m_file_pos += offset; ! break; ! case SeekFromEnd: ! fseek(m_file, static_cast<long>(offset), SEEK_END); ! m_file_pos = ftell(m_file); ! break; ! } ! ! // Throw an exception if an error occured. ! if(ferror(m_file)) ! throw SeekException(); ! ! m_buffer_file_pos = m_file_pos; ! } else { ! // Seeking inside the buffer bounds. ! m_buffer_ptr = m_buffer_base + buffer_position; ! } } ! int64 BinaryStream::Tell() const ! throw(SeekException) ! { assert(m_file); + assert(m_buffer_base); ! // Compute the offset due to input/output buffering. ! const int64 buffer_offset = ! static_cast<int64>(m_buffer_ptr - m_buffer_base); ! assert(buffer_offset >= 0); ! return m_buffer_file_pos + buffer_offset; } ! void BinaryStream::Write(const void *data, int size) ! throw(WriteException) ! { assert(m_file); assert(m_mode == OutputStream); *************** *** 146,162 **** while(size > 0) { ! // Calculate space available in the output buffer. ! const size_t room = m_buffer_end - m_buffer_ptr; ! assert(room >= 0); ! // Flush the output buffer if full. ! if(room == 0) flush_output_buffer(); ! // Compute the amount of data to copy. ! const size_t block_size = min(size, room); assert(block_size > 0); ! // Append data to the output buffer. memcpy(m_buffer_ptr, data_ptr, block_size); --- 230,252 ---- while(size > 0) { ! // Compute available space in the output buffer. ! int space = m_buffer_size - ! static_cast<int>(m_buffer_ptr - m_buffer_base); ! assert(space >= 0); ! // The output buffer is full. ! if(space == 0) { ! // Flush it to disk and empty it. flush_output_buffer(); ! // Recompute available space in the output buffer. ! space = m_buffer_size; ! } ! ! // Compute the number of bytes to copy. ! const int block_size = min(size, space); assert(block_size > 0); ! // Copy data to the output buffer. memcpy(m_buffer_ptr, data_ptr, block_size); *************** *** 165,174 **** m_buffer_ptr += block_size; ! // Compute the amount of data that remains to copy. size -= block_size; } } ! void BinaryStream::Read(void *data, size_t size) throw(ReadException) { assert(m_file); assert(m_mode == InputStream); --- 255,270 ---- m_buffer_ptr += block_size; ! // Adjust buffer end pointer. ! if(m_buffer_ptr > m_buffer_end) ! m_buffer_end = m_buffer_ptr; ! ! // Compute the number of bytes that remains to copy. size -= block_size; } } ! void BinaryStream::Read(void *data, int size) ! throw(ReadException, EOFException) ! { assert(m_file); assert(m_mode == InputStream); *************** *** 181,202 **** while(size > 0) { ! // Compute the amount of data available in the input buffer. ! size_t remaining = m_buffer_end - m_buffer_ptr; ! assert(remaining >= 0); ! // Fill the input buffer if empty. ! if(remaining == 0) { ! remaining = fill_input_buffer(); ! // Error: no more data. ! if(remaining == 0) ! throw ReadException(); } ! // Compute the amount of data to copy. ! const size_t block_size = min(size, remaining); assert(block_size > 0); ! // Copy data from buffer. memcpy(data_ptr, m_buffer_ptr, block_size); --- 277,301 ---- while(size > 0) { ! // Compute the number of bytes available in the input buffer. ! int available = static_cast<int>(m_buffer_end - m_buffer_ptr); ! assert(available >= 0); ! // The input buffer is empty. ! if(available == 0) { ! // Load data from disk. ! available = fill_input_buffer(); ! // Reached end of file. ! if(available == 0) ! throw EOFException(); ! ! assert(available > 0); } ! // Compute the number of bytes to copy. ! const int block_size = min(size, available); assert(block_size > 0); ! // Copy data from the input buffer. memcpy(data_ptr, m_buffer_ptr, block_size); *************** *** 205,209 **** m_buffer_ptr += block_size; ! // Compute the amount of data that remains to copy. size -= block_size; } --- 304,373 ---- m_buffer_ptr += block_size; ! // Compute the number of bytes that remains to copy. ! size -= block_size; ! } ! } ! ! void BinaryStream::CopyTo(BinaryStream *dest, int size) ! throw(ReadException, WriteException) ! { ! assert(m_file); ! assert(m_mode == InputStream); ! assert(m_buffer_base); ! ! assert(dest); ! assert(dest->m_file); ! assert(dest->m_mode == OutputStream); ! assert(dest->m_buffer_base); ! ! assert(size >= 0); ! ! while(size > 0) { ! // Compute the number of bytes available in the input buffer. ! int in_available = static_cast<int>(m_buffer_end - m_buffer_ptr); ! assert(in_available >= 0); ! ! // The input buffer is empty. ! if(in_available == 0) { ! // Load data from disk. ! in_available = fill_input_buffer(); ! ! // Reached end of file. ! if(in_available == 0) ! throw EOFException(); ! ! assert(in_available > 0); ! } ! ! // Compute available space in the output buffer. ! int out_space = dest->m_buffer_size - ! static_cast<int>(dest->m_buffer_ptr - dest->m_buffer_base); ! assert(out_space >= 0); ! ! // The output buffer is full. ! if(out_space == 0) { ! // Flush it to disk and empty it. ! dest->flush_output_buffer(); ! ! // Recompute available space in the output buffer. ! out_space = dest->m_buffer_size; ! } ! ! // Compute the number of bytes to copy. ! const int block_size = min(size, in_available, out_space); ! assert(block_size > 0); ! ! // Copy data from the input buffer to the output buffer. ! memcpy(dest->m_buffer_ptr, m_buffer_ptr, block_size); ! ! // Advance source and destination pointers. ! dest->m_buffer_ptr += block_size; ! m_buffer_ptr += block_size; ! ! // Adjust output buffer end pointer. ! if(dest->m_buffer_ptr > dest->m_buffer_end) ! dest->m_buffer_end = dest->m_buffer_ptr; ! ! // Compute the number of bytes that remains to copy. size -= block_size; } *************** *** 213,217 **** const long x = 1; const char *p = reinterpret_cast<const char *>(&x); - return *p ? LittleEndian : BigEndian; } --- 377,380 ---- *************** *** 221,264 **** m_mode = InputStream; // arbitrary m_swap = false; ! m_buffer_base = m_buffer_end = 0; ! m_buffer_ptr = 0; m_buffer_size = 0; } ! void BinaryStream::flush_output_buffer() throw(WriteException) { assert(m_file); assert(m_mode == OutputStream); assert(m_buffer_base); ! const size_t block_size = m_buffer_ptr - m_buffer_base; assert(block_size >= 0); ! const size_t written = ! fwrite(m_buffer_base, 1, block_size, m_file); if(written < block_size || ferror(m_file)) throw WriteException(); m_buffer_ptr = m_buffer_base; } ! size_t BinaryStream::fill_input_buffer() throw(ReadException) { assert(m_file); assert(m_mode == InputStream); assert(m_buffer_base); ! const size_t read = ! fread(m_buffer_base, 1, m_buffer_size, m_file); if(ferror(m_file)) throw ReadException(); m_buffer_ptr = m_buffer_base; m_buffer_end = m_buffer_base + read; return read; } void BinaryStream::invalidate_input_buffer() { m_buffer_end = m_buffer_base; } --- 384,491 ---- m_mode = InputStream; // arbitrary m_swap = false; ! m_buffer_base = 0; m_buffer_size = 0; + m_buffer_end = 0; + m_buffer_ptr = 0; + m_file_pos = 0; + m_buffer_file_pos = 0; } ! void BinaryStream::flush_output_buffer() ! throw(WriteException) ! { assert(m_file); assert(m_mode == OutputStream); assert(m_buffer_base); ! // Compute the number of bytes the output buffer contains. ! const int block_size = ! static_cast<int>(m_buffer_end - m_buffer_base); assert(block_size >= 0); ! // The output buffer is empty: exit. ! if(block_size == 0) ! return; + // Write the output buffer to disk. + const int written = + static_cast<int>(fwrite(m_buffer_base, 1, block_size, m_file)); + + // Throw an exception if a write error occured. if(written < block_size || ferror(m_file)) throw WriteException(); + // Rewind to the beginning of the output buffer. m_buffer_ptr = m_buffer_base; + + // Empty the output buffer. + m_buffer_end = m_buffer_base; + + // Compute the new position of the buffer in the file. + m_buffer_file_pos += written; + + // Update file current position. + m_file_pos += written; } ! int BinaryStream::fill_input_buffer() ! throw(ReadException) ! { assert(m_file); assert(m_mode == InputStream); assert(m_buffer_base); ! #ifdef VERBOSE ! const double used = static_cast<double>(m_buffer_ptr - m_buffer_base); ! cerr << fixed << setprecision(2); ! cerr << "fill_input_buffer: efficiency=" ! << used / m_buffer_size * 100.0 ! << "%, calling fread: "; ! #endif // VERBOSE ! ! // Load data from disk into the input buffer. ! const int read = ! static_cast<int>(fread(m_buffer_base, 1, m_buffer_size, m_file)); + #ifdef VERBOSE + cerr << "ok" << endl; + #endif // VERBOSE + + // Throw an exception if a read error occured. if(ferror(m_file)) throw ReadException(); + // Rewind to the beginning of the input buffer. m_buffer_ptr = m_buffer_base; + + // Figure out the upper bound of the input buffer. m_buffer_end = m_buffer_base + read; + // Compute the new position of the buffer in the file. + m_buffer_file_pos = m_file_pos; + + // Update file current position. + m_file_pos += read; + + // Return the number of bytes loaded into the input buffer. return read; } void BinaryStream::invalidate_input_buffer() { + assert(m_mode == InputStream); + assert(m_buffer_base); + + #ifdef VERBOSE + const double used = static_cast<double>(m_buffer_ptr - m_buffer_base); + cerr << fixed << setprecision(2); + cerr << "invalidate_input_buffer: efficiency=" + << used / m_buffer_size * 100.0 + << "%" << endl; + #endif // VERBOSE + + // Rewind to the beginning of the input buffer. + m_buffer_ptr = m_buffer_base; + + // Empty the input buffer. m_buffer_end = m_buffer_base; } --- progressmonitor.h DELETED --- Index: pentiumrtsc.cpp =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/pentiumrtsc.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** pentiumrtsc.cpp 13 May 2004 23:12:25 -0000 1.3 --- pentiumrtsc.cpp 30 Oct 2004 15:55:07 -0000 1.4 *************** *** 47,55 **** int64 PentiumRTSC::GetResult() const { ! int64 result = (static_cast<int64>(m_stop_h - m_start_h) << 32) + static_cast<int64>(m_stop_l - m_start_l); ! return result - m_overhead; } --- 47,57 ---- int64 PentiumRTSC::GetResult() const { ! const int64 elapsed = (static_cast<int64>(m_stop_h - m_start_h) << 32) + static_cast<int64>(m_stop_l - m_start_l); ! const int64 result = elapsed - m_overhead; ! ! return result < 0 ? 0 : result; } Index: types.h =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/types.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** types.h 13 May 2004 23:12:25 -0000 1.3 --- types.h 30 Oct 2004 15:55:07 -0000 1.4 *************** *** 58,67 **** } ! #if defined _MSC_VER && _MSC_VER <= 1200 //!< 1200 == VC++ 6.0 #include <iostream> //! Microsoft Visual C++ (R) 6.0 and previous releases lack ! //! the << operator for the 64-bit integer type. std::ostream &operator<<(std::ostream &os, int64 i); --- 58,68 ---- } ! //!< 1200 == Microsoft Visual C++ 6.0 ! #if _MSC_VER <= 1200 #include <iostream> //! Microsoft Visual C++ (R) 6.0 and previous releases lack ! //! the << operator for 64-bit integers. std::ostream &operator<<(std::ostream &os, int64 i); --- NEW FILE: iprogressmonitor.cpp --- /* Sheep - A Rigid Body Dynamics Engine Copyright (C) 2001-2004 Francois Beaune Contact: http://toxicengine.sourceforge.net/ This file is part of Sheep. Sheep is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Sheep is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Sheep; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "iprogressmonitor.h" // include first //#include <> using namespace sheep; IProgressMonitor::IProgressMonitor() { Reset(); } void IProgressMonitor::Reset() { // The following members are set when a job starts: // m_job_start, m_job_duration, m_job_range_min, m_job_range_max, // m_job_progress_scale. m_job_done = true; m_message.erase(); m_progress = 0.0; m_done = false; m_last_update = -2.0; // trigger the update callback } void IProgressMonitor::StartJob(Real range_min, Real range_max, Real duration /*= 1.0*/) { assert(m_job_done); assert(!m_done); assert(m_progress < 1.0); m_job_start = m_progress; assert(duration > 0.0); assert(m_job_start + duration <= 1.0); m_job_duration = duration; assert(range_min < range_max); m_job_range_min = range_min; m_job_range_max = range_max; m_job_progress_scale = m_job_duration / (m_job_range_max - m_job_range_min); m_job_done = false; UpdateCallback(); } void IProgressMonitor::EndJob() { assert(!m_job_done); m_progress = m_job_start + m_job_duration; m_job_done = true; UpdateCallback(); } void IProgressMonitor::Done() { assert(!m_done); if(!m_job_done) EndJob(); assert(m_job_done); m_progress = 1.0; m_done = true; UpdateCallback(); } void IProgressMonitor::SetMessage(const std::string &message) { m_message = message; } --- NEW FILE: stopwatch.h --- /* Sheep - A Rigid Body Dynamics Engine Copyright (C) 2001-2004 Francois Beaune Contact: be...@ai... This file is part of Sheep. Sheep is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Sheep is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Sheep; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SHEEP_MISC_STOPWATCH_H #define SHEEP_MISC_STOPWATCH_H #include "config.h" #include <ctime> #include <string> namespace sheep { //! A very simple stopwatch with a resolution of 1 second. class Stopwatch { public: Stopwatch(); //! Starts the stopwatch, and returns the start time in seconds. time_t Start(); //! Stops the stopwatch, and returns the stop time in seconds. time_t Stop(); //! Returns true if the stopwatch is running, or false otherwise. bool IsRunning() const; //! Returns the elapsed time in seconds. This method can be called //! either while the stopwatch is running, or after the stopwatch //! has been stopped. time_t GetElapsedTime() const; //! Expresses the time t as a human-readable string. t must be //! expressed in seconds. static std::string FormatTime(time_t t); private: bool m_running; //!< True if the stopwatch is running. time_t m_start_time; //!< Start time. time_t m_stop_time; //!< Stop time. }; #include "stopwatch.inl" } #endif // !SHEEP_MISC_STOPWATCH_H Index: threadutils.cpp =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/threadutils.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** threadutils.cpp 2 Jun 2004 10:46:14 -0000 1.2 --- threadutils.cpp 30 Oct 2004 15:55:07 -0000 1.3 *************** *** 65,70 **** mutex::scoped_lock lock(m_mutex); ! for(thread_job_deque::const_iterator i = m_queue.begin(), e = m_queue.end(); ! i != e; ++i) { delete *i; --- 65,70 ---- mutex::scoped_lock lock(m_mutex); ! for(thread_job_deque::const_iterator i = m_queue.begin(), ! e = m_queue.end(); i != e; ++i) { delete *i; Index: binarystream.inl =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/binarystream.inl,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** binarystream.inl 13 May 2004 23:12:25 -0000 1.5 --- binarystream.inl 30 Oct 2004 15:55:07 -0000 1.6 *************** *** 22,26 **** template<typename T> inline ! void BinaryStream::Write(T t) throw(WriteException) { if(m_swap && sizeof(T) > 1) swap_bytes(&t); --- 22,28 ---- template<typename T> inline ! void BinaryStream::Write(T t) ! throw(WriteException) ! { if(m_swap && sizeof(T) > 1) swap_bytes(&t); *************** *** 30,34 **** template<typename T> inline ! void BinaryStream::Read(T *t) throw(ReadException) { assert(t); --- 32,58 ---- template<typename T> inline ! void BinaryStream::WriteArray(T *t, int n) ! throw(WriteException) ! { ! assert(t); ! assert(n >= 0); ! ! if(m_swap && sizeof(T) > 1) { ! // Swap individual elements, starting at the end ! // of the array. This modifies the original data. ! T *p = t + n - 1; ! while(p >= t) { ! swap_bytes(p); ! --p; ! } ! } ! ! Write(reinterpret_cast<char *>(t), n * sizeof(T)); ! } ! ! template<typename T> inline ! void BinaryStream::Read(T *t) ! throw(ReadException) ! { assert(t); *************** *** 40,43 **** --- 64,87 ---- template<typename T> inline + void BinaryStream::ReadArray(T *t, int n) + throw(ReadException) + { + assert(t); + assert(n >= 0); + + Read(reinterpret_cast<char *>(t), n * sizeof(T)); + + if(m_swap && sizeof(T) > 1) { + // Swap individual elements, starting at the end + // of the array. + T *p = t + n - 1; + while(p >= t) { + swap_bytes(p); + --p; + } + } + } + + template<typename T> inline void BinaryStream::swap_bytes(T *t) const { assert(t); *************** *** 49,53 **** char *ca = reinterpret_cast<char *>(t); ! // Swap individual bytes by value. std::reverse(ca, ca + sizeof(T)); } --- 93,97 ---- char *ca = reinterpret_cast<char *>(t); ! // Swap individual bytes. std::reverse(ca, ca + sizeof(T)); } Index: binarystream.h =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/binarystream.h,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** binarystream.h 13 May 2004 23:12:25 -0000 1.5 --- binarystream.h 30 Oct 2004 15:55:07 -0000 1.6 *************** *** 24,30 **** #define SHEEP_MISC_BINARYSTREAM_H ! #include "config.h" ! #include <algorithm> // std::reverse<>() #include <cassert> #include <cstddef> --- 24,30 ---- #define SHEEP_MISC_BINARYSTREAM_H ! #include "types.h" ! #include <algorithm> #include <cassert> #include <cstddef> *************** *** 38,44 **** --- 38,49 ---- struct BaseException {}; struct ReadException : public BaseException {}; + struct EOFException : public ReadException {}; //!< End of file. struct WriteException : public BaseException {}; struct SeekException : public BaseException {}; + //! The two following exceptions are currently unused. + struct FileCreateException : public BaseException {}; //!< When opening in output mode. + struct FileOpenException : public BaseException {}; //!< When opening in input mode. + enum StreamMode { InputStream, *************** *** 53,56 **** --- 58,63 ---- BinaryStream(); + + //! Use IsOpen() to test whether the file has been open/created successfully. BinaryStream( const std::string &filename, *************** *** 59,64 **** --- 66,73 ---- ); + //! The stream is closed at destruction. ~BinaryStream(); + //! Use IsOpen() to test whether the file has been open/created successfully. void Open( const std::string &filename, *************** *** 76,79 **** --- 85,89 ---- //! called before using the stream. void SetBufferSize(int size); + int GetBufferSize() const; void SetEndianness(Endianness endianness); *************** *** 85,103 **** }; ! void Seek(long offset, SeekOrigin origin) throw(SeekException); ! long Tell() const throw(SeekException); //! Writes a sequence of contiguous bytes to the stream. //! No byte reordering is performed. ! void Write(const void *data, size_t size) throw(WriteException); //! Reads a sequence of contiguous bytes from the stream. //! No byte reordering is performed. ! void Read(void *data, size_t size) ! throw(ReadException); template<typename T> --- 95,113 ---- }; ! void Seek(int64 offset, SeekOrigin origin) throw(SeekException); ! int64 Tell() const throw(SeekException); //! Writes a sequence of contiguous bytes to the stream. //! No byte reordering is performed. ! void Write(const void *data, int size) throw(WriteException); //! Reads a sequence of contiguous bytes from the stream. //! No byte reordering is performed. ! void Read(void *data, int size) ! throw(ReadException, EOFException); template<typename T> *************** *** 105,120 **** throw(WriteException); template<typename T> void Read(T *t) throw(ReadException); private: ! FILE *m_file; //!< The file to which is binded the stream. ! StreamMode m_mode; //!< Stream mode (input or output). ! bool m_swap; //!< True if bytes must be swapped (if host and target endianness differ). ! char *m_buffer_base; //!< Base address of the buffer. ! char *m_buffer_end; //!< In InputStream mode: one byte past the end of the data. In OutputStream mode: one byte past the end of the buffer. ! char *m_buffer_ptr; //!< Current location in the buffer (points to the next byte to read/write). ! int m_buffer_size; //!< Total size of the buffer. Endianness get_host_endianness() const; --- 115,165 ---- throw(WriteException); + //! Warning: this method swaps bytes of the original data + //! if byte swapping is enabled! + template<typename T> + void WriteArray(T *t, int n) + throw(WriteException); + template<typename T> void Read(T *t) throw(ReadException); + template<typename T> + void ReadArray(T *t, int n) + throw(ReadException); + + void CopyTo(BinaryStream *dest, int size) + throw(ReadException, WriteException); + private: ! //! File to which is binded the stream. ! FILE *m_file; ! ! //! Operation mode (input or output). ! StreamMode m_mode; ! ! //! True if bytes must be swapped (if host and target ! //! endianness differ). ! bool m_swap; ! ! //! Base address of the buffer. Set once, when the buffer ! //! is (re)allocated. ! char *m_buffer_base; ! ! //! Total size of the buffer. Set once, when the buffer ! //! is (re)allocated. ! int m_buffer_size; ! ! //! Pointer to the last byte of data in the buffer. ! char *m_buffer_end; ! ! //! Pointer to the next byte to read/write from/to the buffer. ! char *m_buffer_ptr; ! ! //! Current position in the file. ! int64 m_file_pos; ! ! //!< Position in the file of the first byte of the buffer. ! int64 m_buffer_file_pos; Endianness get_host_endianness() const; *************** *** 125,129 **** throw(WriteException); ! size_t fill_input_buffer() throw(ReadException); --- 170,174 ---- throw(WriteException); ! int fill_input_buffer() throw(ReadException); Index: pentiumrtsc.inl =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/pentiumrtsc.inl,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** pentiumrtsc.inl 13 May 2004 23:12:25 -0000 1.3 --- pentiumrtsc.inl 30 Oct 2004 15:55:07 -0000 1.4 *************** *** 65,69 **** uint32 h, l; ! asm volatile ("cpuid;\ rdtsc;\ mov %%edx, %0;\ --- 65,69 ---- uint32 h, l; ! asm volatile ("cpuid; /* force the in-order execution of the RDTSC instruction. */ \ rdtsc;\ mov %%edx, %0;\ *************** *** 75,79 **** } ! inline void PentiumRTSC::Stop() { uint32 h, l; --- 75,80 ---- } ! inline ! void PentiumRTSC::Stop() { uint32 h, l; --- NEW FILE: stopwatch.cpp --- /* Sheep - A Rigid Body Dynamics Engine Copyright (C) 2001-2004 Francois Beaune Contact: be...@ai... This file is part of Sheep. Sheep is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Sheep is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Sheep; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stopwatch.h" // include first #include <cassert> #include <sstream> using namespace sheep; using namespace std; Stopwatch::Stopwatch() : m_running(false), m_start_time(0), m_stop_time(0) { } time_t Stopwatch::Start() { assert(!m_running); m_running = true; m_start_time = time(0); return m_start_time; } time_t Stopwatch::Stop() { assert(m_running); m_stop_time = time(0); m_running = false; assert(m_stop_time >= m_start_time); return m_stop_time; } namespace { string format_value(time_t value, const string &unit) { stringstream ss; ss << value << ' ' << unit; if(value > 1) ss << 's'; return ss.str(); } } string Stopwatch::FormatTime(time_t t) { if(t < 1) return "less than a second"; else { // Everything is expressed in seconds. const int MIN = 60; const int HOUR = 60 * MIN; const int DAY = 24 * HOUR; // Compute the number of days. time_t d = t / DAY; t %= DAY; // Compute the number of hours. time_t h = t / HOUR; t %= HOUR; // Compute the number of minutes. time_t m = t / MIN; // Compute the number of seconds. time_t s = t % MIN; // Express t as a human-readable string. string result = format_value(s, "second"); if(m > 0) result = format_value(m, "minute") + " " + result; if(h > 0) result = format_value(h, "hour") + " " + result; if(d > 0) result = format_value(d, "day") + " " + result; return result; } } Index: minmax.h =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/minmax.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** minmax.h 13 May 2004 23:12:25 -0000 1.2 --- minmax.h 30 Oct 2004 15:55:07 -0000 1.3 *************** *** 30,38 **** namespace sheep { ! // For two arguments min and max, use std::min<>() and std::max<>() functions from the STL. template<typename T> const T &min(const T &a, const T &b, const T &c); template<typename T> const T &max(const T &a, const T &b, const T &c); --- 30,42 ---- namespace sheep { ! // Import two arguments min and max functions from the STL. ! using std::min; ! using std::max; + // Three arguments min function. template<typename T> const T &min(const T &a, const T &b, const T &c); + // Three arguments max function. template<typename T> const T &max(const T &a, const T &b, const T &c); --- NEW FILE: stopwatch.inl --- /* Sheep - A Rigid Body Dynamics Engine Copyright (C) 2001-2004 Francois Beaune Contact: be...@ai... This file is part of Sheep. Sheep is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Sheep is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Sheep; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ inline bool Stopwatch::IsRunning() const { return m_running; } inline time_t Stopwatch::GetElapsedTime() const { if(m_running) return time(0) - m_start_time; else return m_stop_time - m_start_time; } Index: consoleprogressmonitor.h =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/consoleprogressmonitor.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** consoleprogressmonitor.h 18 May 2004 00:31:56 -0000 1.4 --- consoleprogressmonitor.h 30 Oct 2004 15:55:07 -0000 1.5 *************** *** 24,28 **** #define SHEEP_MISC_CONSOLEPROGRESSMONITOR_H ! #include "progressmonitor.h" #include <ctime> --- 24,31 ---- #define SHEEP_MISC_CONSOLEPROGRESSMONITOR_H ! #include "iprogressmonitor.h" ! #include "stopwatch.h" ! ! #include "common/math/real.h" #include <ctime> *************** *** 31,39 **** namespace sheep { ! class ConsoleProgressMonitor : public ProgressMonitor { public: ConsoleProgressMonitor(); ! void Reset(const std::string &message); void SetPrecision(int digits); --- 34,53 ---- namespace sheep { ! class ConsoleProgressMonitor : public IProgressMonitor { public: ConsoleProgressMonitor(); ! virtual void Reset(const std::string &message); ! ! virtual void StartJob( ! Real range_min, ! Real range_max, ! Real duration = 1.0 ! ); ! ! virtual void Done(); ! ! //! Sets the number of digits to display after the decimal point. ! //! Default value is 2 (xx.xx %). void SetPrecision(int digits); *************** *** 41,46 **** private: ! int m_digits; //!< Output precision. ! time_t m_start_time; //!< Start time of the first job. }; --- 55,61 ---- private: ! int m_digits; //!< Output precision. ! Stopwatch m_stopwatch; //!< Stopwatch to measure jobs duration. ! time_t m_last_update_time; //!< Time of the last update. }; Index: consoleprogressmonitor.cpp =================================================================== RCS file: /cvsroot/sheepengine/sheep/src/common/misc/consoleprogressmonitor.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** consoleprogressmonitor.cpp 18 May 2004 00:31:56 -0000 1.4 --- consoleprogressmonitor.cpp 30 Oct 2004 15:55:07 -0000 1.5 *************** *** 22,114 **** #include "consoleprogressmonitor.h" // include first - #include "types.h" ! #include <iomanip> // std::setprecision() #include <iostream> - #include <sstream> using namespace sheep; using namespace std; ConsoleProgressMonitor::ConsoleProgressMonitor() : ! m_digits(0), ! m_start_time(0) { } void ConsoleProgressMonitor::Reset(const string &message) { ! ProgressMonitor::Reset(); ! ! SetMessage(message); ! m_start_time = time(0); ! } ! void ConsoleProgressMonitor::SetPrecision(int digits) { ! m_digits = digits; } ! namespace { ! string format_value(time_t value, const string &unit) { ! stringstream ss; ! ! ss << value << ' ' << unit; ! ! if(value > 1) ! ss << 's'; ! ! return ss.str(); ! } ! ! // t is expressed in seconds. ! string format_time(time_t t) { ! if(t < 1) ! return "less than a second"; ! else { ! // Unit is the second. ! const int MIN = 60; ! const int HOUR = 60 * MIN; ! const int DAY = 24 * HOUR; ! ! time_t d = t / DAY; ! t %= DAY; ! ! time_t h = t / HOUR; ! t %= HOUR; ! time_t m = t / MIN; ! time_t s = t % MIN; ! string result = format_value(s, "second"); ! if(m > 0) ! result = format_value(m, "minute") + " " + result; ! if(h > 0) ! result = format_value(h, "hour") + " " + result; ! if(d > 0) ! result = format_value(d, "day") + " " + result; ! return result; ! } ! } } void ConsoleProgressMonitor::UpdateCallback() { if(IsDone()) { ! const time_t elapsed = time(0) - m_start_time; // Clearing the line is not needed. cout << "\r" << GetMessage(); ! if(elapsed < 3) cout << ". "; ! else cout << " [" << format_time(elapsed) << "]. "; cout << endl; } else { ! cout << fixed << setprecision(m_digits); ! cout << "\r" << GetMessage() << " [" << 100.0 * GetProgress() << "% completed]"; } } --- 22,130 ---- #include "consoleprogressmonitor.h" // include first ! #include <iomanip> ! #include <ios> #include <iostream> using namespace sheep; using namespace std; + const int ElapsedTimeDisplayThreshold = 1; // seconds + const int SecondsBetweenUpdates = 3; // seconds + ConsoleProgressMonitor::ConsoleProgressMonitor() : ! m_digits(2) { } void ConsoleProgressMonitor::Reset(const string &message) { ! // Stop the stopwatch if it's running. ! if(m_stopwatch.IsRunning()) ! m_stopwatch.Stop(); ! // Reset the underlying IProgressMonitor object. ! IProgressMonitor::Reset(); ! // Set the new message. ! SetMessage(message); } ! void ConsoleProgressMonitor::StartJob(Real range_min, ! Real range_max, ! Real duration /*= 1.0*/) ! { ! // The stopwatch is started when the first job begins. ! if(!m_stopwatch.IsRunning()) ! m_stopwatch.Start(); ! // Set the time of the last update so that progress will ! // be first reported after a 1 second. ! m_last_update_time = m_stopwatch.GetElapsedTime() + 1; ! // Actually start the job. ! IProgressMonitor::StartJob(range_min, range_max, duration); ! } ! void ConsoleProgressMonitor::Done() { ! // Stop the stopwatch. ! m_stopwatch.Stop(); ! // Set the time of the last update so that the last call ! // to the update callback will actually print something. ! m_last_update_time = -1; ! IProgressMonitor::Done(); ! } ! void ConsoleProgressMonitor::SetPrecision(int digits) { ! m_digits = digits; } + //#define SINGLE_LINE + void ConsoleProgressMonitor::UpdateCallback() { if(IsDone()) { ! const time_t elapsed = m_stopwatch.GetElapsedTime(); + #ifdef SINGLE_LINE // Clearing the line is not needed. cout << "\r" << GetMessage(); ! if(elapsed < ElapsedTimeDisplayThreshold) cout << ". "; ! else cout << " [" << Stopwatch::FormatTime(elapsed) << "]. "; ! #else ! cout << GetMessage(); ! ! if(elapsed < ElapsedTimeDisplayThreshold) ! cout << "."; ! else cout << " [" << Stopwatch::FormatTime(elapsed) << "]."; ! #endif // SINGLE_LINE cout << endl; } else { ! if(m_stopwatch.GetElapsedTime() - m_last_update_time >= ! SecondsBetweenUpdates) ! { ! // Save the formatting settings of the stream and set ! // the new settings. ! ios_base::fmtflags old_flags = cout.flags(); ! cout << fixed << setprecision(m_digits); ! ! #ifdef SINGLE_LINE ! cout << "\r" // return at the beginning of the line ! << GetMessage() ! << " [" << 100.0 * GetProgress() << "% completed]"; ! #else ! cout << GetMessage() ! << " [" << 100.0 * GetProgress() << "% completed]" ! << endl; ! #endif // SINGLE_LINE ! ! // Restore the formatting settings. ! cout.flags(old_flags); ! ! m_last_update_time = m_stopwatch.GetElapsedTime(); ! } } } |