Here is another series of patches. These come in 3 flavours:

Independent, general cleanups and additions, which neither influence API nor 
ABI
        c1255: Minor optimization, assume well formed list as common case
        c1256: Avoid some double type casting
        c1261: Add some unit test for pmt_subsetp and pmt_memq

Changes in ABI, changing no functionality
        c1257: Make function arguments const& (incomplete)
        c1260: Make function arguments const& (continued)

Intrusive changes (pun intended)
        c1258: Switch from shared_ptr to intrusive_ptr for pmt_t

Some more comments:
Patches in the first group should need no further discussion, as these are 
just some optimizations which are completely invisible (despite speedup) from 
the outside.
The second group should be unproblematic as well. Although a recompile of 
anything dependent on pmt is needed, behaviour is unchanged.

The third one may need some more comments:
currently (trunk) pmt_t is defined as boost::shared_ptr<pmt_base>. Although 
the refcounting is quite nice, it comes at a quite high cost. Every shared 
pointer is combined from 3 objects, one being the "data" (in this case, 
pmt_base), one the object for the refcounting, and the third one the 
shared_ptr itself, holding pointers to two aforementioned objects. The last 
one may be created on the stack, but the other two are allocated on the heap.

This costs are cut by half if using intrusive_ptr's. The refcount is stored in 
the object itself. Some more speed is gained by the fact that some operations 
are just simpler for intrusive_ptr than for shared_ptr (have a look at eg 
operator= ....). Although the gain is high, there are no code changes needed, 
just a simple recompile

All patches have been tested by running the mblock and pmt qa tests.

---
Benchmarks:
P4 HT @ 2.80GHz
test_usrp_inband_tx with a constant value for the signal generator:

Results of running "time ./test_usrp_inband_tx" (trunk)
real    0m20.670s
user    0m7.348s
sys     0m2.328s

Results of running "time ./test_usrp_inband_tx" (all patches applied)
real    0m20.574s
user    0m3.632s
sys     0m1.992s
---

Regards,

Stefan

PS: Not finished yet. Next is switching pmt_list* from pairs to vectors and 
mb_message to intrusive_ptr as well. Also nice to have: lockless 
implementation of the message queue ...

-- 
Stefan Brüns  /  Bergstraße 21  /  52062 Aachen
mailto:lurch at gmx.li  http://www.kawo1.rwth-aachen.de/~lurchi/
   phone: +49 241 53809034     mobile: +49 151 50412019
=== modified file 'pmt/src/lib/pmt.cc'
--- pmt/src/lib/pmt.cc	2008-06-26 17:17:15 +0000
+++ pmt/src/lib/pmt.cc	2009-01-30 14:36:53 +0000
@@ -864,7 +864,7 @@
 pmt_t
 pmt_nthcdr(size_t n, pmt_t list)
 {
-  if (!(pmt_is_null(list) || pmt_is_pair(list)))
+  if (!(pmt_is_pair(list) || pmt_is_null(list)))
     throw pmt_wrong_type("pmt_nthcdr", list);
     
   while (n > 0){

=== modified file 'pmt/src/lib/pmt.cc'
--- pmt/src/lib/pmt.cc	2009-01-30 14:41:35 +0000
+++ pmt/src/lib/pmt.cc	2009-01-30 16:13:12 +0000
@@ -938,43 +938,43 @@
 }
 
 pmt_t
-pmt_list1(pmt_t x1)
+pmt_list1(const pmt_t& x1)
 {
   return pmt_cons(x1, PMT_NIL);
 }
 
 pmt_t
-pmt_list2(pmt_t x1, pmt_t x2)
+pmt_list2(const pmt_t& x1, const pmt_t& x2)
 {
   return pmt_cons(x1, pmt_cons(x2, PMT_NIL));
 }
 
 pmt_t
-pmt_list3(pmt_t x1, pmt_t x2, pmt_t x3)
+pmt_list3(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3)
 {
   return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, PMT_NIL)));
 }
 
 pmt_t
-pmt_list4(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4)
+pmt_list4(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4)
 {
   return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, PMT_NIL))));
 }
 
 pmt_t
-pmt_list5(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5)
+pmt_list5(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& x4, const pmt_t& x5)
 {
   return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, pmt_cons(x5, PMT_NIL)))));
 }
 
 pmt_t
-pmt_list6(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5, pmt_t x6)
+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)
 {
   return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, pmt_cons(x5, pmt_cons(x6, PMT_NIL))))));
 }
 
 pmt_t
-pmt_list_add(pmt_t list, pmt_t item)
+pmt_list_add(pmt_t list, const pmt_t& item)
 {
   return pmt_reverse(pmt_cons(item, pmt_reverse(list)));
 }

=== modified file 'pmt/src/lib/pmt.h'
--- pmt/src/lib/pmt.h	2009-01-30 14:41:35 +0000
+++ pmt/src/lib/pmt.h	2009-01-30 16:13:12 +0000
@@ -583,38 +583,38 @@
 /*!
  * \brief Return a list of length 1 containing \p x1
  */
-pmt_t pmt_list1(pmt_t x1);
+pmt_t pmt_list1(const pmt_t& x1);
 
 /*!
  * \brief Return a list of length 2 containing \p x1, \p x2
  */
-pmt_t pmt_list2(pmt_t x1, pmt_t x2);
+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
  */
-pmt_t pmt_list3(pmt_t x1, pmt_t x2, pmt_t x3);
+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
  */
-pmt_t pmt_list4(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4);
+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
  */
-pmt_t pmt_list5(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5);
+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
  */
-pmt_t pmt_list6(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5, pmt_t x6);
+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.
  */
-pmt_t pmt_list_add(pmt_t list, pmt_t item);
+pmt_t pmt_list_add(pmt_t list, const pmt_t& item);
 
 
 /*

=== modified file 'pmt/src/lib/qa_pmt_prims.cc'
--- pmt/src/lib/qa_pmt_prims.cc	2008-04-30 02:52:31 +0000
+++ pmt/src/lib/qa_pmt_prims.cc	2009-01-30 16:45:49 +0000
@@ -413,3 +413,24 @@
   // FIXME add tests for malformed input too.
 
 }
+
+void
+qa_pmt_prims::test_sets()
+{
+  pmt_t s1 = pmt_intern("s1");
+  pmt_t s2 = pmt_intern("s2");
+  pmt_t s3 = pmt_intern("s3");
+
+  pmt_t l1 = pmt_list1(s1);
+  pmt_t l2 = pmt_list2(s2,s3);
+  pmt_t l3 = pmt_list3(s1,s2,s3);
+
+  CPPUNIT_ASSERT(pmt_is_pair(pmt_memq(s1,l1)));
+  CPPUNIT_ASSERT(pmt_is_false(pmt_memq(s3,l1)));
+
+  CPPUNIT_ASSERT(pmt_subsetp(l1,l3));
+  CPPUNIT_ASSERT(pmt_subsetp(l2,l3));
+  CPPUNIT_ASSERT(!pmt_subsetp(l1,l2));
+  CPPUNIT_ASSERT(!pmt_subsetp(l2,l1));
+  CPPUNIT_ASSERT(!pmt_subsetp(l3,l2));
+}

=== modified file 'pmt/src/lib/qa_pmt_prims.h'
--- pmt/src/lib/qa_pmt_prims.h	2008-04-30 02:52:31 +0000
+++ pmt/src/lib/qa_pmt_prims.h	2009-01-30 16:45:49 +0000
@@ -42,6 +42,7 @@
   CPPUNIT_TEST(test_io);
   CPPUNIT_TEST(test_lists);
   CPPUNIT_TEST(test_serialize);
+  CPPUNIT_TEST(test_sets);
   CPPUNIT_TEST_SUITE_END();
 
  private:
@@ -59,6 +60,7 @@
   void test_io();
   void test_lists();
   void test_serialize();
+  void test_sets();
 };
 
 #endif /* INCLUDED_QA_PMT_PRIMS_H */

=== modified file 'pmt/src/lib/pmt.cc'
--- pmt/src/lib/pmt.cc	2009-01-30 14:36:53 +0000
+++ pmt/src/lib/pmt.cc	2009-01-30 14:37:30 +0000
@@ -292,8 +292,9 @@
 long
 pmt_to_long(pmt_t x)
 {
-  if (x->is_integer())
-    return _integer(x)->value();
+  pmt_integer* i = dynamic_cast<pmt_integer*>(x.get());
+  if ( i )
+    return i->value();
 
   throw pmt_wrong_type("pmt_to_long", x);
 }
@@ -386,8 +387,9 @@
 pmt_t
 pmt_car(pmt_t pair)
 {
-  if (pair->is_pair())
-    return _pair(pair)->car();
+  pmt_pair* p = dynamic_cast<pmt_pair*>(pair.get());
+  if ( p )
+    return p->car();
   
   throw pmt_wrong_type("pmt_car", pair);
 }
@@ -395,8 +397,9 @@
 pmt_t
 pmt_cdr(pmt_t pair)
 {
-  if (pair->is_pair())
-    return _pair(pair)->cdr();
+  pmt_pair* p = dynamic_cast<pmt_pair*>(pair.get());
+  if ( p )
+    return p->cdr();
   
   throw pmt_wrong_type("pmt_cdr", pair);
 }
@@ -585,28 +588,31 @@
 void
 pmt_dict_set(pmt_t dict, pmt_t key, pmt_t value)
 {
-  if (!dict->is_dict())
+  pmt_dict* d = _dict(dict);
+  if (!d)
     throw pmt_wrong_type("pmt_dict_set", dict);
 
-  _dict(dict)->set(key, value);
+  d->set(key, value);
 }
 
 bool
 pmt_dict_has_key(pmt_t dict, pmt_t key)
 {
-  if (!dict->is_dict())
+  pmt_dict* d = _dict(dict);
+  if (!d)
     throw pmt_wrong_type("pmt_dict_has_key", dict);
 
-  return _dict(dict)->has_key(key);
+  return d->has_key(key);
 }
 
 pmt_t
 pmt_dict_ref(pmt_t dict, pmt_t key, pmt_t not_found)
 {
-  if (!dict->is_dict())
+  pmt_dict* d = _dict(dict);
+  if (!d)
     throw pmt_wrong_type("pmt_dict_ref", dict);
 
-  return _dict(dict)->ref(key, not_found);
+  return d->ref(key, not_found);
 }
 
 pmt_t

=== modified file 'pmt/src/lib/pmt.cc'
--- pmt/src/lib/pmt.cc	2009-01-30 14:37:30 +0000
+++ pmt/src/lib/pmt.cc	2009-01-30 14:40:12 +0000
@@ -219,7 +219,7 @@
 }
 
 bool 
-pmt_is_symbol(pmt_t obj)
+pmt_is_symbol(const pmt_t& obj)
 {
   return obj->is_symbol();
 }
@@ -250,7 +250,7 @@
 }
 
 const std::string
-pmt_symbol_to_string(pmt_t sym)
+pmt_symbol_to_string(const pmt_t& sym)
 {
   if (!sym->is_symbol())
     throw pmt_wrong_type("pmt_symbol_to_string", sym);
@@ -364,28 +364,28 @@
 ////////////////////////////////////////////////////////////////////////////
 
 pmt_null::pmt_null() {}
-pmt_pair::pmt_pair(pmt_t car, pmt_t cdr) : d_car(car), d_cdr(cdr) {}
+pmt_pair::pmt_pair(const pmt_t& car, const pmt_t& cdr) : d_car(car), d_cdr(cdr) {}
 
 bool
-pmt_is_null(pmt_t x)
+pmt_is_null(const pmt_t& x)
 {
   return x == PMT_NIL;
 }
 
 bool
-pmt_is_pair(pmt_t obj)
+pmt_is_pair(const pmt_t& obj)
 {
   return obj->is_pair();
 }
 
 pmt_t
-pmt_cons(pmt_t x, pmt_t y)
+pmt_cons(const pmt_t& x, const pmt_t& y)
 {
   return pmt_t(new pmt_pair(x, y));
 }
 
 pmt_t
-pmt_car(pmt_t pair)
+pmt_car(const pmt_t& pair)
 {
   pmt_pair* p = dynamic_cast<pmt_pair*>(pair.get());
   if ( p )
@@ -395,7 +395,7 @@
 }
 
 pmt_t
-pmt_cdr(pmt_t pair)
+pmt_cdr(const pmt_t& pair)
 {
   pmt_pair* p = dynamic_cast<pmt_pair*>(pair.get());
   if ( p )
@@ -681,13 +681,13 @@
 ////////////////////////////////////////////////////////////////////////////
 
 bool
-pmt_eq(pmt_t x, pmt_t y)
+pmt_eq(const pmt_t& x, const pmt_t& y)
 {
   return x == y;
 }
 
 bool
-pmt_eqv(pmt_t x, pmt_t y)
+pmt_eqv(const pmt_t& x, const pmt_t& y)
 {
   if (x == y)
     return true;
@@ -705,7 +705,7 @@
 }
 
 bool
-pmt_equal(pmt_t x, pmt_t y)
+pmt_equal(const pmt_t& x, const pmt_t& y)
 {
   if (pmt_eqv(x, y))
     return true;
@@ -747,7 +747,7 @@
 }
 
 size_t
-pmt_length(pmt_t x)
+pmt_length(const pmt_t& x)
 {
   if (x->is_vector())
     return _vector(x)->length();
@@ -755,13 +755,16 @@
   if (x->is_uniform_vector())
     return _uniform_vector(x)->length();
 
-  if (x->is_pair() || x->is_null()) {
-    size_t length=0;
-    while (pmt_is_pair(x)){
+  if (x->is_null()) return 0;
+
+  if (x->is_pair()) {
+    size_t length=1;
+	pmt_t it = pmt_cdr(x);
+    while (pmt_is_pair(it)){
       length++;
-      x = pmt_cdr(x);
+      it = pmt_cdr(it);
     }
-    if (pmt_is_null(x))
+    if (pmt_is_null(it))
       return length;
 
     // not a proper list
@@ -822,7 +825,7 @@
 }
 
 pmt_t
-pmt_map(pmt_t proc(pmt_t), pmt_t list)
+pmt_map(pmt_t proc(const pmt_t&), pmt_t list)
 {
   pmt_t r = PMT_NIL;
 

=== modified file 'pmt/src/lib/pmt.h'
--- pmt/src/lib/pmt.h	2008-06-26 17:17:15 +0000
+++ pmt/src/lib/pmt.h	2009-01-30 14:40:12 +0000
@@ -109,7 +109,7 @@
  */
 
 //! Return true if obj is a symbol, else false.
-bool pmt_is_symbol(pmt_t obj);
+bool pmt_is_symbol(const pmt_t& obj);
 
 //! Return the symbol whose name is \p s.
 pmt_t pmt_string_to_symbol(const std::string &s);
@@ -122,7 +122,7 @@
  * If \p is a symbol, return the name of the symbol as a string.
  * Otherwise, raise the wrong_type exception.
  */
-const std::string pmt_symbol_to_string(pmt_t sym);
+const std::string pmt_symbol_to_string(const pmt_t& sym);
 
 /*
  * ------------------------------------------------------------------------
@@ -206,19 +206,19 @@
 extern const pmt_t PMT_NIL;	//< the empty list
 
 //! Return true if \p x is the empty list, otherwise return false.
-bool pmt_is_null(pmt_t x);
+bool pmt_is_null(const pmt_t& x);
 
 //! Return true if \p obj is a pair, else false.
-bool pmt_is_pair(pmt_t obj);
+bool pmt_is_pair(const pmt_t& obj);
 
 //! Return a newly allocated pair whose car is \p x and whose cdr is \p y.
-pmt_t pmt_cons(pmt_t x, pmt_t y);
+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.
-pmt_t pmt_car(pmt_t pair);
+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.
-pmt_t pmt_cdr(pmt_t pair);
+pmt_t pmt_cdr(const pmt_t& pair);
 
 //! Stores \p value in the car field of \p pair.
 void pmt_set_car(pmt_t pair, pmt_t value);
@@ -449,7 +449,7 @@
  */
 
 //! Return true if x and y are the same object; otherwise return false.
-bool pmt_eq(pmt_t x, pmt_t y);
+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.
@@ -464,7 +464,7 @@
  *   x and y are pairs or vectors that denote same location in store.
  * </pre>
  */
-bool pmt_eqv(pmt_t x, pmt_t y);
+bool pmt_eqv(const pmt_t& x, const pmt_t& y);
 
 /*!
  * pmt_equal recursively compares the contents of pairs and vectors,
@@ -472,11 +472,11 @@
  * pmt_equal may fail to terminate if its arguments are circular data
  * structures.
  */
-bool pmt_equal(pmt_t x, pmt_t y);
+bool pmt_equal(const pmt_t& x, const pmt_t& y);
 
 
 //! Return the number of elements in v
-size_t pmt_length(pmt_t v);
+size_t pmt_length(const pmt_t& v);
 
 /*!
  * \brief Find the first pair in \p alist whose car field is \p obj
@@ -515,7 +515,7 @@
  * \p list must be a list.  The dynamic order in which \p proc is
  * applied to the elements of \p list is unspecified.
  */
-pmt_t pmt_map(pmt_t proc(pmt_t), pmt_t list);
+pmt_t pmt_map(pmt_t proc(const pmt_t&), pmt_t list);
 
 /*!
  * \brief reverse \p list.

=== modified file 'pmt/src/lib/pmt_int.h'
--- pmt/src/lib/pmt_int.h	2008-06-26 17:17:15 +0000
+++ pmt/src/lib/pmt_int.h	2009-01-30 14:40:12 +0000
@@ -151,7 +151,7 @@
   pmt_t		d_cdr;
 
 public:
-  pmt_pair(pmt_t car, pmt_t cdr);
+  pmt_pair(const pmt_t& car, const pmt_t& cdr);
   //~pmt_pair(){};
 
   bool is_pair() const { return true; }

=== modified file 'pmt/src/lib/pmt.cc'
--- pmt/src/lib/pmt.cc	2009-01-30 14:40:12 +0000
+++ pmt/src/lib/pmt.cc	2009-01-30 14:41:35 +0000
@@ -54,6 +54,8 @@
 
 #endif
 
+void intrusive_ptr_add_ref(pmt_base* p) { ++(p->count_); }
+void intrusive_ptr_release(pmt_base* p) { if (--(p->count_) == 0 ) delete p; }
 
 pmt_base::~pmt_base()
 {

=== modified file 'pmt/src/lib/pmt.h'
--- pmt/src/lib/pmt.h	2009-01-30 14:40:12 +0000
+++ pmt/src/lib/pmt.h	2009-01-30 14:41:35 +0000
@@ -23,7 +23,7 @@
 #ifndef INCLUDED_PMT_H
 #define INCLUDED_PMT_H
 
-#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
 #include <boost/any.hpp>
 #include <complex>
 #include <string>
@@ -48,8 +48,10 @@
  * \brief typedef for shared pointer (transparent reference counting).
  * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
  */
-typedef boost::shared_ptr<pmt_base> pmt_t;
+typedef boost::intrusive_ptr<pmt_base> pmt_t;
 
+extern void intrusive_ptr_add_ref(pmt_base*);
+extern void intrusive_ptr_release(pmt_base*);
 
 class pmt_exception : public std::logic_error
 {

=== modified file 'pmt/src/lib/pmt_int.h'
--- pmt/src/lib/pmt_int.h	2009-01-30 14:40:12 +0000
+++ pmt/src/lib/pmt_int.h	2009-01-30 14:41:35 +0000
@@ -34,8 +34,10 @@
 #define PMT_LOCAL_ALLOCATOR 0		// define to 0 or 1
 
 class pmt_base : boost::noncopyable {
+  mutable boost::detail::atomic_count count_;
+
 protected:
-  pmt_base(){};
+  pmt_base() : count_(0) {};
   virtual ~pmt_base();
 
 public:
@@ -65,6 +67,9 @@
   virtual bool is_c32vector() const { return false; }
   virtual bool is_c64vector() const { return false; }
 
+  friend void intrusive_ptr_add_ref(pmt_base* p);
+  friend void intrusive_ptr_release(pmt_base* p);
+
 # if (PMT_LOCAL_ALLOCATOR)
   void *operator new(size_t);
   void operator delete(void *, size_t);

_______________________________________________
Discuss-gnuradio mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/discuss-gnuradio

Reply via email to