dynare/dynare++/kord/journal.hh

185 lines
3.9 KiB
C++
Raw Normal View History

/*
* Copyright © 2004 Ondra Kamenik
* Copyright © 2019-2020 Dynare Team
*
* This file is part of Dynare.
*
* Dynare 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 3 of the License, or
* (at your option) any later version.
*
* Dynare 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 Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
// Resource usage journal
#ifndef JOURNAL_H
#define JOURNAL_H
#include "int_sequence.hh"
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <chrono>
/* Implement static methods for accessing some system resources. An instance of
this class is a photograph of these resources at the time of instantiation. */
struct SystemResources
{
// The starting time of the executable
static const std::chrono::time_point<std::chrono::high_resolution_clock> start;
#ifndef _WIN32
static long pageSize();
#endif
static long availableMemory();
double load_avg;
long mem_avail;
double utime;
double stime;
double elapsed;
long idrss;
long majflt;
SystemResources();
void diff(const SystemResources &pre);
};
class Journal : public std::ofstream
{
int ord{0};
int depth{0};
public:
explicit Journal(const std::string &fname)
: std::ofstream(fname)
{
printHeader();
}
/* Constructor that does not initialize the std::ofstream. To be used when an
on-disk journal is not wanted. */
Journal() = default;
Journal &operator=(Journal &&) = default;
~Journal() override
{
flush();
}
void printHeader();
void
incrementOrd()
{
ord++;
}
int
getOrd() const
{
return ord;
}
void
incrementDepth()
{
depth++;
}
void
decrementDepth()
{
depth--;
}
int
getDepth() const
{
return depth;
}
};
class JournalRecord;
JournalRecord &endrec(JournalRecord &);
class JournalRecord
{
protected:
char recChar;
int ord;
public:
Journal &journal;
std::string prefix;
std::string mes;
SystemResources flash;
using _Tfunc = JournalRecord &(*)(JournalRecord &);
explicit JournalRecord(Journal &jr, char rc = 'M')
: recChar(rc), ord(jr.getOrd()), journal(jr)
{
writePrefix(flash);
}
virtual ~JournalRecord() = default;
JournalRecord &operator<<(const IntSequence &s);
JournalRecord &
operator<<(_Tfunc f)
{
(*f)(*this);
return *this;
}
JournalRecord &
operator<<(char c)
{
mes += c;
return *this;
}
JournalRecord &
operator<<(const std::string &s)
{
mes += s;
return *this;
}
JournalRecord &
operator<<(int i)
{
mes += std::to_string(i);
return *this;
}
JournalRecord &
operator<<(double d)
{
mes += std::to_string(d);
return *this;
}
protected:
void writePrefix(const SystemResources &f);
2019-06-05 18:17:43 +02:00
/* Writes a floating point number as a field of exactly width characters
large. Note that the width will not be respected if the integer part is
too large. */
static void writeFloatTabular(std::ostream &s, double d, int width);
};
/*
2019-06-05 18:17:43 +02:00
Constructs a pair of symmetric records with a RAII-like logic:
when fed with endrec, print the opening record
subsequent records will have depth increased by 1
when deleted, prints the symmetric closing record, and decrease depth
*/
class JournalRecordPair : public JournalRecord
{
std::string prefix_end;
public:
explicit JournalRecordPair(Journal &jr)
: JournalRecord(jr, 'S')
{
journal.incrementDepth();
}
~JournalRecordPair() override;
private:
void writePrefixForEnd(const SystemResources &f);
};
#endif