3 * Copyright 2006 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Radio; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
27 #include <gri_logger.h>
31 #include <boost/weak_ptr.hpp>
35 * This class creates the thread that reads from the ringbuffer and
36 * and writes to the file. This is opaque to the user.
38 class gri_log_poster : public omni_thread
41 gr_buffer_sptr d_writer;
42 gr_buffer_reader_sptr d_reader;
43 omni_semaphore d_ringbuffer_ready;
44 volatile bool d_time_to_die;
45 volatile bool d_writer_overrun;
47 virtual void* run_undetached(void * arg);
50 gri_log_poster(const char *filename);
53 void kill() { d_time_to_die = true; post(); }
54 gr_buffer_sptr writer() const { return d_writer; }
55 void post() { d_ringbuffer_ready.post(); }
56 void note_writer_overrun() { d_writer_overrun = true; }
59 gri_log_poster::gri_log_poster(const char *filename)
61 d_ringbuffer_ready(1, 1), // binary semaphore
63 d_writer_overrun(false)
65 if ((d_fp = fopen(filename, "w")) == 0){
67 throw std::runtime_error("can't open file");
70 // Create a 1MB buffer.
71 d_writer = gr_make_buffer(1 * 1024 * 1024, sizeof(unsigned char));
72 d_reader = gr_buffer_add_reader(d_writer, 0);
74 start_undetached(); // start the thread
77 gri_log_poster::~gri_log_poster()
86 * This is the body of the logging thread.
89 gri_log_poster::run_undetached(void *arg)
93 //fprintf(stderr, "Enter: run_undetached!\n");
95 while (!d_time_to_die){
96 while ((nbytes = d_reader->items_available()) > 0){
97 fwrite(d_reader->read_pointer(), 1, nbytes, d_fp);
98 d_reader->update_read_pointer(nbytes);
101 d_ringbuffer_ready.wait();
103 if (d_writer_overrun){
104 fputs(">>>>> gri_logger: writer overrun. Info lost <<<<<\n", d_fp);
105 d_writer_overrun = false;
109 // fprintf(stderr, "Exit: run_undetached!\n");
113 // ------------------------------------------------------------------------
115 static boost::weak_ptr<gri_logger> s_singleton; // weak pointer IQ test ;-)
116 static omni_mutex s_singleton_mutex;
119 gri_logger::singleton()
121 omni_mutex_lock l(s_singleton_mutex);
124 if (r = s_singleton.lock())
127 r = gri_logger_sptr(new gri_logger("gri_logger.log"));
133 gri_logger::gri_logger(const char *filename)
135 d_poster = new gri_log_poster(filename);
138 gri_logger::~gri_logger()
141 d_poster->join(NULL);
145 gri_logger::write(const void *buf, size_t count)
147 omni_mutex_lock l(d_write_mutex);
148 gr_buffer_sptr writer = d_poster->writer();
150 // either write it all, or drop it on the ground
151 if (count <= (size_t) writer->space_available()){
152 memcpy(writer->write_pointer(), buf, count);
153 writer->update_write_pointer(count);
157 d_poster->note_writer_overrun();
162 gri_logger::printf(const char *format, ...)
168 va_start(ap, format);
169 n = vsnprintf(buf, sizeof(buf), format, ap);
171 if (n > -1 && n < (ssize_t) sizeof(buf))