diff options
Diffstat (limited to 'gruel/src/include')
-rw-r--r-- | gruel/src/include/gruel/CMakeLists.txt | 39 | ||||
-rw-r--r-- | gruel/src/include/gruel/api.h | 33 | ||||
-rw-r--r-- | gruel/src/include/gruel/attributes.h | 74 | ||||
-rw-r--r-- | gruel/src/include/gruel/high_res_timer.h | 124 | ||||
-rw-r--r-- | gruel/src/include/gruel/msg_accepter.h | 53 | ||||
-rw-r--r-- | gruel/src/include/gruel/msg_accepter_msgq.h | 50 | ||||
-rw-r--r-- | gruel/src/include/gruel/msg_passing.h | 116 | ||||
-rw-r--r-- | gruel/src/include/gruel/msg_queue.h | 91 | ||||
-rw-r--r-- | gruel/src/include/gruel/pmt.h | 864 | ||||
-rw-r--r-- | gruel/src/include/gruel/pmt_pool.h | 73 | ||||
-rw-r--r-- | gruel/src/include/gruel/pmt_sugar.h | 171 | ||||
-rw-r--r-- | gruel/src/include/gruel/realtime.h | 96 | ||||
-rw-r--r-- | gruel/src/include/gruel/sys_pri.h | 42 | ||||
-rw-r--r-- | gruel/src/include/gruel/thread.h | 139 | ||||
-rw-r--r-- | gruel/src/include/gruel/thread_body_wrapper.h | 69 | ||||
-rw-r--r-- | gruel/src/include/gruel/thread_group.h | 45 |
16 files changed, 2079 insertions, 0 deletions
diff --git a/gruel/src/include/gruel/CMakeLists.txt b/gruel/src/include/gruel/CMakeLists.txt new file mode 100644 index 000000000..d4c36eddb --- /dev/null +++ b/gruel/src/include/gruel/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright 2010-2012 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. + +######################################################################## +# Install the headers +######################################################################## +install(FILES + api.h + attributes.h + high_res_timer.h + msg_accepter.h + msg_accepter_msgq.h + msg_queue.h + msg_passing.h + pmt.h + pmt_pool.h + pmt_sugar.h + realtime.h + sys_pri.h + thread_body_wrapper.h + thread_group.h + thread.h +DESTINATION ${GR_INCLUDE_DIR}/gruel COMPONENT "gruel_devel") diff --git a/gruel/src/include/gruel/api.h b/gruel/src/include/gruel/api.h new file mode 100644 index 000000000..945814d43 --- /dev/null +++ b/gruel/src/include/gruel/api.h @@ -0,0 +1,33 @@ +/* + * Copyright 2010 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 INCLUDED_GRUEL_API_H +#define INCLUDED_GRUEL_API_H + +#include <gruel/attributes.h> + +#ifdef gruel_EXPORTS +# define GRUEL_API __GR_ATTR_EXPORT +#else +# define GRUEL_API __GR_ATTR_IMPORT +#endif + +#endif /* INCLUDED_GRUEL_API_H */ diff --git a/gruel/src/include/gruel/attributes.h b/gruel/src/include/gruel/attributes.h new file mode 100644 index 000000000..baa5521c8 --- /dev/null +++ b/gruel/src/include/gruel/attributes.h @@ -0,0 +1,74 @@ +/* + * Copyright 2010 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 INCLUDED_GRUEL_ATTRIBUTES_H +#define INCLUDED_GRUEL_ATTRIBUTES_H + +//////////////////////////////////////////////////////////////////////// +// Cross-platform attribute macros +//////////////////////////////////////////////////////////////////////// +#if defined __GNUC__ +# define __GR_ATTR_ALIGNED(x) __attribute__((aligned(x))) +# define __GR_ATTR_UNUSED __attribute__((unused)) +# define __GR_ATTR_INLINE __attribute__((always_inline)) +# define __GR_ATTR_DEPRECATED __attribute__((deprecated)) +# if __GNUC__ >= 4 +# define __GR_ATTR_EXPORT __attribute__((visibility("default"))) +# define __GR_ATTR_IMPORT __attribute__((visibility("default"))) +# else +# define __GR_ATTR_EXPORT +# define __GR_ATTR_IMPORT +# endif +#elif _MSC_VER +# define __GR_ATTR_ALIGNED(x) __declspec(align(x)) +# define __GR_ATTR_UNUSED +# define __GR_ATTR_INLINE __forceinline +# define __GR_ATTR_DEPRECATED __declspec(deprecated) +# define __GR_ATTR_EXPORT __declspec(dllexport) +# define __GR_ATTR_IMPORT __declspec(dllimport) +#else +# define __GR_ATTR_ALIGNED(x) +# define __GR_ATTR_UNUSED +# define __GR_ATTR_INLINE +# define __GR_ATTR_DEPRECATED +# define __GR_ATTR_EXPORT +# define __GR_ATTR_IMPORT +#endif + +//////////////////////////////////////////////////////////////////////// +// define inline when building C +//////////////////////////////////////////////////////////////////////// +#if defined(_MSC_VER) && !defined(__cplusplus) && !defined(inline) +# define inline __inline +#endif + +//////////////////////////////////////////////////////////////////////// +// suppress warnings +//////////////////////////////////////////////////////////////////////// +#ifdef _MSC_VER +# pragma warning(disable: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B' +# pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ... +# pragma warning(disable: 4244) // conversion from 'double' to 'float', possible loss of data +# pragma warning(disable: 4305) // 'initializing' : truncation from 'double' to 'float' +# pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif + +#endif /* INCLUDED_GRUEL_ATTRIBUTES_H */ diff --git a/gruel/src/include/gruel/high_res_timer.h b/gruel/src/include/gruel/high_res_timer.h new file mode 100644 index 000000000..a885520b6 --- /dev/null +++ b/gruel/src/include/gruel/high_res_timer.h @@ -0,0 +1,124 @@ +/* + * Copyright 2011 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef INCLUDED_GRUEL_HIGH_RES_TIMER_H +#define INCLUDED_GRUEL_HIGH_RES_TIMER_H + +namespace gruel { + //! Typedef for the timer tick count + typedef signed long long high_res_timer_type; + + //! Get the current time in ticks + high_res_timer_type high_res_timer_now(void); + + //! Get the number of ticks per second + high_res_timer_type high_res_timer_tps(void); + + //! Get the tick count at the epoch + high_res_timer_type high_res_timer_epoch(void); + +} /* namespace gruel */ + +//////////////////////////////////////////////////////////////////////// +// Use architecture defines to determine the implementation +//////////////////////////////////////////////////////////////////////// +#if defined(linux) || defined(__linux) || defined(__linux__) + #define GRUEL_HRT_USE_CLOCK_GETTIME +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + #define GRUEL_HRT_USE_QUERY_PERFORMANCE_COUNTER +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + #define GRUEL_HRT_USE_MACH_ABSOLUTE_TIME +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + #define GRUEL_HRT_USE_CLOCK_GETTIME +#else + #define GRUEL_HRT_USE_MICROSEC_CLOCK +#endif + +//////////////////////////////////////////////////////////////////////// +#ifdef GRUEL_HRT_USE_CLOCK_GETTIME + #include <ctime> + + inline gruel::high_res_timer_type gruel::high_res_timer_now(void){ + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec*high_res_timer_tps() + ts.tv_nsec; + } + + inline gruel::high_res_timer_type gruel::high_res_timer_tps(void){ + return 1000000000UL; + } +#endif /* GRUEL_HRT_USE_CLOCK_GETTIME */ + +//////////////////////////////////////////////////////////////////////// +#ifdef GRUEL_HRT_USE_MACH_ABSOLUTE_TIME + #include <mach/mach_time.h> + + inline gruel::high_res_timer_type gruel::high_res_timer_now(void){ + return mach_absolute_time(); + } + + inline gruel::high_res_timer_type gruel::high_res_timer_tps(void){ + mach_timebase_info_data_t info; + mach_timebase_info(&info); + return gruel::high_res_timer_type(info.numer*1000000000UL)/info.denom; + } +#endif + +//////////////////////////////////////////////////////////////////////// +#ifdef GRUEL_HRT_USE_QUERY_PERFORMANCE_COUNTER + #include <Windows.h> + + inline gruel::high_res_timer_type gruel::high_res_timer_now(void){ + LARGE_INTEGER counts; + QueryPerformanceCounter(&counts); + return counts.QuadPart; + } + + inline gruel::high_res_timer_type gruel::high_res_timer_tps(void){ + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + return freq.QuadPart; + } +#endif + +//////////////////////////////////////////////////////////////////////// +#ifdef GRUEL_HRT_USE_MICROSEC_CLOCK + #include <boost/date_time/posix_time/posix_time.hpp> + + inline gruel::high_res_timer_type gruel::high_res_timer_now(void){ + static const boost::posix_time::ptime epoch(boost::posix_time::from_time_t(0)); + return (boost::posix_time::microsec_clock::universal_time() - epoch).ticks(); + } + + inline gruel::high_res_timer_type gruel::high_res_timer_tps(void){ + return boost::posix_time::time_duration::ticks_per_second(); + } +#endif + +//////////////////////////////////////////////////////////////////////// +#include <boost/date_time/posix_time/posix_time.hpp> + +inline gruel::high_res_timer_type gruel::high_res_timer_epoch(void){ + static const double hrt_ticks_per_utc_ticks = gruel::high_res_timer_tps()/double(boost::posix_time::time_duration::ticks_per_second()); + boost::posix_time::time_duration utc = boost::posix_time::microsec_clock::universal_time() - boost::posix_time::from_time_t(0); + return gruel::high_res_timer_now() - utc.ticks()*hrt_ticks_per_utc_ticks; +} + +#endif /* INCLUDED_GRUEL_HIGH_RES_TIMER_H */ diff --git a/gruel/src/include/gruel/msg_accepter.h b/gruel/src/include/gruel/msg_accepter.h new file mode 100644 index 000000000..45acb3c78 --- /dev/null +++ b/gruel/src/include/gruel/msg_accepter.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GRUEL_MSG_ACCEPTER_H +#define INCLUDED_GRUEL_MSG_ACCEPTER_H + +#include <gruel/api.h> +#include <gruel/pmt.h> +#include <boost/shared_ptr.hpp> + +namespace gruel { + + /*! + * \brief Virtual base class that accepts messages + */ + class GRUEL_API msg_accepter + { + public: + msg_accepter() {}; + virtual ~msg_accepter(); + + /*! + * \brief send \p msg to \p msg_accepter on port \p which_port + * + * Sending a message is an asynchronous operation. The \p post + * call will not wait for the message either to arrive at the + * destination or to be received. + */ + virtual void post(pmt::pmt_t which_port, pmt::pmt_t msg) = 0; + }; + + typedef boost::shared_ptr<msg_accepter> msg_accepter_sptr; + +} /* namespace gruel */ + +#endif /* INCLUDED_GRUEL_MSG_ACCEPTER_H */ diff --git a/gruel/src/include/gruel/msg_accepter_msgq.h b/gruel/src/include/gruel/msg_accepter_msgq.h new file mode 100644 index 000000000..6b9bcf4db --- /dev/null +++ b/gruel/src/include/gruel/msg_accepter_msgq.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef INCLUDED_MSG_ACCEPTER_MSGQ_H +#define INCLUDED_MSG_ACCEPTER_MSGQ_H + +#include <gruel/api.h> +#include <gruel/msg_accepter.h> +#include <gruel/msg_queue.h> + +namespace gruel { + + /*! + * \brief Concrete class that accepts messages and inserts them into a message queue. + */ + class GRUEL_API msg_accepter_msgq : public msg_accepter + { + protected: + msg_queue_sptr d_msg_queue; + + public: + msg_accepter_msgq(msg_queue_sptr msgq); + ~msg_accepter_msgq(); + + virtual void post(pmt::pmt_t msg); + + msg_queue_sptr msg_queue() const { return d_msg_queue; } + }; + +} /* namespace gruel */ + +#endif /* INCLUDED_MSG_ACCEPTER_MSGQ_H */ diff --git a/gruel/src/include/gruel/msg_passing.h b/gruel/src/include/gruel/msg_passing.h new file mode 100644 index 000000000..25f30118f --- /dev/null +++ b/gruel/src/include/gruel/msg_passing.h @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GRUEL_MSG_PASSING_H +#define INCLUDED_GRUEL_MSG_PASSING_H + +/*! + * \brief Include this header to use the message passing features + */ + +#include <gruel/api.h> +#include <gruel/pmt.h> +#include <gruel/msg_accepter.h> + + +namespace gruel { + + /*! + * \brief send message to msg_accepter + * + * \param accepter is the target of the send. + * \param which_port A pmt symbol describing the port by name. + * \param msg is the message to send. It's usually a pmt tuple. + * + * Sending a message is an asynchronous operation. The \p send + * call will not wait for the message either to arrive at the + * destination or to be received. + * + * \returns msg + */ + static inline pmt::pmt_t + send(msg_accepter_sptr accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg) + { + accepter->post(which_port, msg); + return msg; + } + + /*! + * \brief send message to msg_accepter + * + * \param accepter is the target of the send. + * \param which_port A pmt symbol describing the port by name. + * \param msg is the message to send. It's usually a pmt tuple. + * + * Sending a message is an asynchronous operation. The \p send + * call will not wait for the message either to arrive at the + * destination or to be received. + * + * \returns msg + */ + static inline pmt::pmt_t + send(msg_accepter *accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg) + { + accepter->post(which_port, msg); + return msg; + } + + /*! + * \brief send message to msg_accepter + * + * \param accepter is the target of the send. + * \param which_port A pmt symbol describing the port by name. + * \param msg is the message to send. It's usually a pmt tuple. + * + * Sending a message is an asynchronous operation. The \p send + * call will not wait for the message either to arrive at the + * destination or to be received. + * + * \returns msg + */ + static inline pmt::pmt_t + send(msg_accepter &accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg) + { + accepter.post(which_port, msg); + return msg; + } + + /*! + * \brief send message to msg_accepter + * + * \param accepter is the target of the send. precond: pmt_is_msg_accepter(accepter) + * \param which_port A pmt symbol describing the port by name. + * \param msg is the message to send. It's usually a pmt tuple. + * + * Sending a message is an asynchronous operation. The \p send + * call will not wait for the message either to arrive at the + * destination or to be received. + * + * \returns msg + */ + static inline pmt::pmt_t + send(pmt::pmt_t accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg) + { + return send(pmt_msg_accepter_ref(accepter), which_port, msg); + } + +} /* namespace gruel */ + +#endif /* INCLUDED_GRUEL_MSG_PASSING_H */ diff --git a/gruel/src/include/gruel/msg_queue.h b/gruel/src/include/gruel/msg_queue.h new file mode 100644 index 000000000..f038ca325 --- /dev/null +++ b/gruel/src/include/gruel/msg_queue.h @@ -0,0 +1,91 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 INCLUDED_MSG_QUEUE_H +#define INCLUDED_MSG_QUEUE_H + +#include <gruel/api.h> +#include <gruel/thread.h> +#include <gruel/pmt.h> +#include <deque> + +namespace gruel { + + class msg_queue; + typedef boost::shared_ptr<msg_queue> msg_queue_sptr; + + msg_queue_sptr make_msg_queue(unsigned int limit=0); + + /*! + * \brief thread-safe message queue + */ + class GRUEL_API msg_queue { + + gruel::mutex d_mutex; + gruel::condition_variable d_not_empty; + gruel::condition_variable d_not_full; + unsigned int d_limit; // max # of messages in queue. 0 -> unbounded + + std::deque<pmt::pmt_t> d_msgs; + + public: + msg_queue(unsigned int limit); + ~msg_queue(); + + /*! + * \brief Insert message at tail of queue. + * \param msg message + * + * Block if queue if full. + */ + void insert_tail(pmt::pmt_t msg); + + /*! + * \brief Delete message from head of queue and return it. + * Block if no message is available. + */ + pmt::pmt_t delete_head(); + + /*! + * \brief If there's a message in the q, delete it and return it. + * If no message is available, return pmt_t(). + */ + pmt::pmt_t delete_head_nowait(); + + //! Delete all messages from the queue + void flush(); + + //! is the queue empty? + bool empty_p() const { return d_msgs.empty(); } + + //! is the queue full? + bool full_p() const { return d_limit != 0 && count() >= d_limit; } + + //! return number of messages in queue + unsigned int count() const { return d_msgs.size(); } + + //! return limit on number of message in queue. 0 -> unbounded + unsigned int limit() const { return d_limit; } + }; + +} /* namespace gruel */ + +#endif /* INCLUDED_MSG_QUEUE_H */ diff --git a/gruel/src/include/gruel/pmt.h b/gruel/src/include/gruel/pmt.h new file mode 100644 index 000000000..383a1d44d --- /dev/null +++ b/gruel/src/include/gruel/pmt.h @@ -0,0 +1,864 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009,2010 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 INCLUDED_PMT_H +#define INCLUDED_PMT_H + +#include <gruel/api.h> +#include <boost/intrusive_ptr.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/any.hpp> +#include <complex> +#include <string> +#include <stdint.h> +#include <iosfwd> +#include <stdexcept> +#include <vector> + +namespace gruel { + class msg_accepter; +}; + +/*! + * This file defines a polymorphic type and the operations on it. + * + * It draws heavily on the idea of scheme and lisp data types. + * The interface parallels that in Guile 1.8, with the notable + * exception that these objects are transparently reference counted. + */ + +namespace pmt { + +/*! + * \brief base class of all pmt types + */ +class pmt_base; + +/*! + * \brief typedef for shared pointer (transparent reference counting). + * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm + */ +typedef boost::intrusive_ptr<pmt_base> pmt_t; + +extern GRUEL_API void intrusive_ptr_add_ref(pmt_base*); +extern GRUEL_API void intrusive_ptr_release(pmt_base*); + +class GRUEL_API pmt_exception : public std::logic_error +{ +public: + pmt_exception(const std::string &msg, pmt_t obj); +}; + +class GRUEL_API pmt_wrong_type : public pmt_exception +{ +public: + pmt_wrong_type(const std::string &msg, pmt_t obj); +}; + +class GRUEL_API pmt_out_of_range : public pmt_exception +{ +public: + pmt_out_of_range(const std::string &msg, pmt_t obj); +}; + +class GRUEL_API pmt_notimplemented : public pmt_exception +{ +public: + pmt_notimplemented(const std::string &msg, pmt_t obj); +}; + +/* + * ------------------------------------------------------------------------ + * Booleans. Two constants, #t and #f. + * + * In predicates, anything that is not #f is considered true. + * I.e., there is a single false value, #f. + * ------------------------------------------------------------------------ + */ +extern GRUEL_API const pmt_t PMT_T; //< \#t : boolean true constant +extern GRUEL_API const pmt_t PMT_F; //< \#f : boolean false constant + +//! Return true if obj is \#t or \#f, else return false. +GRUEL_API bool pmt_is_bool(pmt_t obj); + +//! Return false if obj is \#f, else return true. +GRUEL_API bool pmt_is_true(pmt_t obj); + +//! Return true if obj is \#f, else return true. +GRUEL_API bool pmt_is_false(pmt_t obj); + +//! Return \#f is val is false, else return \#t. +GRUEL_API pmt_t pmt_from_bool(bool val); + +//! Return true if val is PMT_T, return false when val is PMT_F, +// else raise wrong_type exception. +GRUEL_API bool pmt_to_bool(pmt_t val); + +/* + * ------------------------------------------------------------------------ + * Symbols + * ------------------------------------------------------------------------ + */ + +//! Return true if obj is a symbol, else false. +GRUEL_API bool pmt_is_symbol(const pmt_t& obj); + +//! Return the symbol whose name is \p s. +GRUEL_API pmt_t pmt_string_to_symbol(const std::string &s); + +//! Alias for pmt_string_to_symbol +GRUEL_API pmt_t pmt_intern(const std::string &s); + + +/*! + * If \p is a symbol, return the name of the symbol as a string. + * Otherwise, raise the wrong_type exception. + */ +GRUEL_API const std::string pmt_symbol_to_string(const pmt_t& sym); + +/* + * ------------------------------------------------------------------------ + * Numbers: we support integer, real and complex + * ------------------------------------------------------------------------ + */ + +//! Return true if obj is any kind of number, else false. +GRUEL_API bool pmt_is_number(pmt_t obj); + +/* + * ------------------------------------------------------------------------ + * Integers + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is an integer number, else false +GRUEL_API bool pmt_is_integer(pmt_t x); + +//! Return the pmt value that represents the integer \p x. +GRUEL_API pmt_t pmt_from_long(long x); + +/*! + * \brief Convert pmt to long if possible. + * + * When \p x represents an exact integer that fits in a long, + * return that integer. Else raise an exception, either wrong_type + * when x is not an exact integer, or out_of_range when it doesn't fit. + */ +GRUEL_API long pmt_to_long(pmt_t x); + +/* + * ------------------------------------------------------------------------ + * uint64_t + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is an uint64 number, else false +GRUEL_API bool pmt_is_uint64(pmt_t x); + +//! Return the pmt value that represents the uint64 \p x. +GRUEL_API pmt_t pmt_from_uint64(uint64_t x); + +/*! + * \brief Convert pmt to uint64 if possible. + * + * When \p x represents an exact integer that fits in a uint64, + * return that uint64. Else raise an exception, either wrong_type + * when x is not an exact uint64, or out_of_range when it doesn't fit. + */ +GRUEL_API uint64_t pmt_to_uint64(pmt_t x); + +/* + * ------------------------------------------------------------------------ + * Reals + * ------------------------------------------------------------------------ + */ + +/* + * \brief Return true if \p obj is a real number, else false. + */ +GRUEL_API bool pmt_is_real(pmt_t obj); + +//! Return the pmt value that represents double \p x. +GRUEL_API pmt_t pmt_from_double(double x); + +/*! + * \brief Convert pmt to double if possible. + * + * Returns the number closest to \p val that is representable + * as a double. The argument \p val must be a real or integer, otherwise + * a wrong_type exception is raised. + */ +GRUEL_API double pmt_to_double(pmt_t x); + +/* + * ------------------------------------------------------------------------ + * Complex + * ------------------------------------------------------------------------ + */ + +/*! + * \brief return true if \p obj is a complex number, false otherwise. + */ +GRUEL_API bool pmt_is_complex(pmt_t obj); + +//! Return a complex number constructed of the given real and imaginary parts. +GRUEL_API pmt_t pmt_make_rectangular(double re, double im); + +//! Return a complex number constructed of the given real and imaginary parts. +GRUEL_API pmt_t pmt_from_complex(double re, double im); + +//! Return a complex number constructed of the given a complex number. +GRUEL_API pmt_t pmt_from_complex(const std::complex<double> &z); + +/*! + * If \p z is complex, real or integer, return the closest complex<double>. + * Otherwise, raise the wrong_type exception. + */ +GRUEL_API std::complex<double> pmt_to_complex(pmt_t z); + +/* + * ------------------------------------------------------------------------ + * Pairs + * ------------------------------------------------------------------------ + */ + +extern GRUEL_API const pmt_t PMT_NIL; //< the empty list + +//! Return true if \p x is the empty list, otherwise return false. +GRUEL_API bool pmt_is_null(const pmt_t& x); + +//! Return true if \p obj is a pair, else false. +GRUEL_API bool pmt_is_pair(const pmt_t& obj); + +//! Return a newly allocated pair whose car is \p x and whose cdr is \p y. +GRUEL_API pmt_t pmt_cons(const pmt_t& x, const pmt_t& y); + +//! If \p pair is a pair, return the car of the \p pair, otherwise raise wrong_type. +GRUEL_API pmt_t pmt_car(const pmt_t& pair); + +//! If \p pair is a pair, return the cdr of the \p pair, otherwise raise wrong_type. +GRUEL_API pmt_t pmt_cdr(const pmt_t& pair); + +//! Stores \p value in the car field of \p pair. +GRUEL_API void pmt_set_car(pmt_t pair, pmt_t value); + +//! Stores \p value in the cdr field of \p pair. +GRUEL_API void pmt_set_cdr(pmt_t pair, pmt_t value); + +GRUEL_API pmt_t pmt_caar(pmt_t pair); +GRUEL_API pmt_t pmt_cadr(pmt_t pair); +GRUEL_API pmt_t pmt_cdar(pmt_t pair); +GRUEL_API pmt_t pmt_cddr(pmt_t pair); +GRUEL_API pmt_t pmt_caddr(pmt_t pair); +GRUEL_API pmt_t pmt_cadddr(pmt_t pair); + +/* + * ------------------------------------------------------------------------ + * Tuples + * + * Store a fixed number of objects. Tuples are not modifiable, and thus + * are excellent for use as messages. Indexing is zero based. + * Access time to an element is O(1). + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is a tuple, othewise false. +GRUEL_API bool pmt_is_tuple(pmt_t x); + +GRUEL_API pmt_t pmt_make_tuple(); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7, const pmt_t &e8); +GRUEL_API pmt_t pmt_make_tuple(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7, const pmt_t &e8, const pmt_t &e9); + +/*! + * If \p x is a vector or proper list, return a tuple containing the elements of x + */ +GRUEL_API pmt_t pmt_to_tuple(const pmt_t &x); + +/*! + * Return the contents of position \p k of \p tuple. + * \p k must be a valid index of \p tuple. + */ +GRUEL_API pmt_t pmt_tuple_ref(const pmt_t &tuple, size_t k); + +/* + * ------------------------------------------------------------------------ + * Vectors + * + * These vectors can hold any kind of objects. Indexing is zero based. + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is a vector, othewise false. +GRUEL_API bool pmt_is_vector(pmt_t x); + +//! Make a vector of length \p k, with initial values set to \p fill +GRUEL_API pmt_t pmt_make_vector(size_t k, pmt_t fill); + +/*! + * Return the contents of position \p k of \p vector. + * \p k must be a valid index of \p vector. + */ +GRUEL_API pmt_t pmt_vector_ref(pmt_t vector, size_t k); + +//! Store \p obj in position \p k. +GRUEL_API void pmt_vector_set(pmt_t vector, size_t k, pmt_t obj); + +//! Store \p fill in every position of \p vector +GRUEL_API void pmt_vector_fill(pmt_t vector, pmt_t fill); + +/* + * ------------------------------------------------------------------------ + * Binary Large Objects (BLOBs) + * + * Handy for passing around uninterpreted chunks of memory. + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is a blob, othewise false. +GRUEL_API bool pmt_is_blob(pmt_t x); + +/*! + * \brief Make a blob given a pointer and length in bytes + * + * \param buf is the pointer to data to use to create blob + * \param len is the size of the data in bytes. + * + * The data is copied into the blob. + */ +GRUEL_API pmt_t pmt_make_blob(const void *buf, size_t len); + +//! Return a pointer to the blob's data +GRUEL_API const void *pmt_blob_data(pmt_t blob); + +//! Return the blob's length in bytes +GRUEL_API size_t pmt_blob_length(pmt_t blob); + +/*! + * <pre> + * ------------------------------------------------------------------------ + * Uniform Numeric Vectors + * + * A uniform numeric vector is a vector whose elements are all of single + * numeric type. pmt offers uniform numeric vectors for signed and + * unsigned 8-bit, 16-bit, 32-bit, and 64-bit integers, two sizes of + * floating point values, and complex floating-point numbers of these + * two sizes. Indexing is zero based. + * + * The names of the functions include these tags in their names: + * + * u8 unsigned 8-bit integers + * s8 signed 8-bit integers + * u16 unsigned 16-bit integers + * s16 signed 16-bit integers + * u32 unsigned 32-bit integers + * s32 signed 32-bit integers + * u64 unsigned 64-bit integers + * s64 signed 64-bit integers + * f32 the C++ type float + * f64 the C++ type double + * c32 the C++ type complex<float> + * c64 the C++ type complex<double> + * ------------------------------------------------------------------------ + * </pre> + */ + +//! true if \p x is any kind of uniform numeric vector +GRUEL_API bool pmt_is_uniform_vector(pmt_t x); + +GRUEL_API bool pmt_is_u8vector(pmt_t x); +GRUEL_API bool pmt_is_s8vector(pmt_t x); +GRUEL_API bool pmt_is_u16vector(pmt_t x); +GRUEL_API bool pmt_is_s16vector(pmt_t x); +GRUEL_API bool pmt_is_u32vector(pmt_t x); +GRUEL_API bool pmt_is_s32vector(pmt_t x); +GRUEL_API bool pmt_is_u64vector(pmt_t x); +GRUEL_API bool pmt_is_s64vector(pmt_t x); +GRUEL_API bool pmt_is_f32vector(pmt_t x); +GRUEL_API bool pmt_is_f64vector(pmt_t x); +GRUEL_API bool pmt_is_c32vector(pmt_t x); +GRUEL_API bool pmt_is_c64vector(pmt_t x); + +GRUEL_API pmt_t pmt_make_u8vector(size_t k, uint8_t fill); +GRUEL_API pmt_t pmt_make_s8vector(size_t k, int8_t fill); +GRUEL_API pmt_t pmt_make_u16vector(size_t k, uint16_t fill); +GRUEL_API pmt_t pmt_make_s16vector(size_t k, int16_t fill); +GRUEL_API pmt_t pmt_make_u32vector(size_t k, uint32_t fill); +GRUEL_API pmt_t pmt_make_s32vector(size_t k, int32_t fill); +GRUEL_API pmt_t pmt_make_u64vector(size_t k, uint64_t fill); +GRUEL_API pmt_t pmt_make_s64vector(size_t k, int64_t fill); +GRUEL_API pmt_t pmt_make_f32vector(size_t k, float fill); +GRUEL_API pmt_t pmt_make_f64vector(size_t k, double fill); +GRUEL_API pmt_t pmt_make_c32vector(size_t k, std::complex<float> fill); +GRUEL_API pmt_t pmt_make_c64vector(size_t k, std::complex<double> fill); + +GRUEL_API pmt_t pmt_init_u8vector(size_t k, const uint8_t *data); +GRUEL_API pmt_t pmt_init_u8vector(size_t k, const std::vector<uint8_t> &data); +GRUEL_API pmt_t pmt_init_s8vector(size_t k, const int8_t *data); +GRUEL_API pmt_t pmt_init_s8vector(size_t k, const std::vector<int8_t> &data); +GRUEL_API pmt_t pmt_init_u16vector(size_t k, const uint16_t *data); +GRUEL_API pmt_t pmt_init_u16vector(size_t k, const std::vector<uint16_t> &data); +GRUEL_API pmt_t pmt_init_s16vector(size_t k, const int16_t *data); +GRUEL_API pmt_t pmt_init_s16vector(size_t k, const std::vector<int16_t> &data); +GRUEL_API pmt_t pmt_init_u32vector(size_t k, const uint32_t *data); +GRUEL_API pmt_t pmt_init_u32vector(size_t k, const std::vector<uint32_t> &data); +GRUEL_API pmt_t pmt_init_s32vector(size_t k, const int32_t *data); +GRUEL_API pmt_t pmt_init_s32vector(size_t k, const std::vector<int32_t> &data); +GRUEL_API pmt_t pmt_init_u64vector(size_t k, const uint64_t *data); +GRUEL_API pmt_t pmt_init_u64vector(size_t k, const std::vector<uint64_t> &data); +GRUEL_API pmt_t pmt_init_s64vector(size_t k, const int64_t *data); +GRUEL_API pmt_t pmt_init_s64vector(size_t k, const std::vector<int64_t> &data); +GRUEL_API pmt_t pmt_init_f32vector(size_t k, const float *data); +GRUEL_API pmt_t pmt_init_f32vector(size_t k, const std::vector<float> &data); +GRUEL_API pmt_t pmt_init_f64vector(size_t k, const double *data); +GRUEL_API pmt_t pmt_init_f64vector(size_t k, const std::vector<double> &data); +GRUEL_API pmt_t pmt_init_c32vector(size_t k, const std::complex<float> *data); +GRUEL_API pmt_t pmt_init_c32vector(size_t k, const std::vector<std::complex<float> > &data); +GRUEL_API pmt_t pmt_init_c64vector(size_t k, const std::complex<double> *data); +GRUEL_API pmt_t pmt_init_c64vector(size_t k, const std::vector<std::complex<double> > &data); + +GRUEL_API uint8_t pmt_u8vector_ref(pmt_t v, size_t k); +GRUEL_API int8_t pmt_s8vector_ref(pmt_t v, size_t k); +GRUEL_API uint16_t pmt_u16vector_ref(pmt_t v, size_t k); +GRUEL_API int16_t pmt_s16vector_ref(pmt_t v, size_t k); +GRUEL_API uint32_t pmt_u32vector_ref(pmt_t v, size_t k); +GRUEL_API int32_t pmt_s32vector_ref(pmt_t v, size_t k); +GRUEL_API uint64_t pmt_u64vector_ref(pmt_t v, size_t k); +GRUEL_API int64_t pmt_s64vector_ref(pmt_t v, size_t k); +GRUEL_API float pmt_f32vector_ref(pmt_t v, size_t k); +GRUEL_API double pmt_f64vector_ref(pmt_t v, size_t k); +GRUEL_API std::complex<float> pmt_c32vector_ref(pmt_t v, size_t k); +GRUEL_API std::complex<double> pmt_c64vector_ref(pmt_t v, size_t k); + +GRUEL_API void pmt_u8vector_set(pmt_t v, size_t k, uint8_t x); //< v[k] = x +GRUEL_API void pmt_s8vector_set(pmt_t v, size_t k, int8_t x); +GRUEL_API void pmt_u16vector_set(pmt_t v, size_t k, uint16_t x); +GRUEL_API void pmt_s16vector_set(pmt_t v, size_t k, int16_t x); +GRUEL_API void pmt_u32vector_set(pmt_t v, size_t k, uint32_t x); +GRUEL_API void pmt_s32vector_set(pmt_t v, size_t k, int32_t x); +GRUEL_API void pmt_u64vector_set(pmt_t v, size_t k, uint64_t x); +GRUEL_API void pmt_s64vector_set(pmt_t v, size_t k, int64_t x); +GRUEL_API void pmt_f32vector_set(pmt_t v, size_t k, float x); +GRUEL_API void pmt_f64vector_set(pmt_t v, size_t k, double x); +GRUEL_API void pmt_c32vector_set(pmt_t v, size_t k, std::complex<float> x); +GRUEL_API void pmt_c64vector_set(pmt_t v, size_t k, std::complex<double> x); + +// Return const pointers to the elements + +GRUEL_API const void *pmt_uniform_vector_elements(pmt_t v, size_t &len); //< works with any; len is in bytes + +GRUEL_API const uint8_t *pmt_u8vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const int8_t *pmt_s8vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const uint16_t *pmt_u16vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const int16_t *pmt_s16vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const uint32_t *pmt_u32vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const int32_t *pmt_s32vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const uint64_t *pmt_u64vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const int64_t *pmt_s64vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const float *pmt_f32vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const double *pmt_f64vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const std::complex<float> *pmt_c32vector_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API const std::complex<double> *pmt_c64vector_elements(pmt_t v, size_t &len); //< len is in elements + +// len is in elements +GRUEL_API const std::vector<uint8_t> pmt_u8vector_elements(pmt_t v); +GRUEL_API const std::vector<int8_t> pmt_s8vector_elements(pmt_t v); +GRUEL_API const std::vector<uint16_t> pmt_u16vector_elements(pmt_t v); +GRUEL_API const std::vector<int16_t> pmt_s16vector_elements(pmt_t v); +GRUEL_API const std::vector<uint32_t> pmt_u32vector_elements(pmt_t v); +GRUEL_API const std::vector<int32_t> pmt_s32vector_elements(pmt_t v); +GRUEL_API const std::vector<uint64_t> pmt_u64vector_elements(pmt_t v); +GRUEL_API const std::vector<int64_t> pmt_s64vector_elements(pmt_t v); +GRUEL_API const std::vector<float> pmt_f32vector_elements(pmt_t v); +GRUEL_API const std::vector<double> pmt_f64vector_elements(pmt_t v); +GRUEL_API const std::vector<std::complex<float> > pmt_c32vector_elements(pmt_t v); +GRUEL_API const std::vector<std::complex<double> > pmt_c64vector_elements(pmt_t v); + +// Return non-const pointers to the elements + +GRUEL_API void *pmt_uniform_vector_writable_elements(pmt_t v, size_t &len); //< works with any; len is in bytes + +GRUEL_API uint8_t *pmt_u8vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API int8_t *pmt_s8vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API uint16_t *pmt_u16vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API int16_t *pmt_s16vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API uint32_t *pmt_u32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API int32_t *pmt_s32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API uint64_t *pmt_u64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API int64_t *pmt_s64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API float *pmt_f32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API double *pmt_f64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API std::complex<float> *pmt_c32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +GRUEL_API std::complex<double> *pmt_c64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements + +/* + * ------------------------------------------------------------------------ + * Dictionary (a.k.a associative array, hash, map) + * + * This is a functional data structure that is persistent. Updating a + * functional data structure does not destroy the existing version, but + * rather creates a new version that coexists with the old. + * ------------------------------------------------------------------------ + */ + +//! Return true if \p obj is a dictionary +GRUEL_API bool pmt_is_dict(const pmt_t &obj); + +//! Make an empty dictionary +GRUEL_API pmt_t pmt_make_dict(); + +//! Return a new dictionary with \p key associated with \p value. +GRUEL_API pmt_t pmt_dict_add(const pmt_t &dict, const pmt_t &key, const pmt_t &value); + +//! Return a new dictionary with \p key removed. +GRUEL_API pmt_t pmt_dict_delete(const pmt_t &dict, const pmt_t &key); + +//! Return true if \p key exists in \p dict +GRUEL_API bool pmt_dict_has_key(const pmt_t &dict, const pmt_t &key); + +//! If \p key exists in \p dict, return associated value; otherwise return \p not_found. +GRUEL_API pmt_t pmt_dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t ¬_found); + +//! Return list of (key . value) pairs +GRUEL_API pmt_t pmt_dict_items(pmt_t dict); + +//! Return list of keys +GRUEL_API pmt_t pmt_dict_keys(pmt_t dict); + +//! Return list of values +GRUEL_API pmt_t pmt_dict_values(pmt_t dict); + +/* + * ------------------------------------------------------------------------ + * Any (wraps boost::any -- can be used to wrap pretty much anything) + * + * Cannot be serialized or used across process boundaries. + * See http://www.boost.org/doc/html/any.html + * ------------------------------------------------------------------------ + */ + +//! Return true if \p obj is an any +GRUEL_API bool pmt_is_any(pmt_t obj); + +//! make an any +GRUEL_API pmt_t pmt_make_any(const boost::any &any); + +//! Return underlying boost::any +GRUEL_API boost::any pmt_any_ref(pmt_t obj); + +//! Store \p any in \p obj +GRUEL_API void pmt_any_set(pmt_t obj, const boost::any &any); + + +/* + * ------------------------------------------------------------------------ + * msg_accepter -- pmt representation of gruel::msg_accepter + * ------------------------------------------------------------------------ + */ +//! Return true if \p obj is a msg_accepter +GRUEL_API bool pmt_is_msg_accepter(const pmt_t &obj); + +//! make a msg_accepter +GRUEL_API pmt_t pmt_make_msg_accepter(boost::shared_ptr<gruel::msg_accepter> ma); + +//! Return underlying msg_accepter +GRUEL_API boost::shared_ptr<gruel::msg_accepter> pmt_msg_accepter_ref(const pmt_t &obj); + +/* + * ------------------------------------------------------------------------ + * General functions + * ------------------------------------------------------------------------ + */ + +//! Return true if x and y are the same object; otherwise return false. +GRUEL_API bool pmt_eq(const pmt_t& x, const pmt_t& y); + +/*! + * \brief Return true if x and y should normally be regarded as the same object, else false. + * + * <pre> + * eqv returns true if: + * x and y are the same object. + * x and y are both \#t or both \#f. + * x and y are both symbols and their names are the same. + * x and y are both numbers, and are numerically equal. + * x and y are both the empty list (nil). + * x and y are pairs or vectors that denote same location in store. + * </pre> + */ +GRUEL_API bool pmt_eqv(const pmt_t& x, const pmt_t& y); + +/*! + * pmt_equal recursively compares the contents of pairs and vectors, + * applying pmt_eqv on other objects such as numbers and symbols. + * pmt_equal may fail to terminate if its arguments are circular data + * structures. + */ +GRUEL_API bool pmt_equal(const pmt_t& x, const pmt_t& y); + + +//! Return the number of elements in v +GRUEL_API size_t pmt_length(const pmt_t& v); + +/*! + * \brief Find the first pair in \p alist whose car field is \p obj + * and return that pair. + * + * \p alist (for "association list") must be a list of pairs. If no pair + * in \p alist has \p obj as its car then \#f is returned. + * Uses pmt_eq to compare \p obj with car fields of the pairs in \p alist. + */ +GRUEL_API pmt_t pmt_assq(pmt_t obj, pmt_t alist); + +/*! + * \brief Find the first pair in \p alist whose car field is \p obj + * and return that pair. + * + * \p alist (for "association list") must be a list of pairs. If no pair + * in \p alist has \p obj as its car then \#f is returned. + * Uses pmt_eqv to compare \p obj with car fields of the pairs in \p alist. + */ +GRUEL_API pmt_t pmt_assv(pmt_t obj, pmt_t alist); + +/*! + * \brief Find the first pair in \p alist whose car field is \p obj + * and return that pair. + * + * \p alist (for "association list") must be a list of pairs. If no pair + * in \p alist has \p obj as its car then \#f is returned. + * Uses pmt_equal to compare \p obj with car fields of the pairs in \p alist. + */ +GRUEL_API pmt_t pmt_assoc(pmt_t obj, pmt_t alist); + +/*! + * \brief Apply \p proc element-wise to the elements of list and returns + * a list of the results, in order. + * + * \p list must be a list. The dynamic order in which \p proc is + * applied to the elements of \p list is unspecified. + */ +GRUEL_API pmt_t pmt_map(pmt_t proc(const pmt_t&), pmt_t list); + +/*! + * \brief reverse \p list. + * + * \p list must be a proper list. + */ +GRUEL_API pmt_t pmt_reverse(pmt_t list); + +/*! + * \brief destructively reverse \p list. + * + * \p list must be a proper list. + */ +GRUEL_API pmt_t pmt_reverse_x(pmt_t list); + +/*! + * \brief (acons x y a) == (cons (cons x y) a) + */ +inline static pmt_t +pmt_acons(pmt_t x, pmt_t y, pmt_t a) +{ + return pmt_cons(pmt_cons(x, y), a); +} + +/*! + * \brief locates \p nth element of \n list where the car is the 'zeroth' element. + */ +GRUEL_API pmt_t pmt_nth(size_t n, pmt_t list); + +/*! + * \brief returns the tail of \p list that would be obtained by calling + * cdr \p n times in succession. + */ +GRUEL_API pmt_t pmt_nthcdr(size_t n, pmt_t list); + +/*! + * \brief Return the first sublist of \p list whose car is \p obj. + * If \p obj does not occur in \p list, then \#f is returned. + * pmt_memq use pmt_eq to compare \p obj with the elements of \p list. + */ +GRUEL_API pmt_t pmt_memq(pmt_t obj, pmt_t list); + +/*! + * \brief Return the first sublist of \p list whose car is \p obj. + * If \p obj does not occur in \p list, then \#f is returned. + * pmt_memv use pmt_eqv to compare \p obj with the elements of \p list. + */ +GRUEL_API pmt_t pmt_memv(pmt_t obj, pmt_t list); + +/*! + * \brief Return the first sublist of \p list whose car is \p obj. + * If \p obj does not occur in \p list, then \#f is returned. + * pmt_member use pmt_equal to compare \p obj with the elements of \p list. + */ +GRUEL_API pmt_t pmt_member(pmt_t obj, pmt_t list); + +/*! + * \brief Return true if every element of \p list1 appears in \p list2, and false otherwise. + * Comparisons are done with pmt_eqv. + */ +GRUEL_API bool pmt_subsetp(pmt_t list1, pmt_t list2); + +/*! + * \brief Return a list of length 1 containing \p x1 + */ +GRUEL_API pmt_t pmt_list1(const pmt_t& x1); + +/*! + * \brief Return a list of length 2 containing \p x1, \p x2 + */ +GRUEL_API pmt_t pmt_list2(const pmt_t& x1, const pmt_t& x2); + +/*! + * \brief Return a list of length 3 containing \p x1, \p x2, \p x3 + */ +GRUEL_API pmt_t pmt_list3(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3); + +/*! + * \brief Return a list of length 4 containing \p x1, \p x2, \p x3, \p x4 + */ +GRUEL_API pmt_t pmt_list4(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4); + +/*! + * \brief Return a list of length 5 containing \p x1, \p x2, \p x3, \p x4, \p x5 + */ +GRUEL_API pmt_t pmt_list5(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4, const pmt_t& x5); + +/*! + * \brief Return a list of length 6 containing \p x1, \p x2, \p x3, \p x4, \p + * x5, \p x6 + */ +GRUEL_API pmt_t pmt_list6(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4, const pmt_t& x5, const pmt_t& x6); + +/*! + * \brief Return \p list with \p item added to it. + */ +GRUEL_API pmt_t pmt_list_add(pmt_t list, const pmt_t& item); + +/*! + * \brief Return \p list with \p item removed from it. + */ +GRUEL_API pmt_t pmt_list_rm(pmt_t list, const pmt_t& item); + +/*! + * \brief Return bool of \p list contains \p item + */ +GRUEL_API bool pmt_list_has(pmt_t list, const pmt_t& item); + + +/* + * ------------------------------------------------------------------------ + * read / write + * ------------------------------------------------------------------------ + */ +extern GRUEL_API const pmt_t PMT_EOF; //< The end of file object + +//! return true if obj is the EOF object, otherwise return false. +GRUEL_API bool pmt_is_eof_object(pmt_t obj); + +/*! + * read converts external representations of pmt objects into the + * objects themselves. Read returns the next object parsable from + * the given input port, updating port to point to the first + * character past the end of the external representation of the + * object. + * + * If an end of file is encountered in the input before any + * characters are found that can begin an object, then an end of file + * object is returned. The port remains open, and further attempts + * to read will also return an end of file object. If an end of file + * is encountered after the beginning of an object's external + * representation, but the external representation is incomplete and + * therefore not parsable, an error is signaled. + */ +GRUEL_API pmt_t pmt_read(std::istream &port); + +/*! + * Write a written representation of \p obj to the given \p port. + */ +GRUEL_API void pmt_write(pmt_t obj, std::ostream &port); + +/*! + * Return a string representation of \p obj. + * This is the same output as would be generated by pmt_write. + */ +GRUEL_API std::string pmt_write_string(pmt_t obj); + + +GRUEL_API std::ostream& operator<<(std::ostream &os, pmt_t obj); + +/*! + * \brief Write pmt string representation to stdout. + */ +GRUEL_API void pmt_print(pmt_t v); + + +/* + * ------------------------------------------------------------------------ + * portable byte stream representation + * ------------------------------------------------------------------------ + */ +/*! + * \brief Write portable byte-serial representation of \p obj to \p sink + */ +GRUEL_API bool pmt_serialize(pmt_t obj, std::streambuf &sink); + +/*! + * \brief Create obj from portable byte-serial representation + */ +GRUEL_API pmt_t pmt_deserialize(std::streambuf &source); + + +GRUEL_API void pmt_dump_sizeof(); // debugging + +/*! + * \brief Provide a simple string generating interface to pmt's serialize function + */ +GRUEL_API std::string pmt_serialize_str(pmt_t obj); + +/*! + * \brief Provide a simple string generating interface to pmt's deserialize function + */ +GRUEL_API pmt_t pmt_deserialize_str(std::string str); + +/*! + * \brief Provide a comparator function object to allow pmt use in stl types + */ +class pmt_comperator { + public: + bool operator()(pmt::pmt_t const& p1, pmt::pmt_t const& p2) const + { return pmt::pmt_eqv(p1,p2)?false:p1.get()>p2.get(); } + }; + +} /* namespace pmt */ + +#include <gruel/pmt_sugar.h> + +#endif /* INCLUDED_PMT_H */ diff --git a/gruel/src/include/gruel/pmt_pool.h b/gruel/src/include/gruel/pmt_pool.h new file mode 100644 index 000000000..93c5290ad --- /dev/null +++ b/gruel/src/include/gruel/pmt_pool.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_PMT_POOL_H +#define INCLUDED_PMT_POOL_H + +#include <gruel/api.h> +#include <cstddef> +#include <vector> +#include <boost/thread.hpp> + +namespace pmt { + +/*! + * \brief very simple thread-safe fixed-size allocation pool + * + * FIXME may want to go to global allocation with per-thread free list. + * This would eliminate virtually all lock contention. + */ +class GRUEL_API pmt_pool { + + struct GRUEL_API item { + struct item *d_next; + }; + + typedef boost::unique_lock<boost::mutex> scoped_lock; + mutable boost::mutex d_mutex; + boost::condition_variable d_cond; + + size_t d_itemsize; + size_t d_alignment; + size_t d_allocation_size; + size_t d_max_items; + size_t d_n_items; + item *d_freelist; + std::vector<char *> d_allocations; + +public: + /*! + * \param itemsize size in bytes of the items to be allocated. + * \param alignment alignment in bytes of all objects to be allocated (must be power-of-2). + * \param allocation_size number of bytes to allocate at a time from the underlying allocator. + * \param max_items is the maximum number of items to allocate. If this number is exceeded, + * the allocate blocks. 0 implies no limit. + */ + pmt_pool(size_t itemsize, size_t alignment = 16, + size_t allocation_size = 4096, size_t max_items = 0); + ~pmt_pool(); + + void *malloc(); + void free(void *p); +}; + +} /* namespace pmt */ + +#endif /* INCLUDED_PMT_POOL_H */ diff --git a/gruel/src/include/gruel/pmt_sugar.h b/gruel/src/include/gruel/pmt_sugar.h new file mode 100644 index 000000000..bde7f716d --- /dev/null +++ b/gruel/src/include/gruel/pmt_sugar.h @@ -0,0 +1,171 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GRUEL_PMT_SUGAR_H +#define INCLUDED_GRUEL_PMT_SUGAR_H + +/*! + * This file is included by pmt.h and contains pseudo-constructor + * shorthand for making pmt objects + */ + +namespace pmt { + + //! Make pmt symbol + static inline pmt_t + mp(const std::string &s) + { + return pmt_string_to_symbol(s); + } + + //! Make pmt symbol + static inline pmt_t + mp(const char *s) + { + return pmt_string_to_symbol(s); + } + + //! Make pmt long + static inline pmt_t + mp(long x){ + return pmt_from_long(x); + } + + //! Make pmt long + static inline pmt_t + mp(long long unsigned x){ + return pmt_from_long(x); + } + + //! Make pmt long + static inline pmt_t + mp(int x){ + return pmt_from_long(x); + } + + //! Make pmt double + static inline pmt_t + mp(double x){ + return pmt_from_double(x); + } + + //! Make pmt complex + static inline pmt_t + mp(std::complex<double> z) + { + return pmt_make_rectangular(z.real(), z.imag()); + } + + //! Make pmt complex + static inline pmt_t + mp(std::complex<float> z) + { + return pmt_make_rectangular(z.real(), z.imag()); + } + + //! Make pmt msg_accepter + static inline pmt_t + mp(boost::shared_ptr<gruel::msg_accepter> ma) + { + return pmt_make_msg_accepter(ma); + } + + //! Make pmt Binary Large Object (BLOB) + static inline pmt_t + mp(const void *data, size_t len_in_bytes) + { + return pmt_make_blob(data, len_in_bytes); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0) + { + return pmt_make_tuple(e0); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0, const pmt_t &e1) + { + return pmt_make_tuple(e0, e1); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2) + { + return pmt_make_tuple(e0, e1, e2); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3) + { + return pmt_make_tuple(e0, e1, e2, e3); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4) + { + return pmt_make_tuple(e0, e1, e2, e3, e4); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5) + { + return pmt_make_tuple(e0, e1, e2, e3, e4, e5); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6) + { + return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7) + { + return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6, e7); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7, const pmt_t &e8) + { + return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6, e7, e8); + } + + //! Make tuple + static inline pmt_t + mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7, const pmt_t &e8, const pmt_t &e9) + { + return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9); + } + + +} /* namespace pmt */ + + +#endif /* INCLUDED_GRUEL_PMT_SUGAR_H */ diff --git a/gruel/src/include/gruel/realtime.h b/gruel/src/include/gruel/realtime.h new file mode 100644 index 000000000..13673ecb3 --- /dev/null +++ b/gruel/src/include/gruel/realtime.h @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2008 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 INCLUDED_GRUEL_REALTIME_H +#define INCLUDED_GRUEL_REALTIME_H + +#include <gruel/api.h> +#include <stdexcept> + +/*! + * \brief System independent way to ask for realtime scheduling + * + * \sa sys_pri.h + */ + +namespace gruel { + + typedef enum { + RT_OK = 0, + RT_NOT_IMPLEMENTED, + RT_NO_PRIVS, + RT_OTHER_ERROR + } rt_status_t; + + + enum rt_sched_policy { + RT_SCHED_RR = 0, // round robin + RT_SCHED_FIFO = 1, // first in first out + }; + + /* + * Define the range for our virtual priorities (don't change these) + * + * Processes (or threads) with numerically higher priority values + * are scheduled before processes with numerically lower priority + * values. Thus, the value returned by rt_priority_max() will be + * greater than the value returned by rt_priority_min(). + */ + static inline int rt_priority_min() { return 0; } + static inline int rt_priority_max() { return 15; } + static inline int rt_priority_default() { return 1; } + + struct GRUEL_API rt_sched_param { + int priority; + rt_sched_policy policy; + + rt_sched_param() + : priority(rt_priority_default()), policy(RT_SCHED_RR){} + + rt_sched_param(int priority_, rt_sched_policy policy_ = RT_SCHED_RR) + { + if (priority_ < rt_priority_min() || priority_ > rt_priority_max()) + throw std::invalid_argument("rt_sched_param: priority out of range"); + + priority = priority_; + policy = policy_; + } + }; + + /*! + * \brief If possible, enable "realtime" scheduling. + * \ingroup misc + * + * In general, this means that the code will be scheduled before any + * non-realtime (normal) processes. Note that if your code contains + * an non-blocking infinite loop and you enable realtime scheduling, + * it's possible to hang the system. + */ + + // NOTE: If you change this, you need to change the code in + // gnuradio-core/src/lib/runtime/gr_realtime.i, see note there. + rt_status_t + GRUEL_API enable_realtime_scheduling(rt_sched_param = rt_sched_param()); + +} // namespace gruel + +#endif /* INCLUDED_GRUEL_REALTIME_H */ diff --git a/gruel/src/include/gruel/sys_pri.h b/gruel/src/include/gruel/sys_pri.h new file mode 100644 index 000000000..c0751e52c --- /dev/null +++ b/gruel/src/include/gruel/sys_pri.h @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef INCLUDED_GRUEL_SYS_PRI_H +#define INCLUDED_GRUEL_SYS_PRI_H + +#include <gruel/api.h> +#include <gruel/realtime.h> + +/* + * A single place to define real-time priorities used by the system itself + */ +namespace gruel { + + struct GRUEL_API sys_pri { + static rt_sched_param python(); // python code + static rt_sched_param normal(); // normal blocks + static rt_sched_param gcell_event_handler(); + static rt_sched_param usrp2_backend(); // thread that services the ethernet + }; + +} + +#endif /* INCLUDED_GRUEL_SYS_PRI_H */ diff --git a/gruel/src/include/gruel/thread.h b/gruel/src/include/gruel/thread.h new file mode 100644 index 000000000..10c6c38cc --- /dev/null +++ b/gruel/src/include/gruel/thread.h @@ -0,0 +1,139 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2012 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_THREAD_H +#define INCLUDED_THREAD_H + +#include <gruel/api.h> +#include <boost/thread/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/condition_variable.hpp> +#include <vector> + +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> + +#endif + +namespace gruel { + + typedef boost::thread thread; + typedef boost::mutex mutex; + typedef boost::unique_lock<boost::mutex> scoped_lock; + typedef boost::condition_variable condition_variable; + + /*! \brief a system-dependent typedef for the underlying thread type. + */ +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + typedef HANDLE gr_thread_t; +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + typedef pthread_t gr_thread_t; +#else + typedef pthread_t gr_thread_t; +#endif + + /*! \brief Get the current thread's ID as a gr_thread_t + * + * We use this when setting the thread affinity or any other + * low-level thread settings. Can be called withing a GNU Radio + * block to get a reference to its current thread ID. + */ + GRUEL_API gr_thread_t get_current_thread_id(); + + /*! \brief Bind the current thread to a set of cores. + * + * Wrapper for system-dependent calls to set the affinity of the + * current thread to the processor mask. The mask is simply a + * 1-demensional vector containing the processor or core number from + * 0 to N-1 for N cores. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_bind_to_processor(const std::vector<int> &mask); + + /*! \brief Convineince function to bind the current thread to a single core. + * + * Wrapper for system-dependent calls to set the affinity of the + * current thread to a given core from 0 to N-1 for N cores. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_bind_to_processor(int n); + + /*! \brief Bind a thread to a set of cores. + * + * Wrapper for system-dependent calls to set the affinity of the + * given thread ID to the processor mask. The mask is simply a + * 1-demensional vector containing the processor or core number from + * 0 to N-1 for N cores. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_bind_to_processor(gr_thread_t thread, const std::vector<int> &mask); + + + /*! \brief Convineince function to bind the a thread to a single core. + * + * Wrapper for system-dependent calls to set the affinity of the + * given thread ID to a given core from 0 to N-1 for N cores. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_bind_to_processor(gr_thread_t thread, unsigned int n); + + /*! \brief Remove any thread-processor affinity for the current thread. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_unbind(); + + /*! \brief Remove any thread-processor affinity for a given thread ID. + * + * Note: this does not work on OSX; it is a nop call since OSX does + * not support the concept of thread affinity (and what they do + * support in this way since 10.5 is not what we want or can use in + * this fashion). + */ + GRUEL_API void thread_unbind(gr_thread_t thread); + +} /* namespace gruel */ + +#endif /* INCLUDED_THREAD_H */ diff --git a/gruel/src/include/gruel/thread_body_wrapper.h b/gruel/src/include/gruel/thread_body_wrapper.h new file mode 100644 index 000000000..e09a43e68 --- /dev/null +++ b/gruel/src/include/gruel/thread_body_wrapper.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_THREAD_BODY_WRAPPER_H +#define INCLUDED_THREAD_BODY_WRAPPER_H + +#include <gruel/api.h> +#include <gruel/thread.h> +#include <exception> +#include <iostream> + +namespace gruel +{ + + GRUEL_API void mask_signals(); + + template <class F> + class thread_body_wrapper + { + F d_f; + std::string d_name; + + public: + + explicit thread_body_wrapper(F f, const std::string &name="") + : d_f(f), d_name(name) {} + + void operator()() + { + mask_signals(); + + try { + d_f(); + } + catch(boost::thread_interrupted const &) + { + } + catch(std::exception const &e) + { + std::cerr << "thread[" << d_name << "]: " + << e.what() << std::endl; + } + catch(...) + { + std::cerr << "thread[" << d_name << "]: " + << "caught unrecognized exception\n"; + } + } + }; +} + +#endif /* INCLUDED_THREAD_BODY_WRAPPER_H */ diff --git a/gruel/src/include/gruel/thread_group.h b/gruel/src/include/gruel/thread_group.h new file mode 100644 index 000000000..1b8a0a4bf --- /dev/null +++ b/gruel/src/include/gruel/thread_group.h @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright (C) 2001-2003 William E. Kempf + * Copyright (C) 2007 Anthony Williams + * Copyright 2008,2009 Free Software Foundation, Inc. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +/* + * This was extracted from Boost 1.35.0 and fixed. + */ + +#ifndef INCLUDED_GRUEL_THREAD_GROUP_H +#define INCLUDED_GRUEL_THREAD_GROUP_H + +#include <gruel/api.h> +#include <gruel/thread.h> +#include <boost/utility.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/function.hpp> + +namespace gruel +{ + class GRUEL_API thread_group : public boost::noncopyable + { + public: + thread_group(); + ~thread_group(); + + boost::thread* create_thread(const boost::function0<void>& threadfunc); + void add_thread(boost::thread* thrd); + void remove_thread(boost::thread* thrd); + void join_all(); + void interrupt_all(); + size_t size() const; + + private: + std::list<boost::thread*> m_threads; + mutable boost::shared_mutex m_mutex; + }; +} + +#endif /* INCLUDED_GRUEL_THREAD_GROUP_H */ |