#pragma once ///////////////////////////////////////////////////////////////////// // ISingletonLogger.h - Interface for logging to multiple streams // // ver 1.0 // // Jim Fawcett, CSE687 - Object Oriented Design, Fall 2018 // ///////////////////////////////////////////////////////////////////// /* * Package Operations: * ------------------- * This package defines three classes: * - ILogger: * An Interface for singleton logger that supports one logger for each * category (int template argument). SingletonLoggersupports multiple * std::iostreams, with each write sending log items to each of its * streams. Logger will accept any stream derived from std::iostream, * e.g., ofstream and ostringstream. * - NoLock: * A class used to provide a locking policy for loggers. It provides * empty lock and unlock methods, intended for use in a single-threaded * environment. The empty methods will be optimized away by the compiler. * - Lock: * A class used to provide a locking policy for loggers. It provides * lock and unlock methods that use a std::mutex to provide mutually * exclusive access to its instantiation method, getInstance. * - Category is an integer value, used to partition loggers into groups. * Each group, i.e. a specific interger value, shares the same logger. * * Required Files: * --------------- * ISingletonLogger.h * * Maintenance History: * -------------------- * ver 1.2 : 07 Oct 2018 * - modified comments * ver 1.1 : 27 Sep 2018 * - extracted interface ILogger as separate package * ver 1.0 : 23 Sep 2018 * - first release */ #include #include #include namespace Utilities { /////////////////////////////////////////////////////////////////// // NoLock class // - Template parameter for single-threaded environment template class NoLock { public: static void lock() {} static void unlock() {} }; /////////////////////////////////////////////////////////////////// // Lock class // - Logger template parameter for multi-threaded environment // - Category is a template parameter used to define categories // of loggers template class Lock { public: Lock() {} Lock(const Lock&) = delete; Lock& operator=(const Lock&) = delete; static void lock() { mtx_.lock(); } static void unlock() { mtx_.unlock(); } private: static std::recursive_mutex mtx_; }; template std::recursive_mutex Lock::mtx_; /////////////////////////////////////////////////////////////////// // ILogger Interface // - uses template template parameter to ensure that // ILogger and Locker use the same Category using Terminator = std::string; template class Locker> class ILogger { public: virtual ~ILogger() {} virtual void addStream(std::ostream* pStream) = 0; virtual bool usingStream(std::ostream* pStream) = 0; virtual bool removeStream(std::ostream* pStream) = 0; virtual void setTerminator(const Terminator& term) = 0; virtual void setAuthor(const std::string& name) = 0; virtual void writeHead(const std::string& msg) = 0; virtual void write(const std::string& text) = 0; virtual void writeTail(const std::string& msg = "end of log") = 0; }; }