summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Blum2013-06-01 22:46:29 -0700
committerJosh Blum2013-06-01 22:46:29 -0700
commitd15ca88acfbd71c5d4f8ab3dabe0f4fbde205985 (patch)
treee0ba8437cf65503fa05197e774024da4f9b54230
parent40af24eb55d2d43f51d7ada30566d5203f0fef8c (diff)
downloadsandhi-d15ca88acfbd71c5d4f8ab3dabe0f4fbde205985.tar.gz
sandhi-d15ca88acfbd71c5d4f8ab3dabe0f4fbde205985.tar.bz2
sandhi-d15ca88acfbd71c5d4f8ab3dabe0f4fbde205985.zip
gras: created uid API - replaces name and unique_id
m---------gnuradio0
-rw-r--r--include/gras/element.hpp33
-rw-r--r--lib/CMakeLists.txt1
-rw-r--r--lib/block.cpp6
-rw-r--r--lib/block_handlers.cpp2
-rw-r--r--lib/element.cpp41
-rw-r--r--lib/element_impl.hpp7
-rw-r--r--lib/element_uid.cpp46
-rw-r--r--lib/top_block_query.cpp4
9 files changed, 104 insertions, 36 deletions
diff --git a/gnuradio b/gnuradio
-Subproject 2c0627d07360e31bb25ac334d349eb52e27086f
+Subproject f4fc952e58ce318298258926f7382ed28b92bfa
diff --git a/include/gras/element.hpp b/include/gras/element.hpp
index 0aed924..47fbae6 100644
--- a/include/gras/element.hpp
+++ b/include/gras/element.hpp
@@ -56,18 +56,37 @@ struct GRAS_API Element : boost::shared_ptr<ElementImpl>
*/
bool equals(const Element &rhs);
+ /*!
+ * Get a canonical name for this element.
+ * This is used for printing elements for debug purposes.
+ * Do not rely on the string to have any specific formatting.
+ * \return a canonical string representation
+ */
+ std::string to_string(void) const;
+
/*******************************************************************
* identification interface
******************************************************************/
- //! An integer ID that is unique across the process
- long unique_id(void) const;
-
- //! Get the name of this element
- std::string name(void) const;
+ /*!
+ * Set the unique identifier of this element.
+ * The UID must be unique across the process.
+ * Typically the user will set a UID so an element
+ * will have a known indentification for the query client.
+ * This call will throw if UID is not process-unique.
+ * \param uid a new unique identifier for this element
+ */
+ void set_uid(const std::string &uid);
- //! get a canonical name for this element
- std::string to_string(void) const;
+ /*!
+ * Get the unique identifier of this element.
+ * Typically, a name is given to an element on construction.
+ * By default UID will be the name or name + some hash
+ * when there is more than one element of the same name.
+ * Otherwise UID is set the by the set_uid API call.
+ * \return the element's unique identifier as a string
+ */
+ std::string get_uid(void) const;
/*******************************************************************
* element tree interface
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index add46db..38377dd 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -42,6 +42,7 @@ list(APPEND GRAS_SOURCES ${apology_sources})
list(APPEND GRAS_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/debug.cpp
${CMAKE_CURRENT_SOURCE_DIR}/element.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/element_uid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sbuffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/circular_buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/buffer_queue_circ.cpp
diff --git a/lib/block.cpp b/lib/block.cpp
index cd191ad..0059569 100644
--- a/lib/block.cpp
+++ b/lib/block.cpp
@@ -71,7 +71,7 @@ static void wait_block_cleanup(ElementImpl &self)
case BLOCK_CLEANUP_WAIT:
if (boost::get_system_time() > start + boost::posix_time::seconds(1))
{
- std::cerr << self.id << ", waiting for you to finish." << std::endl;
+ std::cerr << self.repr << ", waiting for you to finish." << std::endl;
state = BLOCK_CLEANUP_WARN;
}
break;
@@ -79,7 +79,7 @@ static void wait_block_cleanup(ElementImpl &self)
case BLOCK_CLEANUP_WARN:
if (boost::get_system_time() > start + boost::posix_time::seconds(2))
{
- std::cerr << self.id << ", give up the thread context!" << std::endl;
+ std::cerr << self.repr << ", give up the thread context!" << std::endl;
state = BLOCK_CLEANUP_DAMN;
}
break;
@@ -87,7 +87,7 @@ static void wait_block_cleanup(ElementImpl &self)
case BLOCK_CLEANUP_DAMN:
if (boost::get_system_time() > start + boost::posix_time::seconds(3))
{
- std::cerr << self.id << " FAIL; application will now hang..." << std::endl;
+ std::cerr << self.repr << " FAIL; application will now hang..." << std::endl;
state = BLOCK_CLEANUP_DOTS;
}
break;
diff --git a/lib/block_handlers.cpp b/lib/block_handlers.cpp
index 12ba065..e0ee67a 100644
--- a/lib/block_handlers.cpp
+++ b/lib/block_handlers.cpp
@@ -154,7 +154,7 @@ void BlockActor::handle_get_stats(
//create the message reply object
GetStatsMessage message;
- message.block_id = this->block_ptr->to_string();
+ message.block_id = this->block_ptr->get_uid();
message.stats = this->stats;
message.stats_time = time_now();
diff --git a/lib/element.cpp b/lib/element.cpp
index dfc3f57..04a638b 100644
--- a/lib/element.cpp
+++ b/lib/element.cpp
@@ -3,11 +3,10 @@
#include "element_impl.hpp"
#include <gras/element.hpp>
#include <boost/format.hpp>
-#include <boost/detail/atomic_count.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
-
-static boost::detail::atomic_count unique_id_pool(0);
+#include <boost/functional/hash.hpp>
+#include <cstdlib>
using namespace gras;
@@ -20,8 +19,25 @@ Element::Element(const std::string &name)
{
this->reset(new ElementImpl());
(*this)->name = name;
- (*this)->unique_id = ++unique_id_pool;
- (*this)->id = str(boost::format("%s(%d)") % this->name() % this->unique_id());
+ std::string extra;
+ std::string uid = name;
+ boost::hash<std::string> string_hash;
+ std::size_t h = string_hash(uid);
+ while (true)
+ {
+ try
+ {
+ this->set_uid(uid);
+ break;
+ }
+ catch(const std::invalid_argument &ex)
+ {
+ extra = str(boost::format("%04x") % short(h++));
+ uid = name+"#"+extra;
+ }
+ }
+ if (not extra.empty()) (*this)->repr = name;
+ else (*this)->repr = str(boost::format("%s (%s)") % name % extra);
if (GENESIS) std::cerr << "New element: " << to_string() << std::endl;
}
@@ -58,21 +74,6 @@ bool Element::equals(const Element &rhs)
return this->get() == rhs.get();
}
-long Element::unique_id(void) const
-{
- return (*this)->unique_id;
-}
-
-std::string Element::name(void) const
-{
- return (*this)->name;
-}
-
-std::string Element::to_string(void) const
-{
- return (*this)->id;
-}
-
void Element::adopt_element(const std::string &name, const Element &child)
{
if (child->parent) throw std::invalid_argument(str(boost::format(
diff --git a/lib/element_impl.hpp b/lib/element_impl.hpp
index 89097b4..477b478 100644
--- a/lib/element_impl.hpp
+++ b/lib/element_impl.hpp
@@ -25,10 +25,11 @@ struct ElementImpl
void hier_block_cleanup(void);
void block_cleanup(void);
- //common element properties
+ //element identification
std::string name;
- long unique_id;
- std::string id;
+ std::string repr;
+ boost::shared_ptr<std::string> uid;
+
boost::shared_ptr<WeakContainer> weak_self;
//top block stuff
diff --git a/lib/element_uid.cpp b/lib/element_uid.cpp
new file mode 100644
index 0000000..89035b4
--- /dev/null
+++ b/lib/element_uid.cpp
@@ -0,0 +1,46 @@
+// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information.
+
+#include "element_impl.hpp"
+#include <gras/element.hpp>
+#include <boost/thread/mutex.hpp>
+#include <stdexcept>
+#include <set>
+
+using namespace gras;
+
+static boost::mutex uid_mutex;
+static std::set<std::string> &get_uid_set(void)
+{
+ static std::set<std::string> uid_set;
+ return uid_set;
+}
+
+static void free_uid(void *p)
+{
+ boost::mutex::scoped_lock l(uid_mutex);
+ std::string *uid = reinterpret_cast<std::string *>(p);
+ get_uid_set().erase(*uid);
+ delete uid;
+}
+
+void Element::set_uid(const std::string &uid)
+{
+ boost::mutex::scoped_lock l(uid_mutex);
+ if (get_uid_set().count(uid) > 0)
+ {
+ throw std::invalid_argument("Element::set_uid - uid already in use: " + uid);
+ }
+ (*this)->uid.reset(new std::string(uid), &free_uid);
+ get_uid_set().insert(uid);
+}
+
+std::string Element::get_uid(void) const
+{
+ boost::mutex::scoped_lock l(uid_mutex);
+ return *((*this)->uid);
+}
+
+std::string Element::to_string(void) const
+{
+ return (*this)->repr;
+}
diff --git a/lib/top_block_query.cpp b/lib/top_block_query.cpp
index 9d8afbe..bf74204 100644
--- a/lib/top_block_query.cpp
+++ b/lib/top_block_query.cpp
@@ -56,7 +56,7 @@ static ptree query_blocks(ElementImpl *self, const ptree &)
block_attrs.push_back(std::make_pair(p.first, prop_attrs));
prop_e.push_back(std::make_pair("props", block_attrs));
}
- e.push_back(std::make_pair(block->block_ptr->to_string(), prop_e));
+ e.push_back(std::make_pair(block->block_ptr->get_uid(), prop_e));
}
root.push_back(std::make_pair("blocks", e));
return root;
@@ -80,7 +80,7 @@ static ptree query_stats(ElementImpl *self, const ptree &query)
BOOST_FOREACH(Apology::Worker *worker, self->executor->get_workers())
{
//filter workers not needed in query
- const std::string id = dynamic_cast<BlockActor *>(worker)->block_ptr->to_string();
+ const std::string id = dynamic_cast<BlockActor *>(worker)->block_ptr->get_uid();
if (std::find(block_ids.begin(), block_ids.end(), id) == block_ids.end()) continue;
//send a message to the block's actor to query stats