2018年12月27日 星期四

Concurrency and asynchronous operations with C++/WinRT

簡單紀錄一下Concurrency and asynchronous operations with C++/WinRT

The Windows::Foundation Windows Runtime namespace contains four types of asynchronous operation object.
- IAsyncAction,
- IAsyncActionWithProgress,
- IAsyncOperation, and
- IAsyncOperationWithProgress.

在使用asynchronous Windows function時有2種方式
- blocking
- non-blocking
blocking適合用在console program或是background thread,不適合用在UI thread.


*********************************
coroutine介紹
*********************************
C++/WinRT 整合了 C++ coroutines into the programming model to provide a natural way to cooperatively wait for a result.
只要在function前宣告成上述提到的4種asynchronous operation object,即為coroutines。如下ProcessFeedAsync

IAsyncAction ProcessFeedAsync()
{
    Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
    SyndicationClient syndicationClient;
    SyndicationFeed syndicationFeed{ co_await syndicationClient.RetrieveFeedAsync(rssFeedUri) };
    print_function();
}

下例即為如何呼叫此coroutine:
int main
{
    auto processOp{ ProcessFeedAsync() };
    processOp.get();
}

MS對coroutine的解釋:
A coroutine is a function that can be suspended and resumed. In the ProcessFeedAsync coroutine above, when the co_await statement is reached, the coroutine asynchronously initiates the RetrieveFeedAsync call and then it immediately suspends itself and returns control back to the caller (which is main in the example above). main can then continue to do work while the feed is being retrieved and printed. When that's done (when the RetrieveFeedAsync call completes), the ProcessFeedAsync coroutine resumes at the next statement.


*********************************
coroutine回傳值
*********************************
coroutine可以回傳Windows Runtime type,如上。也可以回傳非Windows Runtime type,如concurrency::task. 範例如下
concurrency::task RetrieveFirstTitleAsync()
{
    return concurrency::create_task([]
    {
        Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
        SyndicationClient syndicationClient;
        SyndicationFeed syndicationFeed{ syndicationClient.RetrieveFeedAsync(rssFeedUri).get() };
        return std::wstring{ syndicationFeed.Items().GetAt(0).Title().Text() };
    });
}

int main()
{
    winrt::init_apartment();

    auto firstTitleOp{ RetrieveFirstTitleAsync() };
    // Do other work here.
    std::wcout << firstTitleOp.get() << std::endl;
}


*********************************
coroutine參數
*********************************
如果需要在coroutine中傳遞參數,要用const,以確保thread safe.


*********************************
coroutine的thread
*********************************
coroutine在碰到co_await, co_return, or co_yield時會rutern。
但如果在coroutine裡面沒有機會使用到這幾個時,可以直接使用
co_await winrt::resume_background();
這樣可以讓自己被丟到system thread pool,返回caller的thread,然後讓system啟動一個thread來完成自己的coroutine.

然而使用co_await winrt::resume_foreground(UI_thread)可以讓自己的thread回到UI thread,這個方式可以用來update UI.

值得注意的是在suspension點之後,原來的thread可能會消失不見,resume之後可能會是另一條thread來執行。但是如果我們使用的是Windows Runtime type (IAsyncXXX)的話,C++/WinRT會自動幫我們處理。C++/WinRT會在suspension之前先紀錄calling context,等到resume時會檢查並確保是在calling context. 如果不是使用(IAsyncXXX)的話,請記得確認此library有提供這個技術。


*********************************
Canceling an asychronous operation, and cancellation callbacks
*********************************
使用 IAsyncXXX.Cancel()來取消一個async operation.
或用 IAsyncXXX.callback()來註冊取消一個async operation之後要執行的function.

*********************************
Reporting progress
*********************************
使用 IAsyncActionWithProgress或IAsyncOperationWithProgress來回報進度。

*********************************
Fire and forget
*********************************
宣告coroutine為winrt::fire_and_forget,即為不等待結束。

The visual studio behavior with WinRT runtime component

When "windows runtime component" project created with winrt type.
1. VS default create Class.idl, Class.h, Class.cpp under root of project folder.
2. when project built, VS will generate some files in "Generated Files" folder.
    - Class.g.h
    - module.g.cpp
    - folder "winrt"
        - $project_name.h          // define template for Class
        - folder "impl"
            - $project_name.0.h    // define template for $project_name.1.h
            - $project_name.1.h    // define IClass for $project_name.2.h
            - $project_name.2.h    // define Class for $project_name.h
        - folder "source"
            - Class.h              // this file content is same as default created Class.h
            - Class.cpp            // this file content is same as default created Class.cpp

3. When change members in Class.idl and rebuild project.
3.1. files under root project folder.
    - Class.h                      // not re-generated.
    - Class.cpp                    // not re-generated.
3.2. files under "Generated Files" folder.
    - Class.g.h                    // re-generated, not content is not affected.
    - module.g.cpp                 // re-generated, not content is not affected.
    - files under "Generated Files/winrt" folder.
        - $project_name.h          // re-generated, add members.
        - files under "Generated Files/winrt/impl" folder.
            - $project_name.0.h    // re-generated, add members.
            - $project_name.1.h    // re-generated, not content is not affected.
            - $project_name.2.h    // re-generated, not content is not affected.
        - files under "Generated Files/winrt/source" folder.
            - Class.h              // re-generated, add members.
            - Class.cpp            // re-generated, add members.

4. When rename class name in Class.idl
4.1. files under root project folder.
    - Class.h                      // not re-generated.
    - Class.cpp                    // not re-generated.
4.2. files under "Generated Files" folder.
    - Class.g.h                    // not re-generated. just because new class file generated.
    - NewClass.g.h                 // new class file generated.
    - module.g.cpp                 // re-generated, content changed.
    - files under "Generated Files/winrt" folder.
        - $project_name.h          // re-generated, content changed to new class related.
        - files under "Generated Files/winrt/impl" folder.
            - $project_name.0.h    // re-generated, content changed to new class related.
            - $project_name.1.h    // re-generated, content changed to new class related.
            - $project_name.2.h    // re-generated, content changed to new class related.
        - files under "Generated Files/winrt/source" folder.
            - Class.h              // not re-generated. just because new class file generated.
            - Class.cpp            // not re-generated. just because new class file generated.
            - NewClass.h           // new class file generated.
            - NewClass.cpp         // new class file generated.

           
           
           
           
           
           
           
           
           
           
           
           
           
           
           
           
           
           
           

2018年10月11日 星期四

amazon echo's skills

最近在研究如何開發amazon echo的程式,也就是如何讓擁有amazon echo裝置的人可以有更多話語跟echo裝置互動。

在amazon echo的世界裡,有一個虛擬的助手叫alexa,alexa擁有依些基本對話功能,基本對話能力是amazon開發時就已經內建在echo裏面了,但是amazon不希望echo只能做這些事,所以開放一些SDK,讓全世界有興趣的工程師一起來擴張amazon的能力。這個能力在amazon的世界裏面稱做skill。

可以對比成:android的世界裏面,開發者可以開發許多app,在amazon的世界裏面,這些app稱做skill。

不廢話進重點。

當一個開發者想要開發skill時,要先知道skill怎樣分類,amazon將skill分成四大類。
1. Custom skill
2. Smart Home Skill API
3. Video Skill API
4. Flash Briefing Skill API
接下來分別簡單說說這四大類。

Custom skill
這一類就是讓開發者完全自己定義要如何跟使用者互動,如:到某個網站查詢資料,開發互動式遊戲等等。

Smart Home Skill API
這一類可以讓使用者控制IoT裝置,如Smart TV,電燈,門鎖等等。

Video Skill API
這一類skill者要是讓使用者控制雲端的視頻服務,如播放影片,暫停播放,播歌等等。

Flash Briefing Skill API
最後一類是播放簡報,這裡的簡報意指使用者事前已經設定好的資料,如報紙的頭條新聞,讓alexa播報出來。

參考資料:https://developer.amazon.com/docs/ask-overviews/build-skills-with-the-alexa-skills-kit.html