diff options
author | jcorgan | 2009-07-09 02:55:51 +0000 |
---|---|---|
committer | jcorgan | 2009-07-09 02:55:51 +0000 |
commit | c276a4ffee9314d2528166547abfd2c09d29713f (patch) | |
tree | 03b06ac67874342ba671a4a0405e006de1ece9ba /usrp/host/lib/circular_linked_list.h | |
parent | eefb51c0c0fac68d16544e492aebd883528607e1 (diff) | |
download | gnuradio-c276a4ffee9314d2528166547abfd2c09d29713f.tar.gz gnuradio-c276a4ffee9314d2528166547abfd2c09d29713f.tar.bz2 gnuradio-c276a4ffee9314d2528166547abfd2c09d29713f.zip |
Merged r11377:11390 from jcorgan/usrp-headers in to trunk.
* Public USRP(1) header files are now in their own source directory
and install into $(includedir)/usrp. This was done to avoid name
clashes in the top-level include directory.
Only users who are developing directly to libusrp in C++ are
affected; the GNU Radio C++ and Python APIs are unchanged.
The simple change required by this update is to change:
#include <usrp_*.h>
to #include
<usrp/usrp_*.h>
...in your source code.
* Removed usrp-inband code from tree (put into limbo directory.)
This code has become unmaintained and has started to suffer
from bitrot. A checkpoint tag has been made for anyone still
needing to use it:
http://gnuradio.org/svn/gnuradio/tags/checkpoints/trunk-20090708-pre-usrp-reorg
The plan during the 3.2->3.3 development cycle is to replace the
functions done by the in-band code with extensions to the existing
gr-usrp blocks using the new message passing architecture.
The USRP hardware FPGA code that provided the inband interface
has not been removed; however, it too has become unmaintained and
will likely be rewritten/replaced during the 3.3 timeframe.
The trunk passes distcheck.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@11394 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'usrp/host/lib/circular_linked_list.h')
-rw-r--r-- | usrp/host/lib/circular_linked_list.h | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/usrp/host/lib/circular_linked_list.h b/usrp/host/lib/circular_linked_list.h new file mode 100644 index 000000000..e495d609b --- /dev/null +++ b/usrp/host/lib/circular_linked_list.h @@ -0,0 +1,284 @@ +/* -*- 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 3, 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., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _CIRCULAR_LINKED_LIST_H_ +#define _CIRCULAR_LINKED_LIST_H_ + +#include <mld_threads.h> +#include <stdexcept> + +#define __INLINE__ inline + +#ifndef DO_DEBUG +#define DO_DEBUG 0 +#endif + +#if DO_DEBUG +#define DEBUG(X) do{X} while(0); +#else +#define DEBUG(X) do{} while(0); +#endif + +template <class T> class s_both; + +template <class T> class s_node +{ + typedef s_node<T>* s_node_ptr; + +private: + T d_object; + bool d_available; + s_node_ptr d_prev, d_next; + s_both<T>* d_both; + +public: + s_node (T l_object, + s_node_ptr l_prev = NULL, + s_node_ptr l_next = NULL) + : d_object (l_object), d_available (TRUE), d_prev (l_prev), + d_next (l_next), d_both (0) {}; + + __INLINE__ s_node (s_node_ptr l_prev, s_node_ptr l_next = NULL) { + s_node ((T) NULL, l_prev, l_next); }; + __INLINE__ s_node () { s_node (NULL, NULL, NULL); }; + __INLINE__ ~s_node () {}; + + void remove () { + d_prev->next (d_next); + d_next->prev (d_prev); + d_prev = d_next = this; + }; + + void insert_before (s_node_ptr l_next) { + if (l_next) { + s_node_ptr l_prev = l_next->prev (); + d_next = l_next; + d_prev = l_prev; + l_prev->next (this); + l_next->prev (this); + } else + d_next = d_prev = this; + }; + + void insert_after (s_node_ptr l_prev) { + if (l_prev) { + s_node_ptr l_next = l_prev->next (); + d_prev = l_prev; + d_next = l_next; + l_next->prev (this); + l_prev->next (this); + } else + d_prev = d_next = this; + }; + + __INLINE__ T object () { return (d_object); }; + __INLINE__ void object (T l_object) { d_object = l_object; }; + __INLINE__ bool available () { return (d_available); }; + __INLINE__ void set_available () { d_available = TRUE; }; + __INLINE__ void set_available (bool l_avail) { d_available = l_avail; }; + __INLINE__ void set_not_available () { d_available = FALSE; }; + __INLINE__ s_node_ptr next () { return (d_next); }; + __INLINE__ s_node_ptr prev () { return (d_prev); }; + __INLINE__ s_both<T>* both () { return (d_both); }; + __INLINE__ void next (s_node_ptr l_next) { d_next = l_next; }; + __INLINE__ void prev (s_node_ptr l_prev) { d_prev = l_prev; }; + __INLINE__ void both (s_both<T>* l_both) { d_both = l_both; }; +}; + +template <class T> class circular_linked_list { + typedef s_node<T>* s_node_ptr; + +private: + s_node_ptr d_current, d_iterate, d_available, d_inUse; + UInt32 d_n_nodes, d_n_used; + mld_mutex_ptr d_internal; + mld_condition_ptr d_ioBlock; + +public: + circular_linked_list (UInt32 n_nodes) { + if (n_nodes == 0) + throw std::runtime_error ("circular_linked_list(): n_nodes == 0"); + + d_iterate = NULL; + d_n_nodes = n_nodes; + d_n_used = 0; + s_node_ptr l_prev, l_next; + d_inUse = d_current = l_next = l_prev = NULL; + + l_prev = new s_node<T> (); + l_prev->set_available (); + l_prev->next (l_prev); + l_prev->prev (l_prev); + if (n_nodes > 1) { + l_next = new s_node<T> (l_prev, l_prev); + l_next->set_available (); + l_next->next (l_prev); + l_next->prev (l_prev); + l_prev->next (l_next); + l_prev->prev (l_next); + if (n_nodes > 2) { + UInt32 n = n_nodes - 2; + while (n-- > 0) { + d_current = new s_node<T> (l_prev, l_next); + d_current->set_available (); + d_current->prev (l_prev); + d_current->next (l_next); + l_prev->next (d_current); + l_next->prev (d_current); + l_next = d_current; + d_current = NULL; + } + } + } + d_available = d_current = l_prev; + d_ioBlock = new mld_condition (); + d_internal = d_ioBlock->mutex (); + }; + + ~circular_linked_list () { + iterate_start (); + s_node_ptr l_node = iterate_next (); + while (l_node) { + delete l_node; + l_node = iterate_next (); + } + delete d_ioBlock; + d_ioBlock = NULL; + d_available = d_inUse = d_iterate = d_current = NULL; + d_n_used = d_n_nodes = 0; + }; + + s_node_ptr find_next_available_node () { + d_internal->lock (); +// find an available node + s_node_ptr l_node = d_available; + DEBUG (fprintf (stderr, "w ");); + while (! l_node) { + DEBUG (fprintf (stderr, "x\n");); + // the ioBlock condition will automatically unlock() d_internal + d_ioBlock->wait (); + // and lock() is here + DEBUG (fprintf (stderr, "y\n");); + l_node = d_available; + } + DEBUG (fprintf (stderr, "::f_n_a_n: #u = %ld, node = %p\n", + num_used(), l_node);); +// remove this one from the current available list + if (num_available () == 1) { +// last one, just set available to NULL + d_available = NULL; + } else + d_available = l_node->next (); + l_node->remove (); +// add is to the inUse list + if (! d_inUse) + d_inUse = l_node; + else + l_node->insert_before (d_inUse); + d_n_used++; + l_node->set_not_available (); + d_internal->unlock (); + return (l_node); + }; + + void make_node_available (s_node_ptr l_node) { + if (!l_node) return; + d_internal->lock (); + DEBUG (fprintf (stderr, "::m_n_a: #u = %ld, node = %p\n", + num_used(), l_node);); +// remove this node from the inUse list + if (num_used () == 1) { +// last one, just set inUse to NULL + d_inUse = NULL; + } else + d_inUse = l_node->next (); + l_node->remove (); +// add this node to the available list + if (! d_available) + d_available = l_node; + else + l_node->insert_before (d_available); + d_n_used--; + + DEBUG (fprintf (stderr, "s%ld ", d_n_used);); +// signal the condition when new data arrives + d_ioBlock->signal (); + DEBUG (fprintf (stderr, "t ");); + +// unlock the mutex for thread safety + d_internal->unlock (); + }; + + __INLINE__ void iterate_start () { d_iterate = d_current; }; + + s_node_ptr iterate_next () { +#if 0 +// lock the mutex for thread safety + d_internal->lock (); +#endif + s_node_ptr l_this = NULL; + if (d_iterate) { + l_this = d_iterate; + d_iterate = d_iterate->next (); + if (d_iterate == d_current) + d_iterate = NULL; + } +#if 0 +// unlock the mutex for thread safety + d_internal->unlock (); +#endif + return (l_this); + }; + + __INLINE__ T object () { return (d_current->d_object); }; + __INLINE__ void object (T l_object) { d_current->d_object = l_object; }; + __INLINE__ UInt32 num_nodes () { return (d_n_nodes); }; + __INLINE__ UInt32 num_used () { return (d_n_used); }; + __INLINE__ void num_used (UInt32 l_n_used) { d_n_used = l_n_used; }; + __INLINE__ UInt32 num_available () { return (d_n_nodes - d_n_used); }; + __INLINE__ void num_used_inc (void) { + if (d_n_used < d_n_nodes) ++d_n_used; + }; + __INLINE__ void num_used_dec (void) { + if (d_n_used != 0) --d_n_used; +// signal the condition that new data has arrived + d_ioBlock->signal (); + }; + __INLINE__ bool in_use () { return (d_n_used != 0); }; +}; + +template <class T> class s_both +{ +private: + s_node<T>* d_node; + void* d_this; +public: + __INLINE__ s_both (s_node<T>* l_node, void* l_this) + : d_node (l_node), d_this (l_this) {}; + __INLINE__ ~s_both () {}; + __INLINE__ s_node<T>* node () { return (d_node); }; + __INLINE__ void* This () { return (d_this); }; + __INLINE__ void set (s_node<T>* l_node, void* l_this) { + d_node = l_node; d_this = l_this;}; +}; + +#endif /* _CIRCULAR_LINKED_LIST_H_ */ |