summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gnuradio/gras.hpp24
-rw-r--r--include/gnuradio/sbuffer.hpp127
-rw-r--r--include/gnuradio/sbuffer.ipp106
-rw-r--r--lib/CMakeLists.txt1
-rw-r--r--lib/gr_block.cpp2
-rw-r--r--lib/sbuffer.cpp69
6 files changed, 328 insertions, 1 deletions
diff --git a/include/gnuradio/gras.hpp b/include/gnuradio/gras.hpp
index c8b217c..23aab4c 100644
--- a/include/gnuradio/gras.hpp
+++ b/include/gnuradio/gras.hpp
@@ -19,16 +19,40 @@
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
//this is part of core for now, treat it as such
#include <gr_core_api.h>
#define GRAS_API GR_CORE_API
+#define GRAS_MAX_ALIGNMENT 32
+
namespace gnuradio
{
struct ElementImpl;
+struct SBuffer;
+struct SBufferImpl;
+
+void intrusive_ptr_add_ref(SBufferImpl*);
+void intrusive_ptr_release(SBufferImpl*);
+
+struct Affinity
+{
+ Affinity(void)
+ {
+ value = -1;
+ }
+
+ operator long long(void) const
+ {
+ return value;
+ }
+
+ long long value;
+};
+
} //namespace gnuradio
#endif /*INCLUDED_GNURADIO_GRAS_HPP*/
diff --git a/include/gnuradio/sbuffer.hpp b/include/gnuradio/sbuffer.hpp
new file mode 100644
index 0000000..0db6c05
--- /dev/null
+++ b/include/gnuradio/sbuffer.hpp
@@ -0,0 +1,127 @@
+//
+// Copyright 2012 Josh Blum
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef INCLUDED_GNURADIO_SBUFFER_HPP
+#define INCLUDED_GNURADIO_SBUFFER_HPP
+
+#include <gnuradio/gras.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/function.hpp>
+
+namespace gnuradio
+{
+
+//! The callback function type when buffers dereference
+typedef boost::function<void(SBuffer &)> SBufferDeleter;
+
+//! The token type held by the caller
+typedef boost::shared_ptr<SBufferDeleter> SBufferToken;
+
+//! The token type weak ptr help by buffer
+typedef boost::weak_ptr<SBufferDeleter> SBufferTokenWeak;
+
+struct GRAS_API SBufferConfig
+{
+ //! Default constructor zeros out buffer config
+ SBufferConfig(void);
+
+ //! pointer to the memory start
+ void *memory;
+
+ //! length of the memory in bytes
+ size_t length;
+
+ //! memory affinity - meta information
+ Affinity affinity;
+
+ //! deleter callback, may be used to free
+ SBufferDeleter deleter;
+
+ //! token object, called if set under deref condition
+ SBufferTokenWeak token;
+};
+
+/*!
+ * Buffer is a reference counted smart pointer handler of memory.
+ *
+ * Default allocator:
+ * To use the default system allocator, set the memory to NULL,
+ * and set length and affinity to the desired values.
+ * The deleter will be automaically configured by the allocator.
+ *
+ * Custom allocator:
+ * Set all config struct members. Its all you!
+ *
+ * Token usage:
+ * When a token is set, the buffer will not cleanup and call the deleter.
+ * Rather, the bound function in the token will be called with the buffer.
+ * A parent object should hold the shared pointer to the token.
+ * When the parent object deconstructs, the weak pointer will die,
+ * and the normal buffer cleanup/freeing/deconstruction will happen.
+ *
+ * Length and memory usage:
+ * Length and memory are intentionally references
+ * so that they can be modified (carefully).
+ * The user may do this to pass a subset of the memory.
+ * Using the token causes a reset of these values.
+ */
+struct GRAS_API SBuffer : boost::intrusive_ptr<SBufferImpl>
+{
+ //! Default constructor, zeros things
+ SBuffer(void);
+
+ /*!
+ * Create a new buffer.
+ * The config object represents a chunk of memory,
+ * or instructions for the default allocator.
+ */
+ SBuffer(const SBufferConfig &config);
+
+ /*!
+ * Get a pointer to the start of the underlying memory
+ */
+ void *get_actual_memory(void) const;
+
+ /*!
+ * Get the length of the underlying memory in bytes
+ */
+ size_t get_actual_length(void) const;
+
+ //! Get a pointer into valid memory
+ void *get(void) const;
+
+ //! The offset into valid memory in bytes
+ size_t offset;
+
+ //! The number of valid bytes past offset
+ size_t length;
+
+ //! Get the affinity of the memory
+ Affinity get_affinity(void) const;
+
+ //! Unique if caller holds the only reference count
+ bool unique(void) const;
+
+ //! Get the number of reference holders
+ size_t use_count(void) const;
+};
+
+} //namespace gnuradio
+
+#include <gnuradio/sbuffer.ipp>
+
+#endif /*INCLUDED_GNURADIO_SBUFFER_HPP*/
diff --git a/include/gnuradio/sbuffer.ipp b/include/gnuradio/sbuffer.ipp
new file mode 100644
index 0000000..f290b7c
--- /dev/null
+++ b/include/gnuradio/sbuffer.ipp
@@ -0,0 +1,106 @@
+//
+// Copyright 2012 Josh Blum
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef INCLUDED_GNURADIO_SBUFFER_IPP
+#define INCLUDED_GNURADIO_SBUFFER_IPP
+
+#include <boost/detail/atomic_count.hpp>
+
+namespace gnuradio
+{
+
+struct SBufferImpl
+{
+ SBufferImpl(const SBufferConfig &config):
+ count(0),
+ config(config)
+ {
+ //NOP
+ }
+
+ boost::detail::atomic_count count;
+ size_t __pad; //avoid a probably non-issue w/ count
+ SBufferConfig config;
+};
+
+inline void intrusive_ptr_add_ref(SBufferImpl *impl)
+{
+ ++impl->count;
+}
+
+inline void intrusive_ptr_release(SBufferImpl *impl)
+{
+ if (--impl->count == 0)
+ {
+ //call the deleter if possible
+ boost::shared_ptr<SBufferDeleter> token_deleter = impl->config.token.lock();
+ if (token_deleter)
+ {
+ SBuffer buff;
+ (*token_deleter)(buff);
+ }
+ else if (impl->config.deleter)
+ {
+ SBuffer buff;
+ impl->config.deleter(buff);
+ impl->config.deleter = SBufferDeleter(); //reset deleter, so we dont double delete
+ }
+ else
+ {
+ delete impl; //its really dead now
+ }
+ }
+}
+
+inline SBufferConfig::SBufferConfig(void)
+{
+ memory = NULL;
+ length = 0;
+}
+
+inline void *SBuffer::get_actual_memory(void) const
+{
+ return (*this)->config.memory;
+}
+
+inline size_t SBuffer::get_actual_length(void) const
+{
+ return (*this)->config.length;
+}
+
+inline void *SBuffer::get(void) const
+{
+ return ((char *)(*this)->config.memory) + this->offset;
+}
+
+inline Affinity SBuffer::get_affinity(void) const
+{
+ return (*this)->config.affinity;
+}
+
+inline bool SBuffer::unique(void) const
+{
+ return (*this)->count == 1;
+}
+
+inline size_t SBuffer::use_count(void) const
+{
+ return (*this)->count;
+}
+
+} //namespace gnuradio
+
+#endif /*INCLUDED_GNURADIO_SBUFFER_IPP*/
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 8baa38d..414e13a 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -23,6 +23,7 @@ endif()
########################################################################
list(APPEND gnuradio_core_sources
${CMAKE_CURRENT_SOURCE_DIR}/element.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/sbuffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/block.cpp
${CMAKE_CURRENT_SOURCE_DIR}/block_task.cpp
${CMAKE_CURRENT_SOURCE_DIR}/block_allocator.cpp
diff --git a/lib/gr_block.cpp b/lib/gr_block.cpp
index ce1b09e..1f59bb1 100644
--- a/lib/gr_block.cpp
+++ b/lib/gr_block.cpp
@@ -67,7 +67,7 @@ bool gr_block::is_unaligned(void)
//TODO
//probably dont need this since volk dispatcher checks alignment
//32 byte aligned is good enough for you
- return ((*this)->work_io_ptr_mask & ptrdiff_t(0x1f)) != 0;
+ return ((*this)->work_io_ptr_mask & ptrdiff_t(GRAS_MAX_ALIGNMENT-1)) != 0;
}
size_t gr_block::fixed_rate_noutput_to_ninput(const size_t noutput_items)
diff --git a/lib/sbuffer.cpp b/lib/sbuffer.cpp
new file mode 100644
index 0000000..2877b2e
--- /dev/null
+++ b/lib/sbuffer.cpp
@@ -0,0 +1,69 @@
+//
+// Copyright 2012 Josh Blum
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with io_sig program. If not, see <http://www.gnu.org/licenses/>.
+
+#include <gnuradio/sbuffer.hpp>
+#include <numanuma.hpp>
+#include <boost/bind.hpp>
+
+using namespace gnuradio;
+
+static void numanuma_mem_deleter(SBuffer &, numanuma::mem *m)
+{
+ delete m;
+}
+
+static void default_allocator_deleter(SBuffer &, char *m)
+{
+ delete m;
+}
+
+static void default_allocator(SBufferConfig &config)
+{
+ if (config.affinity == Affinity())
+ {
+ char *m = new char[config.length + GRAS_MAX_ALIGNMENT - 1];
+ size_t x = size_t(m) + GRAS_MAX_ALIGNMENT - 1;
+ x -= x % GRAS_MAX_ALIGNMENT;
+ config.memory = (void *)x;
+ config.deleter = boost::bind(&default_allocator_deleter, _1, m);
+ }
+ else
+ {
+ numanuma::mem *m = numanuma::mem::make(config.affinity, config.length);
+ config.memory = m->get();
+ config.length = m->len();
+ config.deleter = boost::bind(&numanuma_mem_deleter, _1, m);
+ }
+}
+
+SBuffer::SBuffer(void):
+ offset(0),
+ length(0)
+{
+ //NOP
+}
+
+SBuffer::SBuffer(const SBufferConfig &config):
+ offset(0),
+ length(0)
+{
+ this->reset(new SBufferImpl(config));
+ if (config.memory == NULL)
+ {
+ default_allocator((*this)->config);
+ }
+ this->length = this->get_actual_length();
+}