diff --git a/op25/gr-op25/include/op25/message.h b/op25/gr-op25/include/op25/message.h new file mode 100644 index 0000000..6805963 --- /dev/null +++ b/op25/gr-op25/include/op25/message.h @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifndef INCLUDED_OP25_MESSAGE_H +#define INCLUDED_OP25_MESSAGE_H + +#include +#include +#include + +namespace gr { +namespace op25 { + +/*! + * \brief Message class. + * + * \ingroup misc + * The ideas and method names for adjustable message length were + * lifted from the click modular router "Packet" class. + */ +class OP25_API message +{ +public: + typedef std::shared_ptr sptr; + +private: + sptr d_next; // link field for msg queue + long d_type; // type of the message + double d_arg1; // optional arg1 + double d_arg2; // optional arg2 + + std::vector d_buf; + unsigned char* d_msg_start; // where the msg starts + unsigned char* d_msg_end; // one beyond end of msg + + message(long type, double arg1, double arg2, size_t length); + + friend class msg_queue; + + unsigned char* buf_data() { return d_buf.data(); } + size_t buf_len() const { return d_buf.size(); } + +public: + /*! + * \brief public constructor for message + */ + static sptr make(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); + + static sptr make_from_string(const std::string s, + long type = 0, + double arg1 = 0, + double arg2 = 0); + + + ~message(); + + long type() const { return d_type; } + double arg1() const { return d_arg1; } + double arg2() const { return d_arg2; } + + void set_type(long type) { d_type = type; } + void set_arg1(double arg1) { d_arg1 = arg1; } + void set_arg2(double arg2) { d_arg2 = arg2; } + + unsigned char* msg() const { return d_msg_start; } + size_t length() const { return d_msg_end - d_msg_start; } + std::string to_string() const; +}; + +OP25_API long message_ncurrently_allocated(); + +} /* namespace op25 */ +} /* namespace gr */ + +#endif /* INCLUDED_OP25_MESSAGE_H */ diff --git a/op25/gr-op25/include/op25/msg_handler.h b/op25/gr-op25/include/op25/msg_handler.h new file mode 100644 index 0000000..329860c --- /dev/null +++ b/op25/gr-op25/include/op25/msg_handler.h @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifndef INCLUDED_OP25_MSG_HANDLER_H +#define INCLUDED_OP25_MSG_HANDLER_H + +#include +#include + +namespace gr { +namespace op25 { + +class msg_handler; +typedef std::shared_ptr msg_handler_sptr; + +/*! + * \brief abstract class of message handlers + * \ingroup base + */ +class OP25_API msg_handler +{ +public: + virtual ~msg_handler(); + + //! handle \p msg + virtual void handle(message::sptr msg) = 0; +}; + +} /* namespace op25 */ +} /* namespace gr */ + +#endif /* INCLUDED_OP25_MSG_HANDLER_H */ diff --git a/op25/gr-op25/include/op25/msg_queue.h b/op25/gr-op25/include/op25/msg_queue.h new file mode 100644 index 0000000..d4ed002 --- /dev/null +++ b/op25/gr-op25/include/op25/msg_queue.h @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifndef INCLUDED_OP25_MSG_QUEUE_H +#define INCLUDED_OP25_MSG_QUEUE_H + +#include +#include +#include + +namespace gr { +namespace op25 { + +/*! + * \brief thread-safe message queue + * \ingroup misc + */ +class OP25_API msg_queue : public msg_handler +{ + gr::thread::mutex d_mutex; + gr::thread::condition_variable d_not_empty; + gr::thread::condition_variable d_not_full; + message::sptr d_head; + message::sptr d_tail; + unsigned int d_count; // # of messages in queue. + unsigned int d_limit; // max # of messages in queue. 0 -> unbounded + +public: + typedef std::shared_ptr sptr; + + static sptr make(unsigned int limit = 0); + + msg_queue(unsigned int limit); + ~msg_queue() override; + + //! Generic msg_handler method: insert the message. + void handle(message::sptr msg) override { insert_tail(msg); } + + /*! + * \brief Insert message at tail of queue. + * \param msg message + * + * Block if queue if full. + */ + void insert_tail(message::sptr msg); + + /*! + * \brief Delete message from head of queue and return it. + * Block if no message is available. + */ + message::sptr delete_head(); + + /*! + * \brief If there's a message in the q, delete it and return it. + * If no message is available, return 0. + */ + message::sptr delete_head_nowait(); + + //! Delete all messages from the queue + void flush(); + + //! is the queue empty? + bool empty_p() const { return d_count == 0; } + + //! is the queue full? + bool full_p() const { return d_limit != 0 && d_count >= d_limit; } + + //! return number of messages in queue + unsigned int count() const { return d_count; } + + //! return limit on number of message in queue. 0 -> unbounded + unsigned int limit() const { return d_limit; } +}; + +} /* namespace op25 */ +} /* namespace gr */ + +#endif /* INCLUDED_OP25_MSG_QUEUE_H */ diff --git a/op25/gr-op25/lib/message.cc b/op25/gr-op25/lib/message.cc new file mode 100644 index 0000000..ab397cb --- /dev/null +++ b/op25/gr-op25/lib/message.cc @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +namespace gr { +namespace op25 { + +static long s_ncurrently_allocated = 0; + +message::sptr message::make(long type, double arg1, double arg2, size_t length) +{ + return message::sptr(new message(type, arg1, arg2, length)); +} + +message::sptr +message::make_from_string(const std::string s, long type, double arg1, double arg2) +{ + message::sptr m = message::make(type, arg1, arg2, s.size()); + memcpy(m->msg(), s.data(), s.size()); + return m; +} + +message::message(long type, double arg1, double arg2, size_t length) + : d_type(type), d_arg1(arg1), d_arg2(arg2), d_buf(length) +{ + if (length == 0) + d_msg_start = d_msg_end = nullptr; + else { + d_msg_start = d_buf.data(); + d_msg_end = d_msg_start + length; + } + s_ncurrently_allocated++; +} + +message::~message() +{ + assert(d_next == 0); + s_ncurrently_allocated--; +} + +std::string message::to_string() const +{ + return std::string((char*)d_msg_start, length()); +} + +long message_ncurrently_allocated() { return s_ncurrently_allocated; } + +} /* namespace op25 */ +} /* namespace gr */ diff --git a/op25/gr-op25/lib/msg_handler.cc b/op25/gr-op25/lib/msg_handler.cc new file mode 100644 index 0000000..7521a73 --- /dev/null +++ b/op25/gr-op25/lib/msg_handler.cc @@ -0,0 +1,23 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +namespace gr { +namespace op25 { + +msg_handler::~msg_handler() {} + +} /* namespace op25 */ +} /* namespace gr */ diff --git a/op25/gr-op25/lib/msg_queue.cc b/op25/gr-op25/lib/msg_queue.cc new file mode 100644 index 0000000..b42ba29 --- /dev/null +++ b/op25/gr-op25/lib/msg_queue.cc @@ -0,0 +1,113 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2009,2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +namespace gr { +namespace op25 { + +msg_queue::sptr msg_queue::make(unsigned int limit) +{ + return msg_queue::sptr(new msg_queue(limit)); +} + +msg_queue::msg_queue(unsigned int limit) + : d_not_empty(), + d_not_full(), + /*d_head(0), d_tail(0),*/ d_count(0), + d_limit(limit) +{ +} + +msg_queue::~msg_queue() { flush(); } + +void msg_queue::insert_tail(message::sptr msg) +{ + if (msg->d_next) + throw std::invalid_argument("gr::msg_queue::insert_tail: msg already in queue"); + + gr::thread::scoped_lock guard(d_mutex); + + while (full_p()) + d_not_full.wait(guard); + + if (d_tail == 0) { + d_tail = d_head = msg; + // msg->d_next = 0; + msg->d_next.reset(); + } else { + d_tail->d_next = msg; + d_tail = msg; + // msg->d_next = 0; + msg->d_next.reset(); + } + d_count++; + d_not_empty.notify_one(); +} + +message::sptr msg_queue::delete_head() +{ + gr::thread::scoped_lock guard(d_mutex); + message::sptr m; + + while ((m = d_head) == 0) + d_not_empty.wait(guard); + + d_head = m->d_next; + if (d_head == 0) { + // d_tail = 0; + d_tail.reset(); + } + + d_count--; + // m->d_next = 0; + m->d_next.reset(); + d_not_full.notify_one(); + return m; +} + +message::sptr msg_queue::delete_head_nowait() +{ + gr::thread::scoped_lock guard(d_mutex); + message::sptr m; + + if ((m = d_head) == 0) { + // return 0; + return message::sptr(); + } + + d_head = m->d_next; + if (d_head == 0) { + // d_tail = 0; + d_tail.reset(); + } + + d_count--; + // m->d_next = 0; + m->d_next.reset(); + d_not_full.notify_one(); + return m; +} + +void msg_queue::flush() +{ + message::sptr m; + + while ((m = delete_head_nowait()) != 0) + ; +} + +} /* namespace op25 */ +} /* namespace gr */ diff --git a/op25/gr-op25/python/op25/bindings/message_python.cc b/op25/gr-op25/python/op25/bindings/message_python.cc new file mode 100644 index 0000000..2a9f995 --- /dev/null +++ b/op25/gr-op25/python/op25/bindings/message_python.cc @@ -0,0 +1,129 @@ +/* + * Copyright 2022 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +/***********************************************************************************/ +/* This file is automatically generated using bindtool and can be manually edited */ +/* The following lines can be configured to regenerate this file during cmake */ +/* If manual edits are made, the following tags should be modified accordingly. */ +/* BINDTOOL_GEN_AUTOMATIC(0) */ +/* BINDTOOL_USE_PYGCCXML(0) */ +/* BINDTOOL_HEADER_FILE(message.h) */ +/* BINDTOOL_HEADER_FILE_HASH(e324acfee988515a91a4759680dbabbf) */ +/***********************************************************************************/ + +#include +#include +#include + +namespace py = pybind11; + +#include +// pydoc.h is automatically generated in the build directory +#include + +void bind_message(py::module& m) +{ + + using message = ::gr::op25::message; + + + py::class_>(m, "message", D(message)) + + .def(py::init(&message::make), + py::arg("type") = 0, + py::arg("arg1") = 0, + py::arg("arg2") = 0, + py::arg("length") = 0, + D(message,make) + ) + + + + + + + .def_static("make_from_string",&message::make_from_string, + py::arg("s"), + py::arg("type") = 0, + py::arg("arg1") = 0, + py::arg("arg2") = 0, + D(message,make_from_string) + ) + + + + .def("type",&message::type, + D(message,type) + ) + + + + .def("arg1",&message::arg1, + D(message,arg1) + ) + + + + .def("arg2",&message::arg2, + D(message,arg2) + ) + + + + .def("set_type",&message::set_type, + py::arg("type"), + D(message,set_type) + ) + + + + .def("set_arg1",&message::set_arg1, + py::arg("arg1"), + D(message,set_arg1) + ) + + + + .def("set_arg2",&message::set_arg2, + py::arg("arg2"), + D(message,set_arg2) + ) + + + + .def("msg",&message::msg, + D(message,msg) + ) + + + + .def("to_string",&message::to_string, + D(message,to_string) + ) + + ; + + + + m.def("message_ncurrently_allocated",&::gr::op25::message_ncurrently_allocated, + D(message_ncurrently_allocated) + ); + + + +} + + + + + + + + diff --git a/op25/gr-op25/python/op25/bindings/msg_handler_python.cc b/op25/gr-op25/python/op25/bindings/msg_handler_python.cc new file mode 100644 index 0000000..ae5c488 --- /dev/null +++ b/op25/gr-op25/python/op25/bindings/msg_handler_python.cc @@ -0,0 +1,64 @@ +/* + * Copyright 2022 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +/***********************************************************************************/ +/* This file is automatically generated using bindtool and can be manually edited */ +/* The following lines can be configured to regenerate this file during cmake */ +/* If manual edits are made, the following tags should be modified accordingly. */ +/* BINDTOOL_GEN_AUTOMATIC(0) */ +/* BINDTOOL_USE_PYGCCXML(0) */ +/* BINDTOOL_HEADER_FILE(msg_handler.h) */ +/* BINDTOOL_HEADER_FILE_HASH(668ae41ad9b9d463886fcf60a87e9ede) */ +/***********************************************************************************/ + +#include +#include +#include + +namespace py = pybind11; + +#include +// pydoc.h is automatically generated in the build directory +#include + +void bind_msg_handler(py::module& m) +{ + + using msg_handler = ::gr::op25::msg_handler; + + + py::class_>(m, "msg_handler", D(msg_handler)) + + // .def(py::init<>(),D(msg_handler,msg_handler,0)) + // .def(py::init(), py::arg("arg0"), + // D(msg_handler,msg_handler,1) + // ) + + + + .def("handle",&msg_handler::handle, + py::arg("msg"), + D(msg_handler,handle) + ) + + ; + + + + +} + + + + + + + + diff --git a/op25/gr-op25/python/op25/bindings/msg_queue_python.cc b/op25/gr-op25/python/op25/bindings/msg_queue_python.cc new file mode 100644 index 0000000..63027cd --- /dev/null +++ b/op25/gr-op25/python/op25/bindings/msg_queue_python.cc @@ -0,0 +1,116 @@ +/* + * Copyright 2022 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +/***********************************************************************************/ +/* This file is automatically generated using bindtool and can be manually edited */ +/* The following lines can be configured to regenerate this file during cmake */ +/* If manual edits are made, the following tags should be modified accordingly. */ +/* BINDTOOL_GEN_AUTOMATIC(0) */ +/* BINDTOOL_USE_PYGCCXML(0) */ +/* BINDTOOL_HEADER_FILE(msg_queue.h) */ +/* BINDTOOL_HEADER_FILE_HASH(3f70adbde5e636fca8dc78e0505b06fd) */ +/***********************************************************************************/ + +#include +#include +#include + +namespace py = pybind11; + +#include +// pydoc.h is automatically generated in the build directory +#include + +void bind_msg_queue(py::module& m) +{ + + using msg_queue = ::gr::op25::msg_queue; + + + py::class_>(m, "msg_queue", D(msg_queue)) + + .def(py::init(&msg_queue::make), + py::arg("limit") = 0, + D(msg_queue,make) + ) + + + + + + + .def("handle",&msg_queue::handle, + py::arg("msg"), + D(msg_queue,handle) + ) + + + + .def("insert_tail",&msg_queue::insert_tail, + py::arg("msg"), + D(msg_queue,insert_tail) + ) + + + + .def("delete_head",&msg_queue::delete_head, py::call_guard(), + D(msg_queue,delete_head) + ) + + + + .def("delete_head_nowait",&msg_queue::delete_head_nowait, + D(msg_queue,delete_head_nowait) + ) + + + + .def("flush",&msg_queue::flush, + D(msg_queue,flush) + ) + + + + .def("empty_p",&msg_queue::empty_p, + D(msg_queue,empty_p) + ) + + + + .def("full_p",&msg_queue::full_p, + D(msg_queue,full_p) + ) + + + + .def("count",&msg_queue::count, + D(msg_queue,count) + ) + + + + .def("limit",&msg_queue::limit, + D(msg_queue,limit) + ) + + ; + + + + +} + + + + + + + +