diff options
-rw-r--r-- | include/gnuradio/gras.hpp | 24 | ||||
-rw-r--r-- | include/gnuradio/sbuffer.hpp | 127 | ||||
-rw-r--r-- | include/gnuradio/sbuffer.ipp | 106 | ||||
-rw-r--r-- | lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/gr_block.cpp | 2 | ||||
-rw-r--r-- | lib/sbuffer.cpp | 69 |
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(); +} |