2015-06-26 3 views
1

Я пытаюсь написать простой отладочный макрос, который будет работать с несколькими потоками, запускающими его. Я, должно быть, явно ничего не вижу, потому что вывод std :: cout не синхронизирован. Любая помощь очень ценится.C++ Многопоточный макрос отладки

//=======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_ 

Выход:

[отладка]: [Тема: [отладка]: [Тема: 1074275136] Запуск Log..1099953248] инициализации запуска

+0

'станд :: cout.flush()' – Amartel

+0

@Amartel Это включено неявно в 'std :: endl'. (и, таким образом, основная причина, по которой использование 'std :: endl' вместо' '\ n'' может привести к снижению производительности) – Angew

ответ

3

Youre sync_mutex является static переменная namespace-scope, что означает, что у нее есть внутренняя связь — каждая единица перевода (.cpp файл), которая включает заголовок, будет иметь свою собственную копию мьютекса. Поэтому доступ из разных единиц перевода не синхронизирован.

Вы должны убедиться, что есть всего один объект sync_mutex на всю программу. Наиболее очевидным способом было бы превратить мьютекс в переменную extern вместо static, а затем определить ее в точно одном исходном файле.

В качестве альтернативы, если вы хотите, чтобы остаться заголовок только, вы могли бы это быть статичным локальная переменная внутри инлайн функции:

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

inline std::mutex& sync_mutex() 
{ 
    static std::mutex m; 
    return m; 
} 
Смежные вопросы