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