1 // class for asynchronous logging
2 // Copyright (C) 2011 Tim Blechmann
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
19 #ifndef UTILITIES_ASYNCHRONOUS_LOG_HPP
20 #define UTILITIES_ASYNCHRONOUS_LOG_HPP
26 #include <boost/bind.hpp>
27 #include <boost/thread.hpp>
28 #include <boost/lockfree/ringbuffer.hpp>
29 #include <boost/mpl/if.hpp>
31 #include <nova-tt/semaphore.hpp>
34 namespace asynchronous_log_impl
{
36 using namespace boost
;
38 struct asynchronous_log
:
41 bool log_printf(const char *fmt
, ...)
46 bool result
= log_printf(fmt
, vargs
);
51 bool log_printf(const char *fmt
, va_list vargs
)
53 array
<char, 4096> scratchpad
;
54 int print_result
= vsnprintf(scratchpad
.c_array(), scratchpad
.size(), fmt
, vargs
);
56 if (print_result
>= scratchpad
.size())
57 fprintf(stderr
, "warning: log message truncated");
59 return log(scratchpad
.c_array(), print_result
);
62 bool log(const char * string
)
64 size_t length
= strlen(string
);
65 return log(string
, length
);
68 bool log(const char * string
, size_t length
)
70 size_t total_enqueued
= buffer
.enqueue(string
, length
);
71 if (total_enqueued
== 0)
76 if (total_enqueued
== length
)
79 string
+= total_enqueued
;
80 length
-= total_enqueued
;
83 size_t enqueued
= buffer
.enqueue(string
, length
);
89 if (enqueued
== length
)
92 string
+= total_enqueued
;
93 length
-= total_enqueued
;
99 size_t read_log(char * out_buffer
, size_t size
)
102 return read(out_buffer
, size
);
107 size_t read_log_waiting(char * out_buffer
, size_t size
)
110 return read(out_buffer
, size
);
113 size_t read(char * out_buffer
, size_t size
)
115 return buffer
.dequeue(out_buffer
, size
);
118 void interrrupt(void)
124 lockfree::ringbuffer
<char, 32768> buffer
;
128 struct asynchronous_log_thread
:
132 asynchronous_log_thread(void):
133 running_flag(true), thread_(bind(&asynchronous_log_thread::run
, this))
136 ~asynchronous_log_thread(void)
138 running_flag
= false;
145 while (running_flag
.load()) {
146 size_t read_chars
= read_log_waiting(out_buffer
.c_array(), out_buffer
.size());
147 post_outbuffer(read_chars
);
149 while (read_chars
== out_buffer
.size()) {
150 read_chars
= read(out_buffer
.c_array(), out_buffer
.size());
151 post_outbuffer(read_chars
);
154 size_t read_chars
= read_log(out_buffer
.c_array(), out_buffer
.size());
155 post_outbuffer(read_chars
);
158 void post_outbuffer(size_t read_chars
)
160 for (size_t i
= 0; i
!= read_chars
; ++i
)
161 putchar(out_buffer
[i
]);
167 atomic_bool running_flag
;
168 array
<char, 4096> out_buffer
;
171 } /* namespace asynchronous_log_impl */
173 using asynchronous_log_impl::asynchronous_log
;
174 using asynchronous_log_impl::asynchronous_log_thread
;
176 } /* namespace nova */
178 #endif /* UTILITIES_ASYNCHRONOUS_LOG_HPP */