Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

EvgenyLPanasyuk

EvgenyLPanasyuk Evgeny​LPanasyuk

Niner since 2012

  • Bringing await to C++

    Full emulation of await feature from C# language in C++ based on Stackful Coroutines from Boost.Coroutine library: https://github.com/panaseleus/await_emu

    int bar(int i)
    {
    auto result = await boost::async([i]{ return reschedule(), i*100; });
    // await "transforms" rest of code into continuation and attaches it to boost::future::then
    // (any other mechanism similar to .then can be used)
    return result + i*10;
    }

    This proof-of-concept shows that exact syntax of await feature can be emulated with help of Stackful Coroutines, demonstrating that it is superior mechanism.

  • The Future of C++

    @Wasi:

    1. Regarding your first example "executed in thread 1:":    asynchronous file operations does not have to be executed in new threads, refer "overlapped I/O".

    2. Regarding your second example "executed in a <worker> thread":    it opens files sequentially, doubling latency.

    3. Imagine that you need to write tcp proxy server, that should handle many connections (let say 10k) simultaneously. How logic loop which reads data from one socket and sends it to another would look in your code?
    Using some approach based on coroutine-like stuff (async+await, etc) - code would look very clear, structurally similar to simple synchronous versions.

     

  • The Future of C++

    C#'s await/async is compiler feature which rewrites method into special class-finite_state_machine. All method's local variables are automatically moved into fields of that class, and code of method is moved into special class method which depending on current state just jumps by switch into right await position (http://www.codeproject.com/Articles/535635/Async-Await-and-the-Generated-StateMachine ) . That is similar in something to stackless coroutines.

    In C++ stackless coroutines can be implemented just within 100 code lines, for example look to Boost.Asio. Of course syntax sugar is less sweet - local variables must be moved into class field by hands, but everything else is similar in shape and content. For instance state machine is generated automatically (with similar switch inside), by macros. (See talk by Christopher M. Kohlhoff http://blip.tv/boostcon/why-c-0x-is-the-awesomest-language-for-network-programming-5368225 , code example - https://github.com/chriskohlhoff/awesome/blob/master/server.cpp ).

    Boost.Coroutine library provides stackful coroutines for C++ on wide range of platforms.
    Stackful coroutines are much more powerfull than stackless ones:

    ___________________
    Major advantage #1:

    Stackful coroutine allows to encapsulate all asynchronous logic inside components - in a such way, that client code would look EXACTLY SAME to SYNCHRONOUS code.
    For example, Python's gevent library does monkey patching of stadard sockets which automaticly turns all code that use them into "asyncronous", without any changes (http://www.gevent.org/intro.html#monkey-patching ).

    Another demo can be found at Boost.Coroutine: it has example of simple server which asynchronously reads data from tcp port and prints it on screen, and all this happens in one thread. Reading loop looks exactly same as "normal" blocking code:

    Result foo(TcpStream &client_stream)
    {
        string msg;
        do
        {
            std::getline(client_stream, msg); // happens asynchronously
            cout << msg << endl;
        } while(msg != "exit");
        // ...
        return result;
    }


    ALL asynchronous logic is hidden inside TcpStream. Inside of it, after calling asynchronous read, coroutine yields, and going to "sleep". When data would be available - coroutine would be awaken by appropriate completion handler.

    It is not possible to achieve same level (the highest, in fact) of encapsulation using stackless coroutine (or await/async) - asynchronous guts will stick out from the client code: foo would have to be "async" and getline will be called as "await":

    async Task<Result> foo(TcpStream client_stream)
    {
        string msg;
        do
        {
            msg = await client_stream.getline();
            Console.WriteLine(msg);
        } while(msg != "exit");
        // ...
        return result;
    }


    Well, that doesn't look like a big deal, but often there is not just one async method, but rather full chain of async methods.
    When your "foo" is called by "bar", which need result, then "bar" in general has two choices: convert itself to async and do await, or do blocking wait on Task's result.
    Moreover, when you have chain of method calls, like this:

    quux
    |
    baz
    |
    bar
    |
    foo

    "async"-choice transitively infects all upper levels (until one of them decides to do blocking wait, or not need the result).

    While in case of stackful coroutines, any asynchronous specific code is only at the ends of chain: at the begin, where coroutine is started, and at the very bottom - at yield place.

    ___________________
    Advantage #2, Performance:

    When you have chained levels of awaits - special code is executed at each of them - one level awaits another, and so on. It is O(N).

    But in case of stackful coroutines, no matter how long chain you have - each level "implicitly" awaits the bottom one, that is O(1). Among other things this is extremely fast: http://www.boost.org/doc/libs/1_54_0/libs/coroutine/doc/html/coroutine/performance.html

    ___________________
    Advantage #3, the Killer:

    Exactly same syntax of await can be emulated with help of Stackful Coroutines.
    I have made small proof-of-concept: https://github.com/panaseleus/await_emu :

    int bar(int i)
    {
        // await is not limited by "one level" as in C#
        auto result = await async([i]{ return reschedule(), i*100; });
        return result + i*10;
    }
    
    int foo(int i)
    {
        cout << i << ":\tbegin" << endl;
        cout << await async([i]{ return reschedule(), i*10; }) << ":\tbody" << endl;
        cout << bar(i) << ":\tend" << endl;
        return i*1000;
    }
    
    void async_user_handler()
    {
        vector<future<int>> fs;
    
        // instead of `async` at function signature, `asynchronous` should be
        // used at the call place:
        for(auto i=0; i!=5; ++i)
            fs.push_back( asynchronous([i]{ return foo(i+1); }) );
    
        for(auto &&f : fs)
            cout << await f << ":\tafter end" << endl;
    }


    await here takes std::future-like object with support of continuation attachment (e.g. .then), and "returns result" of future.
    At this example boost::async is used. But that approach can be extended to work with other futures, like PPL's task::then, etc.
    Output example:

    1:      begin
    2:      begin
    3:      begin
    4:      begin
    5:      begin
    20:     body
    10:     body
    30:     body
    110:    end
    1000:   after end
    50:     body
    220:    end
    2000:   after end
    550:    end
    40:     body
    330:    end
    3000:   after end
    440:    end
    4000:   after end
    5000:   after end

  • C++ and Beyond 2012: Andrei Alexandrescu - Systematic Error Handling in C++

    P.S. I like the alternative approach defined in https://github.com/panaseleus/stack_unwinding even if the code is not completely portable in C++11.

    Yes, it based on top of platform-specific implementation of uncaught_exception_count.

    However, I made it work on all platforms I have access to - MSVC, GCC, Clang ( see full list at github readme ).

    And I think it should be easy to implement it on other platforms, because info about current exceptions in flight should be stored somewhere.

    By the way, at 1:18:10 Andrei mentioned that he would accept GCC only solution.

  • C++ and Beyond 2012: Andrei Alexandrescu - Systematic Error Handling in C++

    I have implemented scope(failure) and scope(success) in C++. https://github.com/panaseleus/stack_unwinding
    I.e. ScopeGuard without need to call .dismiss() manually.

    For example:

    try
    {
        int some_var=1; // some_var is just for example of capturing,
        // but not requirement
        cout << "Case #1: stack unwinding" << endl;
        scope(exit)
        {
            cout << "exit " << some_var << endl;
            ++some_var;
        };
        scope(failure)
        {
            cout << "failure " << some_var  << endl;
            ++some_var;
        };
        scope(success)
        {
            cout << "success " << some_var  << endl;
            ++some_var;
        };
        throw 1;
    } catch(int){}