Thursday, 27 March 2008

BoostCon '08

I figure it's about time to announce that I will be giving a hands-on tutorial regarding the Boost.Serialization library this year at BoostCon.

I went last year as a spectator and thoroughly enjoyed myself (I know, sad!) This year has a lot of new and interesting sessions. The keynote speaker is Bjarne Stroustrup. How cool is that?!

Anyway, If you sign up before April 1st, you get the early bird special. If you are planning to go, might as well sign up and get the savings. Not to mention the beautiful surroundings (Aspen!) It is gorgeous. This time I am taking my camera.

If you are coming, please leave a note so we can meet!

Monday, 24 March 2008

A lame implementation of dynamic scoping in C++

This is very lame. I have nothing to say for myself except I'm very sorry.

#include <vector>
#include <iostream>
#include <boost/thread/tss.hpp>

#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/thread/barrier.hpp>

/**
Dynamic scoping is a form of scoping where the bindings associated
with variables are determined at runtime.

C++ has lexical scoping which is a form of scoping where the
bindings associated with are known at compile-time.

This piece of code is a half-assed implementation of thread-safe
dynamic variables in C++. See the main function in this file for a
"test" of the thread-safety

If I cared enough, I would make the variables get the global
bindings when new threads were created but as of now, they only get
the default value.

Alas, I don't care enough.

Usage:

// at global scope
dynamic_variable<int> dv_foo(5); // default value
dynamic_variable<double> dv_bar; // defaults to 0

void print()
{
std::cout << "FOO: " << dv_foo() << " BAR: " << dv_bar() << std::endl;
}

int main(int argc, char * argv[])
{
{
dynamic_bind<int> foo(dv_foo,10);
dynamic_bind<double> bar(dv_bar,10);
print();
}
{
dynamic_bind<int> foo(dv_foo,20);
dynamic_bind<double> bar(dv_bar,20);
print();
}
print();
}

output:
FOO: 10 BAR: 10
FOO: 20 BAR: 20
FOO: 5 BAR: 0
**/


template
<typename T> struct dynamic_bind;

template
<typename T>

struct
dynamic_variable
{

dynamic_variable(T const & t)
:
initial_value_(t)
{


init();
}

dynamic_variable()
:
initial_value_(T())
{

init();
}


T & operator()()
{

init();
return
bindings_.get()->back();
}


private
:
friend class
dynamic_bind<T>;

void
init()
{


if
(!bindings_.get())
{

bindings_.reset(new std::vector<T>());

bind(initial_value_);
}
}


void
bind(T const & t)
{


init();
bindings_.get()->push_back(t);
}

void
unbind()
{


init();
bindings_.get()->pop_back();
}


boost::thread_specific_ptr<std::vector<T> > bindings_;

T initial_value_;
};


template
<typename T>
struct
dynamic_bind
{

dynamic_bind(dynamic_variable<T> & var,

T const & t):
var_(var)
{

var_.bind(t);
}
~
dynamic_bind()
{


var_.unbind();
}

private
:
dynamic_variable<T> & var_;
};



dynamic_variable<int> dv_thread_id(0);
dynamic_variable<std::string> dv_x;

dynamic_variable<std::string> dv_y("global y");

void
reader()
{

std::cout << "In thread " << dv_thread_id()
<<
", x = " << dv_x()
<<
", y = " << dv_y()
<<
std::endl;
}


void
setter()
{

boost::barrier wait_for(2);

dynamic_bind<std::string> x(dv_x,"setter::x1");
{


// yield to allow for interleaving of threads
boost::thread::yield();
dynamic_bind<std::string> x(dv_x,"setter::x2");

// first time this function is called, y has not
// been dynamically rebound, so y will have its
// default value
reader();
}

dynamic_bind<std::string> y(dv_y,"setter::y1");
{


boost::thread::yield();
reader();
}
}


void
threadfunc(int threadid)
{


dynamic_bind<int> thread_id(dv_thread_id,threadid);
setter();
}


int
main()
{


std::cout << "In main..." << std::endl;
boost::thread t1(boost::bind(threadfunc,1));

boost::thread t2(boost::bind(threadfunc,2));
t1.join();

t2.join();
}


Friday, 14 March 2008

Piracy surcharge? Wtf? Think of the kittens!

Totally off-topic.

Music industry proposes a piracy surcharge on ISPs.

You know, you'd think they would realize that being able to charge $5/month/user results in big $$$. Big enough so that you *don't* need to call it piracy anymore. I think everyone I know would gladly pay $X/month to have access to the world's music collection in high quality. But if you call it a piracy surcharge, I ain't paying. How about calling it a "music access surcharge" or something that is more indicative of its purpose.

Mmmmkay, lets do the math:


  1. Let's say $1.50 per broadband user per month (I'm sorry, $5 for you not providing any infrastructure is too much.)

  2. Let's say oh 33.9 million *subscribers* in America alone



Per-month, that works out to: 50.85 million dollars in America for doing nothing special except promising not to sue anyone.

Per-year, that works out to $610 million dollars in America alone, again, for doing nothing special. You could probably get double that if you get the European countries and Canada on board.

I'd *love* to own that business. No distribution costs? That is ridiculous! This is the new world order people.

Wednesday, 5 March 2008

Update: Serializing Boost.Tuple using Boost.Serialization

So as I often do while sleeping, I was thinking about the code I posted yesterday and I realized that it was way more complicated than it needed to be. I started out by writing:

template<typename Archive, typename T1>

void
serialize(Archive & ar,
boost::tuple<T1> & t,

const
unsigned int)
{

ar & t.get<0>();
}


But for some reason, when generalizing for more than one element, I starting using the head and tail members of the tuple. What I should have focused on was generating:
template<typename Archive, typename T1>

void
serialize(Archive & ar,
boost::tuple<T1> & t,

const
unsigned int)
{

ar & t.get<0>();
}


template
<typename Archive, typename T1, T2>
void
serialize(Archive & ar,

boost::tuple<T1,T2> & t,

const
unsigned int)
{


ar & t.get<0>();
ar & t.get<1>();
}
...

And in fact, this is quite easy to do using just the Boost Preprocessor. So simple that I smacked myself when I thought of it:

#include <boost/tuple/tuple.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/preprocessor/repetition.hpp>

namespace boost { namespace serialization {

#define GENERATE_ELEMENT_SERIALIZE(z,which,unused) \
ar & boost::serialization::make_nvp("element",t.get< which >());

#define GENERATE_TUPLE_SERIALIZE(z,nargs,unused) \
template< typename Archive, BOOST_PP_ENUM_PARAMS(nargs,typename T) > \
void serialize(Archive & ar, \
boost::tuple< BOOST_PP_ENUM_PARAMS(nargs,T) > & t, \
const unsigned int version) \
{ \
BOOST_PP_REPEAT_FROM_TO(0,nargs,GENERATE_ELEMENT_SERIALIZE,~); \
}


BOOST_PP_REPEAT_FROM_TO(1,6,GENERATE_TUPLE_SERIALIZE,~);

}}

Tuesday, 4 March 2008

Serializing Boost.Tuple using Boost.Serialization

Note: there is an update here. This post is entertainment only!

If you are using Boost Serialization, at some point, you will have to serialize instances of a class that you cannot alter. Perhaps it is from a third-party library like Boost. One example of a class you might want to serialize is Boost Tuple.

The way one normally serializes instances of a class using Boost Serialization is by inserting a template member function:

#include <boost/archive/text_oarchive.hpp>
#include <iostream>

struct
foo

{

foo(int bar):bar(bar){}
template
<typename Archive>

void
serialize(Archive & ar, const unsigned int)
{

ar & bar;
}


private
:
int
bar;
};


int
main()
{

foo f(5);;

boost::archive::text_oarchive ar(std::cout);
ar & f;
}



But if you want to serialize something like Boost Tuple, you can't really go and modify the code to add the serialize member. Technically, you could but it would be a maintenance headache. Instead, you would use non-intrusive serialization which looks something like this:
#include <boost/tuple/tuple.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <sstream>
#include <iostream>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>

namespace
boost { namespace serialization {

template
<typename Archive, typename T1>
void
serialize(Archive & ar, boost::tuple<T1> & t, const unsigned int)
{


ar & t.get<0>();
}
}}


template
<typename TupleType>
void
test(TupleType t)
{


std::ostringstream os;
{

boost::archive::text_oarchive ar(os);
ar & boost::serialization::make_nvp("tuple",t);
}


TupleType t2;
{

std::istringstream is(os.str());
boost::archive::text_iarchive ar(is);

ar & boost::serialization::make_nvp("tuple",t2);
}

std::cout << t << " == " << t2 << " ? " << std::boolalpha << (t==t2) << std::endl;
}


int
main()
{

test(boost::make_tuple(1.0));
}


The above code will work just fine for a tuple with only one element but will fail for any tuples with more than one element.

Under the hood, boost::tuple is a template class with a fixed number of template parameters all defaulting to boost::tuples::null_type. So one way to serialize all tuples with at most five elements is to write the above free serialize function five times over. That is really as much fun as it sounds. So lets make it a bit more fun!

In a language like Lisp, you would generate the code by writing a macro. However, C++ macros are nowhere near as easy-to-use as Lisp macros. But the good/insane guys at Boost have pushed the limits and have developed a set of preprocessor macros that add the control flow statements you have come to love like looping and if statements. Thats right, looping!

So to make it more fun, we must abuse the C++ preprocessor and have it generate the code we need.

There are multiple ways to iterate using Boost.Preprocessor. The one I will use (for no particular reason) is BOOST_PP_REPEAT_FROM_TO(first,last,macro,data). This macro causes the argument passed in for the macro argument to be evaluated last-first times.

The expected signature for this macro is macro(z,iteration,data). z is simply the next available repetition dimension and data is any other stuff you want to pass in. For the vast majority of stuff, I think you ignore these two parameters. iteration will take on the values first, first+1,...,last-1.

In our case, we would like to call BOOST_PP_REPEAT_FROM_TO(0,6,GENERATE_TUPLE_SERIALIZE,~). Even though we do not make any use of the last parameter, we must still provide a value. Now the rest is fairly mechanical. We need to write GENERATE_TUPLE_SERIALIZE. From the above, we can see the signature should look something like #define GENERATE_TUPLE_SERIALIZE(z,n,unused). So lets take a stab at it:
#define GENERATE_TUPLE_SERIALIZE(z,nargs,unused)                            \
template< typename Archive, BOOST_PP_ENUM_PARAMS(nargs,typename T) > \
void serialize(Archive & ar, \
boost::tuple< BOOST_PP_ENUM_PARAMS(nargs,T) > & t, \
const unsigned int version) \
{ \
ar & boost::serialization::make_nvp("head",t.head); \
ar & boost::serialization::make_nvp("tail",t.tail); \
}


Too easy :-)

Peeking under the hood (but still public API) for Boost Tuple, we see that each tuple is really a cons, albeit a compile-time one. This is done through inheritance. So for example, boost::tuple<int> is really boost::tuples::cons<int,boost::tuples::null_type>.

When we access t.tail in the above definition of serialize, we are accessing one of these cons structures. So if we compiled the code as is, that is:
#include <boost/tuple/tuple.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <boost/preprocessor/repetition.hpp>

#include <sstream>
#include <iostream>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>


namespace
boost { namespace serialization {

#define GENERATE_TUPLE_SERIALIZE(z,nargs,unused) \
template< typename Archive, BOOST_PP_ENUM_PARAMS(nargs,typename T) > \
void serialize(Archive & ar, \
boost::tuple< BOOST_PP_ENUM_PARAMS(nargs,T) > & t, \
const unsigned int version) \
{ \
ar & boost::serialization::make_nvp("head",t.head); \
ar & boost::serialization::make_nvp("tail",t.tail); \
}


BOOST_PP_REPEAT_FROM_TO(1,6,GENERATE_TUPLE_SERIALIZE,~);

}}


template
<typename TupleType>

void
test(TupleType t)
{

std::ostringstream os;
{

boost::archive::text_oarchive ar(os);

ar & boost::serialization::make_nvp("tuple",t);
}

TupleType t2;
{


std::istringstream is(os.str());
boost::archive::text_iarchive ar(is);

ar & boost::serialization::make_nvp("tuple",t2);
}

std::cout << t << " == " << t2 << " ? " << std::boolalpha << (t==t2) << std::endl;
}


int
main()
{

test(boost::make_tuple(1.0));
}



We would get a compile error:

serialize3.cpp:23: error: ‘class boost::tuples::tuple<double, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type>’ has no member named ‘tail’

The reason for this is that a one element tuple has no tail. There are multiple ways to solve this problem, but I think the neatest is to treat 1-element tuples (ignore 0-element tuples) as special cases and treat the rest as generic. The new serialization code looks like:

namespace boost { namespace serialization {

template
<typename Archive, typename T1>
void
serialize(Archive & ar,

boost::tuple<T1> & t,
const
unsigned int)
{

ar & boost::serialization::make_nvp("head",t.head);
}


#define GENERATE_TUPLE_SERIALIZE(z,nargs,unused) \
template< typename Archive, BOOST_PP_ENUM_PARAMS(nargs,typename T) > \
void serialize(Archive & ar, \
boost::tuple< BOOST_PP_ENUM_PARAMS(nargs,T) > & t, \
const unsigned int version) \
{ \
ar & boost::serialization::make_nvp("head",t.head); \
ar & boost::serialization::make_nvp("tail",t.tail); \
}


BOOST_PP_REPEAT_FROM_TO(2,6,GENERATE_TUPLE_SERIALIZE,~);

}}


If we compile this, we get yet another error:
/usr/include/boost/serialization/access.hpp:109: 

error:struct boost::tuples::cons<int, boost::tuples::cons<char,

boost::tuples::cons<std::basic_string<char, std::char_traits<char>,

std::allocator<char> >, boost::tuples::null_type> > >’ has no member
named ‘serialize’

Almost home free! The reason we get this error is that when we reference the tail member of the tuple, that is a cons object, not a tuple. So we need two more functions:
    template<typename Archive, typename T1>

void
serialize(Archive & ar,
boost::tuples::cons<T1,boost::tuples::null_type> & t,

const
unsigned int)
{

ar & boost::serialization::make_nvp("head",t.head);
}


template
<typename Archive, typename T1, typename T2>

void
serialize(Archive & ar,
boost::tuples::cons<T1,T2> & t,

const
unsigned int)
{

ar & boost::serialization::make_nvp("head",t.head);

ar & boost::serialization::make_nvp("tail",t.tail);
}



With that, the final code looks like:
#include <boost/tuple/tuple.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <boost/preprocessor/repetition.hpp>

#include <sstream>
#include <iostream>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>


namespace
boost { namespace serialization {

template
<typename Archive, typename T1>

void
serialize(Archive & ar,
boost::tuples::cons<T1,boost::tuples::null_type> & t,

const
unsigned int)
{

ar & boost::serialization::make_nvp("head",t.head);
}


template
<typename Archive, typename T1, typename T2>

void
serialize(Archive & ar,
boost::tuples::cons<T1,T2> & t,

const
unsigned int)
{

ar & boost::serialization::make_nvp("head",t.head);

ar & boost::serialization::make_nvp("tail",t.tail);
}


template
<typename Archive, typename T1>
void
serialize(Archive & ar,

boost::tuple<T1> & t,
const
unsigned int)
{

ar & boost::serialization::make_nvp("head",t.head);
}


#define GENERATE_TUPLE_SERIALIZE(z,nargs,unused) \
template< typename Archive, BOOST_PP_ENUM_PARAMS(nargs,typename T) > \
void serialize(Archive & ar, \
boost::tuple< BOOST_PP_ENUM_PARAMS(nargs,T) > & t, \
const unsigned int version) \
{ \
ar & boost::serialization::make_nvp("head",t.head); \
ar & boost::serialization::make_nvp("tail",t.tail); \
}


BOOST_PP_REPEAT_FROM_TO(2,6,GENERATE_TUPLE_SERIALIZE,~);

}}


template
<typename TupleType>

void
test(TupleType t)
{

std::ostringstream os;
{

boost::archive::text_oarchive ar(os);

ar & boost::serialization::make_nvp("tuple",t);
}

TupleType t2;
{


std::istringstream is(os.str());
boost::archive::text_iarchive ar(is);

ar & boost::serialization::make_nvp("tuple",t2);
}

std::cout << t << " == " << t2 << " ? " << std::boolalpha << (t==t2) << std::endl;
}


int
main()
{

test(boost::make_tuple(1.0));
test(boost::make_tuple(1.0,1));

test(boost::make_tuple(1.0,1,'c'));
test(boost::make_tuple(1.0,1,'c',std::string("FOO!")));
}



Compiling and running the code, we get the expected output:

/tmp$ g++ serialize6.cpp -lboost_serialization && ./a.out
(1) == (1) ? true
(1 1) == (1 1) ? true
(1 1 c) == (1 1 c) ? true
(1 1 c FOO!) == (1 1 c FOO!) ? true


Why did I do this? Someone asked and I was waiting for a process to finish running. That and I tend to do bursts of random C++ code when I am sick (which I am today!)