Monday, July 14, 2014

Runtime value to Compile time value/action conversion via variadic selection tree

With c++11 some of the older macro or table based generator techniques can be tossed out. One of these is the runtime to compile time translation of a value.

For example lets say you have a table of of idents and related actions. 2 possible solution are
* Populate an array with function pointers.
* Generate a switch statement with marcos..

But c++11 has opened a new and what seems to flexible possibility: The ability to use a variaditic template to generated a reduction tree. This seems to have some very interesting possibilities.
* The redux tree can have its action templated... (But I seemed to have a compiler bug that stops it working)
* Its not locked into a single function signature a "Param..." argument pack gives it the flexibility to adapt on both entry and exit of the selection tree.
* good use of inlining lets the tree flatten out and the compiler gets to hit it with opt routines like the macro generated select version.


#include <iostream>
#include <cstring>

// -----------------------------------------------
//                         IDs
// -----------------------------------------------

enum {
    UNKNOWN = 0,
    MIN_TAG = UNKNOWN,
    INT,
    FLOAT,
    MAX_TAG
};

// -----------------------------------------------
//            ID -> Type translation trait
// -----------------------------------------------

template <int Tag> struct Trait {};

template <> struct Trait<UNKNOWN>
{
    typedef void Type;
    static const char* id() { return "unknown";   }
};

template <> struct Trait<INT>
{
    typedef int Type;
    static const char* id() { return "int";   }
};

template <> struct Trait<FLOAT>
{
    typedef float Type;
    static const char* id() { return "float"; }
};

// -----------------------------------------------
//                    Execution point
// -----------------------------------------------

template <int I>
void function(char* data)
{
    typename Trait<I>::Type value =
        (*static_cast<typename Trait<I>::Type*>(
            static_cast<void*>(data)));

    std::cout
        << " type:"  << Trait<I>::id()
        << " value:" << value
        << "\n";
}

template <>
void function<UNKNOWN>(char* data)
{
    std::cout
        << " unknown type number given!"
        << "\n";
}

template <>
void function<MAX_TAG>(char* data) { function<UNKNOWN>(data); }

struct DoAction
{
    template <int I, typename... Params>
    static void call(Params... params)
    {
        function<I>(params...);
    }
};

// -----------------------------------------------
//  SelectTree: runtime -> complie time selector
// -----------------------------------------------

template <typename Action, int min, int max>
struct SelectTree
{
    enum { mid = (max+min)/2 };

    template <typename... Params>
    static void call(int i, Params... params)
    {
        if (i <= mid) SelectTree<Action,min  ,mid>::call(i, params...);
        else          SelectTree<Action,mid+1,max>::call(i, params...);
    }
};

template <typename Action, int value>
struct SelectTree<Action, value, value>
{
    template <typename... Params>
    static void call(int i, Params... params)
    {
        //Action::call<value>(params...);    // compiler bug!
        DoAction::call<value>(params...);
    }
};

// -----------------------------------------------
//                        MAIN
// -----------------------------------------------

int main()
{
    float x = 1.0;

    char data[4];
    std::memcpy(data, &x, sizeof(x));

    int sel = 3;
    std::cin >> sel;

    SelectTree<DoAction,MIN_TAG,MAX_TAG>::call(sel, data);
}


the output looks like
$ a.exe
1
 type:int value:1065353216
$ a.exe
2
 type:float value:1
$ a.exe
-2
 unknown type number given!
$ a.exe
0
 unknown type number given!
$ a.exe
123213
 unknown type number given!

Saturday, July 5, 2014

Async usage of futures and promises in ASIO

One of the new c++11 additions with great potential is futures and promises. However im a heavy asio based async programmer. Most exiting examples on the web deal directly with std::thread and handle the std::promise via std::move. But the asio design basically means you need to use the binding approach to coding. Unfortunately std::bind is great until u need to use a un-copyable move only class like std::promise.

Now you can do something crazy like rewrite the bind so that it can handle movable items, as i did in my post movable-stdbind-with-placeholders. Which is all well and good in theroy BUT there is something to be said about keeping to the standard and well used libs(like boost). Why? Well compiler developers and lib devs like the boost guys are working very hard to improve there stuff. So if you keep to the standard tools and libs you get all the bonuses from their hard work for free when u upgrade. Compiler designers research, profile and add better optimizations and well used libs get more and more eyes on, who in turn find and contribute better code.

And second to all that there is a really trivial and obvious solution to the problem: std::shared_ptr...

So here is how you use std::promise and std::future in lambdas, binds, asio and anything else u cant move into.. I also tossed in an example of how to use non-blocking checks on the futures which is another key tool for using futures in asio code.

#include <iostream>
#include <chrono>
#include <thread>
#include <future>
#include <boost/asio.hpp>

void asyncRun()
{
    std::cout << "Async..." << std::flush;

    boost::asio::io_service io_service;
    std::shared_ptr< std::promise<int> > promise(new std::promise<int>());
    std::future<int> future = promise->get_future();

    io_service.post(
                    [promise]()
                    {
                        std::chrono::milliseconds dura( 2000 );
                        std::this_thread::sleep_for( dura );
                        promise->set_value(9);
                    }
                    );

    std::thread t1( [&io_service]{ io_service.run(); });
    t1.detach();

    std::cout << "Waiting..." << std::flush;
    future.wait();
    std::cout << "Done!\nResults are: "
              << future.get() << '\n';

}


void nonBlockingRun()
{
    std::cout << "Non Blocking..." << std::flush;

    std::promise<int> promise;
    std::future<int> future = promise.get_future();
    std::thread t1( [](std::promise<int> p)
                    {
                        std::chrono::milliseconds dura( 2000 );
                        std::this_thread::sleep_for( dura );
                        p.set_value(9);
                    },
                    std::move(promise) );
    t1.detach();

    std::cout << "Waiting...\n" << std::flush;
    std::future_status status;
    do {
        status = future.wait_for(std::chrono::seconds(0));

        if (status == std::future_status::deferred) {
            std::cout << "+";
        } else if (status == std::future_status::timeout) {
            std::cout << ".";
        }
    } while (status != std::future_status::ready);
    std::cout << "Done!\nResults are: "
              << future.get() << '\n';
}

void blockingRun()
{
    std::cout << "Blocking..." << std::flush;

    std::promise<int> promise;
    std::future<int> future = promise.get_future();
    std::thread t1( [](std::promise<int> p)
                    {
                        std::chrono::milliseconds dura( 2000 );
                        std::this_thread::sleep_for( dura );
                        p.set_value(9);
                    },
                    std::move(promise) );
    t1.detach();

    std::cout << "Waiting..." << std::flush;
    future.wait();
    std::cout << "Done!\nResults are: "
              << future.get() << '\n';
}

int main()
{
    nonBlockingRun();
    blockingRun();
    asyncRun();
}