Guitarix
gx_logging.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3  * Copyright (C) 2011 Pete Shorthose
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  * ---------------------------------------------------------------------------
19  */
20 
21 #include "gx_logging.h"
22 #include <iostream>
23 #include <iomanip>
24 
25 /****************************************************************
26  ** Logging
27  */
28 
29 GxLogger::GxLogger()
30  : trackable(),
31  msglist(),
32  msgmutex(),
33  got_new_msg(),
34  ui_thread(),
35  handlers(),
36  queue_all_msgs(true) {
37 }
38 
39 static class GxLoggerGuard {
40 private:
41  GxLogger *logger_instance;
42 public:
43  GxLoggerGuard() : logger_instance(0) {}
44  ~GxLoggerGuard() { destroy(); }
45  void create() { logger_instance = new GxLogger; }
46  void destroy() { if (logger_instance) { delete logger_instance; logger_instance = 0; }}
47  GxLogger *get() { return logger_instance; }
48 } logger_guard;
49 
51  GxLogger *l = logger_guard.get();
52  if (!l) {
53  logger_guard.create();
54  l = logger_guard.get();
55  }
56  return *l;
57 }
58 
60  logger_guard.destroy();
61 }
62 
63 GxLogger::~GxLogger() {
64  delete got_new_msg;
65 }
66 
67 void GxLogger::set_ui_thread() {
68  if (ui_thread) {
69  assert(pthread_equal(pthread_self(), ui_thread));
70  } else {
71  got_new_msg = new Glib::Dispatcher;
72  ui_thread = pthread_self();
73  got_new_msg->connect(mem_fun(*this, &GxLogger::write_queued));
74  }
75 }
76 
77 GxLogger::msg_signal& GxLogger::signal_message() {
78  set_ui_thread();
79  return handlers;
80 }
81 
83  if (!queue_all_msgs) {
84  return;
85  }
86  queue_all_msgs = false;
87  write_queued();
88 }
89 
90 void GxLogger::write_queued() {
91  if (handlers.empty()) {
92  return;
93  }
94 
95  // quick copy list
96  msgmutex.lock();
97  std::list<logmsg> l = msglist;
98  if (!queue_all_msgs) {
99  msglist.clear();
100  }
101  msgmutex.unlock();
102 
103  // feed throught the handler(s)
104  for (std::list<logmsg>::iterator i = l.begin(); i != l.end(); ++i) {
105  if (queue_all_msgs) {
106  if (!i->plugged) {
107  handlers(i->msg, i->msgtype, i->plugged);
108  i->plugged = true;
109  }
110  } else {
111  handlers(i->msg, i->msgtype, i->plugged);
112  }
113  }
114 }
115 
116 std::string GxLogger::format(const char* func, const std::string& msg) {
117  // timestamp
118  time_t now;
119  time(&now);
120  struct tm *tm_now = localtime(&now);
121  std::ostringstream msgbuf;
122  msgbuf << "[" << std::setfill('0')
123  << std::setw(2) << tm_now->tm_hour << ":"
124  << std::setw(2) << tm_now->tm_min << ":"
125  << std::setw(2) << tm_now->tm_sec << "]"
126  << " " << func << " *** " << msg;
127  return msgbuf.str();
128 }
129 
130 void GxLogger::print(const char* func, const std::string& msg, GxLogger::MsgType msgtype) {
131  GxLogger::print(format(func, msg), msgtype);
132 }
133 
134 void GxLogger::print(const std::string& formatted_msg, GxLogger::MsgType msgtype) {
135  if (handlers.empty() || !(pthread_equal(pthread_self(), ui_thread))) {
136  boost::mutex::scoped_lock lock(msgmutex);
137  // defer output
138  msglist.push_back(logmsg(formatted_msg, msgtype, false));
139  if (!handlers.empty() && msglist.size() == 1) {
140  (*got_new_msg)();
141  }
142  } else {
143  write_queued();
144  handlers(formatted_msg, msgtype, false);
145  if (queue_all_msgs) {
146  msglist.push_back(logmsg(formatted_msg, msgtype, true));
147  }
148  }
149 }
150 
151 /*
152 ** utility logger functions
153 */
154 
155 // ---- log message handler
156 void gx_print_logmsg(const char* func, const std::string& msg, GxLogger::MsgType msgtype) {
157  GxLogger::get_logger().print(func, msg, msgtype);
158 }
159 
160 // warning
161 void gx_print_warning(const char* func, const std::string& msg) {
163 }
164 
165 // error
166 void gx_print_error(const char* func, const std::string& msg) {
167  gx_print_logmsg(func, msg, GxLogger::kError);
168 }
169 
171 }
172 
173 // fatal error
174 // - do not use before Gtk::Main() ctor
175 // - do not use when main loop is blocked (modal dialog or something)
176 //
177 void gx_print_fatal(const char* func, const std::string& msg) {
178  std::string msgbuf = std::string(_("fatal system error: ")) + func + " *** " + msg + "\n";
180 }
181 
182 // info
183 void gx_print_info(const char* func, const std::string& msg) {
184  gx_print_logmsg(func, msg, GxLogger::kInfo);
185 }
186 
187 
188 /****************************************************************
189  ** class GxExit
190  */
191 
192 GxExit::GxExit(): exit_sig(), ui_thread() {}
193 
195 
196 void GxExit::exit_program(std::string msg, int errcode) {
197  exit_sig.emit_reverse(!pthread_equal(pthread_self(), ui_thread));
198  if (msg.empty()) {
199  msg = "** guitarix exit **";
200  }
201  std::cerr << msg << std::endl;
202  _exit(errcode);
203 }
204 
206  static GxExit instance;
207  return instance;
208 }
void gx_print_logmsg(const char *func, const std::string &msg, GxLogger::MsgType msgtype)
Definition: gx_logging.cpp:156
void gx_print_fatal(const char *func, const std::string &msg)
Definition: gx_logging.cpp:177
void gx_print_error(const char *func, const std::string &msg)
Definition: gx_logging.cpp:166
static GxLogger & get_logger()
Definition: gx_logging.cpp:50
void fatal_msg(const std::string &msg)
Definition: gx_logging.h:119
static GxExit & get_instance()
Definition: gx_logging.cpp:205
msg_signal & signal_message()
Definition: gx_logging.cpp:77
void exit_program(std::string msg="", int errcode=1)
Definition: gx_logging.cpp:196
void gx_print_warning(const char *func, const std::string &msg)
Definition: gx_logging.cpp:161
static void destroy()
Definition: gx_logging.cpp:59
void gx_print_info(const char *func, const std::string &msg)
Definition: gx_logging.cpp:183
void print(const char *func, const std::string &msg, MsgType msgtype)
Definition: gx_logging.cpp:130
void unplug_queue()
Definition: gx_logging.cpp:82