Tuesday, May 22, 2012

C++ books wishlist

1. C++ Concurrency in Action: Practical Multithreading, Anthony Williams, http://www.amazon.com/gp/product/1933988770/
2. API Design for C++, Martin Reddy, http://www.amazon.com/API-Design-C-Martin-Reddy/dp/0123850037/
3. The C++ Standard Library: A Tutorial and Reference (2nd Edition), Nicolai M. Josuttis, http://www.amazon.com/The-Standard-Library-Tutorial-Reference/dp/0321623215/
4. Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition), Scott Meyers, http://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876/

Sunday, May 13, 2012

Boost::Variant as a union-like container for thread messages

How Boost::Variant can be used to carry messages to a thread:

#include <stdint.h>
#include <string>
#include <iostream>
#include <boost/variant.hpp>

using namespace std;

class WorkerMessageBase
{
public:
    typedef enum
    {
        INIT_REQ = 1,
        LOGIN_REQ,
        CLOSE_REQ,

    } MessageType;

    WorkerMessageBase();
    virtual ~WorkerMessageBase();

    inline const MessageType getMessageType(void) const
    {
        return m_msg_type;
    }

protected:
    MessageType m_msg_type;
};

WorkerMessageBase::WorkerMessageBase(){}
WorkerMessageBase::~WorkerMessageBase(){}

class InitReq : public WorkerMessageBase
{
public:
    InitReq()
    {
        m_msg_type = InitReq::INIT_REQ;
    }
protected:
    uint32_t    m_current_time;
};

class LoginReq : public WorkerMessageBase
{
public:
    LoginReq()
    {
        m_msg_type = LoginReq::LOGIN_REQ;
    }
protected:
    bool        m_authenticate;
    string      m_login;
    string      m_password;
};

class CloseReq : public WorkerMessageBase
{
public:
    CloseReq()
    {
        m_msg_type = CloseReq::CLOSE_REQ;
    }
protected:
    uint32_t    m_timeout;
};

typedef boost::variant<
    InitReq,
    LoginReq,
    CloseReq
    > WorkerMessage;

typedef struct
{
    uint32_t        header;
    WorkerMessage   msg;
} message_t;

class Extractor : public boost::static_visitor<WorkerMessageBase *>
{
    public:
    WorkerMessageBase * operator()(InitReq & req) const {return &req;}
    WorkerMessageBase * operator()(LoginReq & req) const {return &req;}
    WorkerMessageBase * operator()(CloseReq & req) const {return &req;}
};

void handler(Extractor & extractor, message_t *ptr)
{
    WorkerMessageBase   *msg_p;

    msg_p = boost::apply_visitor(extractor, ptr->msg);

    cout << "Handler received msg type: " << msg_p->getMessageType() << endl;
}

int main()
{
    InitReq         init_req;
    LoginReq        login_req;
    CloseReq        close_req;
    message_t       m;
    Extractor       extractor;

    m.msg = init_req;
    handler(extractor, &m);

    m.msg = login_req;
    handler(extractor, &m);

    m.msg = close_req;
    handler(extractor, &m);

    return 0;
}