static member variable in multithreaded environment

Discussion in 'C++' started by nin234@yahoo.com, Feb 23, 2005.

  1. Guest

    I tried searching the newgroups for an answer to this question. I
    found
    many related topics, but didn't find the exact answer I am looking
    for.


    I am implementing a class to aid in the logging for our product as
    follows. Code snippet is as follows.

    //Header file srvLog.h starts here
    enum eErrLvl
    {
    eLOG_DEBUG_5 = 1,
    eLOG_DEBUG_4,
    eLOG_DEBUG_3,
    eLOG_DEBUG_2,
    eLOG_DEBUG_1,
    eLOG_INFO,
    eLOG_WARNING,
    eLOG_ERROR,
    eLOG_FATAL
    };

    std::eek:stream& operator << (std::eek:stream&, eErrLvl&);

    class srvLog
    {
    static int nLglvl;
    eErrLvl nSeverity;
    public:
    srvLog () {}
    static void setlvl (int lvl) { nLglvl = lvl; }
    const srvLog& operator () (eErrLvl nSvrty) { nSeverity =
    nSvrty; return *this;}
    friend std::eek:stream& operator << (std::eek:stream& , const
    srvLog&);
    };

    //Source file srvLog.C starts here
    int srvLog::nLglvl = eLOG_ERROR;

    std::eek:stream&
    operator << (std::eek:stream& os, eErrLvl& eLvl)
    {
    switch (eLvl)
    {
    case eLOG_DEBUG_5:
    case eLOG_DEBUG_4:
    case eLOG_DEBUG_3:
    case eLOG_DEBUG_2:
    case eLOG_DEBUG_1:
    os << "Debug\t: ";
    break;
    case eLOG_INFO:
    os << "Info\t: ";
    break;
    case eLOG_WARNING:
    os << "Warn\t: ";
    break;
    case eLOG_ERROR:
    os << "Error\t: ";
    break;
    case eLOG_FATAL:
    os << "Fatal\t: ";
    break;
    }
    return os;
    }
    std::eek:stream& operator << (std::eek:stream& os, const srvLog& oLog)
    {
    if (oLog.nSeverity >= oLog::nLglvl)
    os.clear();
    else
    {
    os.clear (std::ios::failbit);
    return os;
    }
    char msg[100];
    //memset (msg, '\0', 100);
    struct timeval now;
    gettimeofday (&now, NULL);

    struct tm *pTm = localtime (&now.tv_sec);
    strftime (msg, 100, "%c ", pTm);
    os << msg << oLog.nSeverity;
    return os;
    }


    //Sample use case

    int main ()
    {
    srvLog lgstrt;
    //Class A
    A ainst;
    std::cerr << lgstrt(eLOG_FATAL) << "more to log " << ainst <<
    std::endl;
    pthread_create (, threadA, ... , ...);
    pthread_create (, threadB, ... , ...);

    }
    //ThreadA in a different file and shared library
    void threadA ()
    {
    srvLog lgstrt;
    //Class A
    A ainst;
    std::cerr << lgstrt(eLOG_FATAL) << "more to log " << ainst <<
    std::end;
    }

    //ThreadB in a different file and shared library
    void threadB ()
    {
    srvLog lgstrt;
    //Class A
    A ainst;
    std::cerr << lgstrt(eLOG_FATAL) << "more to log " << ainst <<
    std::endl;
    }

    Logging is controlled by the nLglvl static variable. This is part of
    a daemon. So the logging is to a file and the value of nLglvl will be
    set by a command line tool.
    My questions are the following
    1) Is the value of nLglvl shared by threadA, threadB and main()
    thread.

    2)Where should I call setlvl()?
    3) If the answer to 1) is yes. Is it really required to use locking
    in
    this scenario. Because the change to the value of nLglvl will be
    infrequent and I can live with some bad reads.

    I am using POSIX threads. Linux and solaris are the current
    environments. It must be portable to all unix flavors. I threads are
    not part of the C++ standard, but to me it does n't make much sense. I
    feel this is as much a C++ question as a Threads one

    Ninan
    , Feb 23, 2005
    #1
    1. Advertising

  2. nin234 wrote:

    > I tried searching the newgroups for an answer to this question.
    > I found many related topics
    > but didn't find the exact answer I am looking for.
    >
    >
    > I am implementing a class
    > to aid in the logging for our product as follows.
    > Code snippet is as follows.


    > cat srvLog.h

    #ifndef GUARD_SRVLOG_H
    #define GUARD_SRVLOG_H 1

    #include <iostream>

    //Header file srvLog.h starts here
    enum eErrLvl {
    eLOG_DEBUG_5 = 1,
    eLOG_DEBUG_4,
    eLOG_DEBUG_3,
    eLOG_DEBUG_2,
    eLOG_DEBUG_1,
    eLOG_INFO,
    eLOG_WARNING,
    eLOG_ERROR,
    eLOG_FATAL
    };

    std::eek:stream& operator<<(std::eek:stream&, const eErrLvl&);

    class srvLog {
    private:
    static int nLglvl;
    eErrLvl nSeverity;
    public:
    srvLog(void) { }
    static void setlvl(int lvl) { nLglvl = lvl; }
    const srvLog& operator()(eErrLvl nSvrty) {
    nSeverity = nSvrty;
    return *this;
    }
    friend
    std::eek:stream& operator<<(std::eek:stream&, const srvLog&);
    };

    class A {
    public:
    friend
    std::eek:stream& operator<<(std::eek:stream& os, const A& a) {
    return os << 13;
    }
    };

    #endif//GUARD_SRVLOG_H

    > cat srvLog.C

    //Source file srvLog.C starts here
    #include <sys/time.h>
    #include "srvLog.h"

    int srvLog::nLglvl = eLOG_ERROR;

    std::eek:stream&
    operator<<(std::eek:stream& os, const eErrLvl& eLvl) {
    switch (eLvl) {
    case eLOG_DEBUG_5:
    case eLOG_DEBUG_4:
    case eLOG_DEBUG_3:
    case eLOG_DEBUG_2:
    case eLOG_DEBUG_1:
    os << "Debug\t: ";
    break;
    case eLOG_INFO:
    os << "Info\t: ";
    break;
    case eLOG_WARNING:
    os << "Warn\t: ";
    break;
    case eLOG_ERROR:
    os << "Error\t: ";
    break;
    case eLOG_FATAL:
    os << "Fatal\t: ";
    break;
    }
    return os;
    }

    std::eek:stream&
    operator<<(std::eek:stream& os, const srvLog& oLog) {
    if (oLog.nSeverity >= srvLog::nLglvl) {
    os.clear();
    char msg[100];
    //memset (msg, '\0', 100);
    struct timeval now;
    gettimeofday(&now, NULL);

    struct tm* pTm = localtime (&now.tv_sec);
    strftime (msg, 100, "%c ", pTm);
    os << msg << oLog.nSeverity;
    }
    else {
    os.clear (std::ios::failbit);
    }
    return os;
    }

    > cat main.C

    //Sample use case
    #include "srvLog.h"
    #include <pthread.h>

    int main(int argc, char* argv[]) {
    srvLog lgstrt;
    //Class A
    A ainst;
    std::cerr << lgstrt(eLOG_FATAL) << "more to log "
    << ainst << std::endl;
    // pthread_create(, threadA, ... , ...);
    // pthread_create(, threadB, ... , ...);
    return 0;
    }

    //ThreadA in a different file and shared library
    void threadA(void) {
    srvLog lgstrt;
    //Class A
    A ainst;
    std::cerr << lgstrt(eLOG_FATAL) << "more to log "
    << ainst << std::endl;
    }

    //ThreadB in a different file and shared library
    void threadB(void) {
    srvLog lgstrt;
    //Class A
    A ainst;
    std::cerr << lgstrt(eLOG_FATAL) << "more to log "
    << ainst << std::endl;
    }

    > g++ -Wall -ansi -pedantic -o main main.C srvLog.C
    > ./main

    Wed Feb 23 09:10:23 2005 Fatal : more to log 13

    > Logging is controlled by the nLglvl static variable.
    > This is part of a daemon so the logging is to a file
    > and the value of nLglvl will be set by a command line tool.
    >
    > My questions are the following
    >
    > 1) Is the value of nLglvl shared
    > by threadA, threadB and main() thread.


    nLglvl is just a global variable in the srvLog namespace.

    > 2) Where should I call setlvl()?


    You should rewrite setlvl(int) so that srvLog::nLglvl
    is protected by mutual exclusion.
    Then you can call it anywhere at any time.

    > 3) If the answer to 1) is yes.
    > Is it really required to use locking in this scenario?


    Practically speaking, yes.

    > Because the change to the value of nLglvl will be
    > infrequent and I can live with some bad reads.


    You say that now ...

    > I am using POSIX threads.
    > Linux and Solaris are the current environments.
    > It must be portable to all UNIX flavors.
    > I [know that] threads are not part of the C++ standard
    > but, to me, it doesn't make much sense.
    > I feel this is as much a C++ question as it is a threads question.


    The only C++ question is about the static (global) variable nLglvl.
    Now, you would be *much* better off to post your other questions
    (about where to call srvLog::setlvl(int), portability, etc.)
    in one of the UNIX newsgroups.
    E. Robert Tisdale, Feb 23, 2005
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Joerg Gippert
    Replies:
    9
    Views:
    661
    John C. Bollinger
    Oct 10, 2003
  2. Anthony
    Replies:
    3
    Views:
    424
    Javier Estrada
    Oct 8, 2003
  3. Replies:
    9
    Views:
    429
    Pete Becker
    Mar 6, 2006
  4. Replies:
    5
    Views:
    635
  5. dolphin
    Replies:
    3
    Views:
    1,319
    Pete Becker
    Dec 5, 2007
Loading...

Share This Page