/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM 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; only version 2 of the License.      
 * 
 * NMM 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 NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef _NMM_CPUINFO_HPP_
#define _NMM_CPUINFO_HPP_

#include "nmm/nmm_prefix.hpp"

#include "nmm/utils/thread/ThreadMutex.hpp"
#include "nmm/utils/thread/Thread.hpp"
#include "nmm/utils/NamedObject.hpp"

#include <string>
#include <vector>
#include <fstream>

namespace NMM {

class CPUInfo : public NamedObject {
    static bool first_read;
    static ifstream stat_file;
    static string STATFILENAME;
    static string CPUFILENAME;

    static unsigned int cpu_num;       // the number of cpu's
    static string cpu_type;   // the cpu type (i.e. Pentium III)
    static double cpu_speed;  // the relative cpu speed measured in bogomips

    static ThreadMutex cv;
    static ThreadCondition* mcv;
    static bool is_running; // indicator if the ThreadCondition is setup

    // in this struct infos about the utilisation of a cpu are saved
    struct CPUUsage {
      unsigned int cpu_user;
      unsigned int cpu_nice;
      unsigned int cpu_system;
      unsigned int cpu_free;

      CPUUsage() {
        cpu_user = cpu_nice = cpu_system = cpu_free = 0;
      }

      friend CPUUsage operator-(const CPUUsage& a,const CPUUsage& b) {
        CPUUsage diff;
        diff.cpu_user   = a.cpu_user   - b.cpu_user;
        diff.cpu_nice   = a.cpu_nice   - b.cpu_nice;
        diff.cpu_system = a.cpu_system - b.cpu_system;
        diff.cpu_free   = a.cpu_free   - b.cpu_free;
        return diff;
      }

    };

    static vector<CPUUsage> cpu_usage;
    static vector<int> cpu_free;

    static void read_cpu_info();

    Thread cpu_free_monitor_thread; // the thread that continuesly updates cpu_free values
    static void* run_static(void*); // the corresponding thread function
    static bool is_started; // indicator if the thread is already active
    static unsigned int update_intervall;  // the intervall after which the cpu utilisation is measured

  public:

    CPUInfo();
    ~CPUInfo();

    /**
     * start the cpu info monitor (collects info about the free cpu-time)
     */
    void start();

    /**
     * stop the cpu info monitor
     */
    void stop();

    /**
     * \param the number of the cpu (0,...)
     * \returns amount of jiffies (in a second) the cpu was idle
     */
    const unsigned int getFreeCPU(unsigned int cpu);

    /**
     * \returns amount of jiffies(in a second) all cpu's were idle
     */
    const unsigned int getTotalFreeCPU();

    /**
     * \returns the number of cpu's
     */
    const unsigned int getCPUNum();

    /**
     * \returns the name of the cpu
     */
    const string getCPUType();

    /**
     * \returns the speed of one cpu (bogomips)
     */
    const unsigned int getCPUSpeed();

    /**
     * sets the intervall for which the amount of free cpu time is valid
     */
    void setUpdateIntervall(unsigned int seconds);
};

}

#include "nmm/nmm_suffix.hpp"

#endif
