2

I am trying to write simple debug macro that will work with multiple threads running it. I must be obviously missing something, because the std::cout output is not synchronized. Any help much appreciated.

//=======Debugger========//

#ifndef _DEBUGGER_H_
#define _DEBUGGER_H_

#include <iostream>
#include <thread>
#include <mutex>

/*
 * Debugger. All messages are directed to std::cout
 */

#ifndef WITH_NOCOLOR
 #define COLOR_GREEN        "\e[0;32m"
 #define COLOR_RED          "\e[1;91m"
 #define COLOR_CYAN         "\e[1;36m"
 #define COLOR_YELLOW       "\e[1;33m"
 #define COLOR_ORANGE       "\e[0;33m"
 #define RESET_COLOR        "\e[m"
#else
 #define COLOR_GREEN        ""
 #define COLOR_RED          ""
 #define COLOR_CYAN         ""
 #define COLOR_YELLOW       ""
 #define COLOR_ORANGE       ""
 #define RESET_COLOR        ""
#endif //WITH_NOCOLOR

#define THREAD_ID           "[thread: " << std::this_thread::get_id() << "] "
#define THREAD_SYNC_START   { std::lock_guard< std::mutex > lock( sync_mutex );
#define THREAD_SYNC_STOP    }

static std::mutex sync_mutex;

#define DEBUG       "[Debug]: "
#define ERROR       "[Error]: "
#define INFO        "[Info ]: "
#define WARNING     "[Warn ]: "

#define Debug(x)    do { THREAD_SYNC_START \
                    std::cout << COLOR_CYAN << DEBUG << RESET_COLOR <<  THREAD_ID << x << std::endl; \
                    THREAD_SYNC_STOP \
                    }while(0)

#define Err(x)      do { THREAD_SYNC_START \
                    std::cout << COLOR_RED << ERROR << COLOR_ORANGE << THREAD_ID << x << RESET_COLOR << std::endl; \
                    THREAD_SYNC_STOP \
                    }while(0)

#define Info(x)     do { THREAD_SYNC_START \
                    std::cout << INFO << THREAD_ID << x <<std::endl; \
                    THREAD_SYNC_STOP \
                    }while(0)

#define Warn(x)     do { THREAD_SYNC_START \
                    std::cout << COLOR_YELLOW << WARNING << RESET_COLOR << THREAD_ID << x << std::endl; \
                    THREAD_SYNC_STOP \
                    }while(0);

#endif //_DEBUGGER_H_

Output:

[Debug]: [thread: [Debug]: [thread: 1074275136] Starting Log..1099953248] init start

1
  • @Amartel That's included implicitly in std::endl. (and, thus, the primary reason why using std::endl instead of '\n' can kill performance) Commented Jun 26, 2015 at 12:46

1 Answer 1

4

Youre sync_mutex is a static namespace-scope variable, which means that it has internal linkage—each translation unit (.cpp file) which includes the header will have its own copy of the mutex. Accesses from different translation units are therefore not synchronised.

You need to make sure there's only one sync_mutex object for the entire program. The most obvious way would be to turn the mutex into an extern variable instead of a static one, and then define it in exactly one source file.

Alternatively, if you wanted to stay header-only, you could have it be a static local variable inside an inline function:

#define THREAD_SYNC_START   { std::lock_guard< std::mutex > lock( sync_mutex() );

inline std::mutex& sync_mutex()
{
  static std::mutex m;
  return m;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.