summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/lib/io/gri_logger.cc
diff options
context:
space:
mode:
authorjcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5>2006-08-03 04:51:51 +0000
committerjcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5>2006-08-03 04:51:51 +0000
commit5d69a524f81f234b3fbc41d49ba18d6f6886baba (patch)
treeb71312bf7f1e8d10fef0f3ac6f28784065e73e72 /gnuradio-core/src/lib/io/gri_logger.cc
Houston, we have a trunk.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@3122 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gnuradio-core/src/lib/io/gri_logger.cc')
-rw-r--r--gnuradio-core/src/lib/io/gri_logger.cc173
1 files changed, 173 insertions, 0 deletions
diff --git a/gnuradio-core/src/lib/io/gri_logger.cc b/gnuradio-core/src/lib/io/gri_logger.cc
new file mode 100644
index 0000000000..a1bdfb0e28
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gri_logger.cc
@@ -0,0 +1,173 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gri_logger.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdexcept>
+#include <boost/weak_ptr.hpp>
+
+
+/*
+ * This class creates the thread that reads from the ringbuffer and
+ * and writes to the file. This is opaque to the user.
+ */
+class gri_log_poster : public omni_thread
+{
+ FILE *d_fp;
+ gr_buffer_sptr d_writer;
+ gr_buffer_reader_sptr d_reader;
+ omni_semaphore d_ringbuffer_ready;
+ volatile bool d_time_to_die;
+ volatile bool d_writer_overrun;
+
+ virtual void* run_undetached(void * arg);
+
+public:
+ gri_log_poster(const char *filename);
+ ~gri_log_poster();
+
+ void kill() { d_time_to_die = true; post(); }
+ gr_buffer_sptr writer() const { return d_writer; }
+ void post() { d_ringbuffer_ready.post(); }
+ void note_writer_overrun() { d_writer_overrun = true; }
+};
+
+gri_log_poster::gri_log_poster(const char *filename)
+ : omni_thread(),
+ d_ringbuffer_ready(1, 1), // binary semaphore
+ d_time_to_die(false),
+ d_writer_overrun(false)
+{
+ if ((d_fp = fopen(filename, "w")) == 0){
+ perror (filename);
+ throw std::runtime_error("can't open file");
+ }
+
+ // Create a 1MB buffer.
+ d_writer = gr_make_buffer(1 * 1024 * 1024, sizeof(unsigned char));
+ d_reader = gr_buffer_add_reader(d_writer, 0);
+
+ start_undetached(); // start the thread
+}
+
+gri_log_poster::~gri_log_poster()
+{
+ if (d_fp != 0){
+ fclose(d_fp);
+ d_fp = 0;
+ }
+}
+
+/*
+ * This is the body of the logging thread.
+ */
+void *
+gri_log_poster::run_undetached(void *arg)
+{
+ int nbytes;
+
+ //fprintf(stderr, "Enter: run_undetached!\n");
+
+ while (!d_time_to_die){
+ while ((nbytes = d_reader->items_available()) > 0){
+ fwrite(d_reader->read_pointer(), 1, nbytes, d_fp);
+ d_reader->update_read_pointer(nbytes);
+ }
+ fflush(d_fp);
+ d_ringbuffer_ready.wait();
+
+ if (d_writer_overrun){
+ fputs(">>>>> gri_logger: writer overrun. Info lost <<<<<\n", d_fp);
+ d_writer_overrun = false;
+ }
+ }
+
+ // fprintf(stderr, "Exit: run_undetached!\n");
+ return 0;
+}
+
+// ------------------------------------------------------------------------
+
+static boost::weak_ptr<gri_logger> s_singleton; // weak pointer IQ test ;-)
+static omni_mutex s_singleton_mutex;
+
+gri_logger_sptr
+gri_logger::singleton()
+{
+ omni_mutex_lock l(s_singleton_mutex);
+ gri_logger_sptr r;
+
+ if (r = s_singleton.lock())
+ return r;
+
+ r = gri_logger_sptr(new gri_logger("gri_logger.log"));
+ s_singleton = r;
+ return r;
+}
+
+
+gri_logger::gri_logger(const char *filename)
+{
+ d_poster = new gri_log_poster(filename);
+}
+
+gri_logger::~gri_logger()
+{
+ d_poster->kill();
+ d_poster->join(NULL);
+}
+
+void
+gri_logger::write(const void *buf, size_t count)
+{
+ omni_mutex_lock l(d_write_mutex);
+ gr_buffer_sptr writer = d_poster->writer();
+
+ // either write it all, or drop it on the ground
+ if (count <= (size_t) writer->space_available()){
+ memcpy(writer->write_pointer(), buf, count);
+ writer->update_write_pointer(count);
+ d_poster->post();
+ }
+ else {
+ d_poster->note_writer_overrun();
+ }
+}
+
+void
+gri_logger::printf(const char *format, ...)
+{
+ va_list ap;
+ char buf[4096];
+ int n;
+
+ va_start(ap, format);
+ n = vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+ if (n > -1 && n < (ssize_t) sizeof(buf))
+ write(buf, n);
+}