ça existe un ostream vide/bidon ?

ça existe un ostream vide/bidon ? - C++ - Programmation

Marsh Posté le 02-06-2009 à 07:55:32    

ça existe en C++ un stream qui ne fasse rien ?
par exemple pour qu'une ligne suivante consomme le moins possible de CPU:
 
ostream << "message"
 
merci

Reply

Marsh Posté le 02-06-2009 à 07:55:32   

Reply

Marsh Posté le 02-06-2009 à 08:56:00    

non mais c'est assez simple à faire en héritant de stream je pense

Reply

Marsh Posté le 02-06-2009 à 10:26:25    

un ostream qui écrit dans /dev/null ? [:dawa]


---------------
last.fm
Reply

Marsh Posté le 02-06-2009 à 12:10:08    

il ferait qd mm tout son travail en interne. Tu fais un stream qui fait rien dans ses insertions/extractions et zou

Reply

Marsh Posté le 02-06-2009 à 12:16:44    

Même si t'hérites, si tu veux tout transformer en NOP, il faudrait tout redéfinir inline :/

Reply

Marsh Posté le 02-06-2009 à 19:53:37    

bon j'ai trouvé une autre solution en utilisant les templates, en faite je fais une classe de log avec une gestion de différents level de logs, et il me fallait une feinte pour ne pas prendre en compte des <<'message' quand le level n'est pas suffisament grand

Reply

Marsh Posté le 02-06-2009 à 23:38:36    

Tu ne veux pas plutôt réutiliser de l'existent ?

Reply

Marsh Posté le 03-06-2009 à 00:22:04    

si c'est assez bien oui,  mais c'est du boost j'imagine ? idéalement j'aurais besoin d'une classe qui sache être hyper performante  pour pouvoir être intégrée dans des applis temps réel, et également user friendly quand il s'agit d'applis moins critiques. La classe de log parfaite quoi en somme :)


Message édité par Glock 17Pro le 03-06-2009 à 00:30:15
Reply

Marsh Posté le 03-06-2009 à 07:07:02    

sauf que genre t'e as le 1er à y penser :E
quant à tes exigences sur le TR .... [:prozac]

Reply

Marsh Posté le 03-06-2009 à 07:36:48    

ok  :heink:

Reply

Marsh Posté le 03-06-2009 à 07:36:48   

Reply

Marsh Posté le 03-06-2009 à 10:31:06    

si ca correspond à ce que j'ai vu dans tes autres posts, tu calcules  en template un booléen à partir de ton niveau de log, donc pourquoi ne pas avoir une fonction log< bool LevelEstAssezHaut >( const string& message ) qui, quand l'argument template vaut vrai, logge vraiment et quand il vaut faux, ne fait rien ?


---------------
last.fm
Reply

Marsh Posté le 03-06-2009 à 10:47:50    

voilà c'est ce que je fais mais le 'rien' me poser me problème car grace un #define mon code pour logger  
faisait ainsi :
 
WriteLog(DEBUG) << "message" << i;
WriteLog(CRITIQUE) << "message2";
WriteLog(FLUSH);
 
En faite je résoud mon problème en surchant operator << dans la spécialisation de ma classe template ayant comme paramètre bool = false (booléen calculé grace à une une autre classe template,en se basant sur des const, donc calculable à la compilation) . Je fais juste un return *this dans operator <<  ainsi que dans la méthode appelé pour logger ,comme ça la ligne de tout le code à ne peut pas prendre en compte, par exemple WriteLog(DEBUG) << "message2", car le level demandé est uniquement les messages CRITIQUE,  se limite juste à des appels de fonctions vides.
 

Code :
  1. #include <sstream>
  2. #include <fstream>
  3. #include <iostream>
  4. #include <ctime>   //time
  5. namespace Logger
  6. {
  7. #define WriteLog(level) Log< LogHelper<level>::Value >().Get(level)
  8. /* PARAMETRE */
  9. enum LogLevel {FLUSH,DEBUG,INFO,CRITIQUE};
  10. const char * const path  = "log.txt";
  11. const int reportingLevel = CRITIQUE;
  12. /* END OF PARAMETRE*/
  13.  std::ostringstream      log_buffer;
  14. char* GetTime()
  15. {
  16.  time_t t = time(NULL);
  17.  char * ret=ctime(&t);
  18.  ret[24]='\0'; //on enelve le \n
  19.  return  ret;
  20. }
  21. ///////////////////////////
  22. template<int U> struct LogHelper
  23. {
  24.  enum { Value = ( U >= reportingLevel ) };
  25. };
  26. template<> struct LogHelper<0>
  27. {
  28.  enum { Value = 2};
  29. };
  30. ///////////////////////////
  31. template<int condition> struct Log{};
  32. template<> struct Log< 1 >
  33. {
  34. public:
  35.  Log(){}
  36.    ~Log()  {  log_buffer << std::endl;   }
  37.    std::ostringstream& Get(LogLevel level) const
  38.    {
  39.     log_buffer << GetTime() << " " << level << ": ";
  40.     return log_buffer;
  41.    }
  42. private:
  43.    Log(const Log& );
  44.    Log& operator =(const Log& );
  45. };
  46. ////////DO NOTHING//////////
  47. template<> struct Log< 0 >
  48. {
  49.  Log< 0 >& Get(LogLevel level)
  50.  {
  51.   return *this;
  52.  }
  53.  template<class T>
  54.  Log< 0 >& operator <<(T t)
  55.  {
  56.   return *this;
  57.  }
  58. };
  59. ////////WRITE TO FILE//////////
  60. template<> struct Log< 2 >
  61. {
  62.    void Get(LogLevel /*dummy*/) const
  63.    {
  64.      std::ofstream file(path);
  65.   file<< log_buffer.str();
  66.   file.close();
  67.    }
  68. };
  69. }


Message édité par Glock 17Pro le 03-06-2009 à 10:55:39
Reply

Marsh Posté le 03-06-2009 à 11:14:21    

pourquoi ne pas faire plutôt :

Code :
  1. WriteLog(DEBUG, "message" << i );
  2. WriteLog(CRITIQUE, "message2" );
  3. WriteLog(FLUSH);


 
et dans ta macro, tu ne fais rien, ou alors tu balance ton message dans ton stream ?


---------------
last.fm
Reply

Marsh Posté le 03-06-2009 à 11:20:00    

en testant avec un if dans la macro?

Reply

Marsh Posté le 03-06-2009 à 13:35:52    

Code :
  1. #define WriteLog_DEBUG( ... )
  2. #define WriteLog_CRITIQUE( message ) ostream << message;
  3. #define WriteLog( level, message ) WriteLog_##level( message )


 
en général, on passe par des macros pour le log aussi parce que ca permet facilement d'ajouter un __FILE__ et un __LINE__  pour avoir un meilleur suivi des problèmes, et ca permet de désactiver intégralement les logs via la définition d'une constante.
 
Sinon, tu dois aussi pouvoir faire un opérateur template du style :

Code :
  1. template<typename T>
  2. Log<0>& operator << ( Log<0>& log_stream, T& arg )
  3. {
  4.     return log_stream;
  5. }


 
Edit : précision : du coup, si tu fais ca pour le cas général et que tu rediriges directement vers ton stream que tu veux, ca te fera un petit overhead, mais pas bien méchant :o


Message édité par theshockwave le 03-06-2009 à 13:37:23

---------------
last.fm
Reply

Marsh Posté le 03-06-2009 à 13:47:27    

oui mais le problème c'est que le level pourlequel on veut filtré peut changer d'une execution à l'autre, là j'ai l'impression qu'avec ta macro, le code est figé, tous les messages de niveau égale à DEBUG sont filtrés, comment faire si je les veux par la suite, tout le temps changer à la main? pas très pratique

Reply

Marsh Posté le 03-06-2009 à 14:56:41    

mais dans ce cas, ton template ne pourra pas non plus s'en sortir ! Le choix du template sera nécessairement fait à la compilation.
 
Fais une interface de log de plus haut niveau. Tu envoies ton message à cet interface de log et elle fait une simple comparaison avec le niveau de log souhaité pour savoir si elle envoie dans le stream ou non et basta.
 
Je te conseille d'ailleurs, si tu veux quelque chose de puissant, de dissocier les appels aux logs de l'écriture dans les streams. Ca te permettra d'avoir, par exemple, plusieurs sorties de log différentes avec des configurations de verbosité différentes (genre, des logs à l'écran et dans un fichier, avec un niveau de détail plus élevé dans le fichier)


---------------
last.fm
Reply

Marsh Posté le 03-06-2009 à 15:20:42    

et mates le proposal de Boost.Log aussi, y a pas mal d epb pas clair dans ce genre de tache.

Reply

Marsh Posté le 03-06-2009 à 16:15:50    

J'ai déjà écrit une série de variations sur ce thème.  La structure que j'ai employée les dernières fois était une variation sur le thème:

Code :
  1. #define LOG  if(needToLog()) ; else getStream()


où LOG peut éventuellement avoir des paramètres passés tous ou en partie à needToLog() et getStream().

 

Le if();else est un bon vieux truc pour éviter de pairer un else qui suit la macro avec le if de la macro.

 

Si needToLog() est en fait constant, les compilateurs que j'ai testé vire le code mort mais continuent à détecter les erreurs de syntaxe -- ça évite les log qui ne compilent plus quand on les active parce que le dernier type qui a fait des modifs ne les utilise pas.  Ce peut naturellement être une variable (mise avec le débuggeur ou à l'initialisation avec une variable d'environnement) ou une fonction aussi compliquée que désiré.

 

getStream() renvoie soit un ostream& dans les versions les plus simples ou une classe avec un operator<< template forwardant vers un ostream interne (comme ça on peut avoir un format différent pour les logs et les IO textes normales) avec un constructeur et un destructeur qui ajoute ce qu'on désire (timestamp pour le ctor, flush pour le dtor sont les applications évidentes).

 

Le streambuf de l'ostream est ce que l'on veut.  C'est lui qui gère le choix des destinations (fichier, console, fenêtre modale ou non, ou combinaison)


Message édité par Un Programmeur le 03-06-2009 à 16:17:31
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed