1 / 28

Deep Dive into C++/CX and WinRT

Deep Dive into C++/CX and WinRT. Marian Luparu Senior Program Manager 3-010. Agenda. C++/CX guiding principles C++/CX good practices Correctness Performance Tips & Tricks. C++/CX. High-fidelity support for WinRT constructs and semantics Align to familiar C++ constructs

sauda
Download Presentation

Deep Dive into C++/CX and WinRT

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Deep Dive into C++/CX and WinRT Marian Luparu Senior Program Manager 3-010

  2. Agenda • C++/CX guiding principles • C++/CX good practices • Correctness • Performance • Tips & Tricks

  3. C++/CX • High-fidelity support for WinRT constructs and semantics • Align to familiar C++ constructs • Minimize concept count

  4. Good, Better, Best • Some lessons learned from writing Windows Store apps with C++/CX

  5. Correctness • Some lessons learned from writing Windows Store apps with C++/CX

  6. Exceptions • WinRT C++ Exceptions (Platform::Exception) • The only way to communicate failure over an ABI boundary • throw ref new OutOfBoundsException(“angle is outside range”); • C++ Exceptions • Will terminate the process when reaching an ABI boundary • SEH Exceptions • When bad things happen to your app • Exception types

  7. Exceptions • When catching COMException • Handle only HRESULTs that you expect, re-throw everything else • catch (COMException^ e) { • switch(e->HResult) { … default: throw; } • } • When throwing an exception from an HRESULT • using namespace Platform; • if (FAILED(hr)) { • throw Exception::CreateException(hr); • } • Catch the most specific exception • Throw the most specific exception

  8. Async& Exceptions • task<Content> ReadContent(String^ filename) • { • anim->Start(); • autot = create_task(KnownFolders::DocumentsLibrary-> • GetFileAsync(filename)) • .then( • [](StorageFile^ file) { • returnfile->OpenAsync(FileAccessMode::Read); • }) • .then( • [](IRandomAccessStream^ stream) { • autoinputStream = stream->GetInputStreamAt(0); • autodr = refnewDataReader(inputStream); • returndr->LoadAsync(stream->Size); • }) • .then( • [anim](unsignedintcount) { • anim->End(); • // read content • return content; • }); • returnt;}

  9. Async& Exceptions [anim](unsignedintcount) { anim->End(); // read content }); [anim](task<unsignedint> lt) { anim->End(); // read content }); [anim](task<unsignedint> lt) { anim->End(); try { unsignedint count = lt.get(); // read content } catch(AccessDeniedException^ ex) { throw; } }); • anim->Start(); • auto t = create_task(KnownFolders::DocumentsLibrary-> • GetFileAsync("Log.txt")) • .then( • [](StorageFile^ file) { • returnfile->OpenAsync(FileAccessMode::Read); • }) • .then( • [](IRandomAccessStream^ stream) { • autoinputStream = stream->GetInputStreamAt(0); • autodr = refnewDataReader(inputStream); • returndr->LoadAsync(stream->Size); • }) • .then( • [anim](unsignedintcount) { • anim->End(); • // read content • }); • return t;

  10. Performance • Some lessons learned from writing Windows Store apps with C++/CX

  11. Async & Threading void MainPage::OnNavigatedTo(NavigationEventArgs^ e) { create_task(KnownFolders::DocumentsLibrary-> GetFileAsync(“Surface.ini")) .then( [](StorageFile^ file) { returnfile->OpenAsync(FileAccessMode::Read); }) .then( [](IRandomAccessStream^ stream) { autoinputStream = stream->GetInputStreamAt(0); autodr = refnewDataReader(inputStream); returndr->LoadAsync(stream->Size); }) .then( [](unsignedintcount) { // read content txtContent->Text = content; }); } UI Thread Op T Background Thread Background Thread Background Thread Op T Op STA Thread T STA Thread

  12. Async & Threading void MainPage::OnNavigatedTo(NavigationEventArgs^ e) { create_task(KnownFolders::DocumentsLibrary-> GetFileAsync(“Surface.ini")) .then( [](StorageFile^ file) { returnfile->OpenAsync(FileAccessMode::Read); }) .then( [](IRandomAccessStream^ stream) { autoinputStream = stream->GetInputStreamAt(0); autodr = refnewDataReader(inputStream); returndr->LoadAsync(stream->Size); }) .then( [](unsignedintcount) { // read content txtContent->Text = content; }); } UI Thread Op T Background Thread Background Thread Background Thread Op T Op STA Thread T STA Thread

  13. Async & Threading void MainPage::OnNavigatedTo(NavigationEventArgs^ e) { create_task(KnownFolders::DocumentsLibrary-> GetFileAsync(“Surface.ini")) .then( [](StorageFile^ file) { returnfile->OpenAsync(FileAccessMode::Read); }) .then( [](IRandomAccessStream^ stream) { autoinputStream = stream->GetInputStreamAt(0); autodr = refnewDataReader(inputStream); returndr->LoadAsync(stream->Size); }) .then( [](unsignedintcount) { // read content txtContent->Text = content; }); } void MainPage::OnNavigatedTo(NavigationEventArgs^ e) { create_task(KnownFolders::DocumentsLibrary-> GetFileAsync(“Surface.ini")) .then( [](StorageFile^ file) { returnfile->OpenAsync(FileAccessMode::Read); }, task_continuation_context::use_arbitrary()) .then( [](IRandomAccessStream^ stream) { autoinputStream = stream->GetInputStreamAt(0); autodr = refnewDataReader(inputStream); returndr->LoadAsync(stream->Size); }, task_continuation_context::use_arbitrary()) .then( [](unsignedintcount) { // read content txtContent->Text = content; }, task_continuation_context::use_current()); } UI Thread Op T Background Thread Background Thread Background Thread Op T Op STA Thread T STA Thread

  14. Async & Threading (Back to the UI thread) • 2 Options: PPL contexts Dispatcher // ... .then([content](unsignedintcount) { // read content }, task_continuation_context::use_arbitrary()) .then([content]() { txtContent->Text = *content; }, task_continuation_context::use_current()); // ... .then( [](unsignedintcount) { // read content CoreApplication::MainView-> CoreWindow->Dispatcher->RunAsync( CoreDispatcherPriority::Normal, refnewDispatchedHandler( [content]() { txtContent->Text = content; }) ); }, task_continuation_context::use_arbitrary());

  15. Clear BoundaryC++/CX and standard C++ code • Some lessons learned from writing Windows Store apps with C++/CX

  16. Clear boundary – Why is it important? • “It would be a mistake, and we are absolutely not telling you, to go rush out and say, 'every class I ever wrote should now be a ref class or a value class and I shouldn't use those old standard things any more” • Herb Sutter • //BUILD/ 2011 • Performance • Portability • Coding style

  17. Clear BoundaryData conversions • Good: Reduce chattiness at WinRTboundary • Better: Minimize conversions between WinRT and C++ types • String^ or std::wstring? • Vector<T>^ or std::vector<T>? • Keep data in its originating type for as long as possible • Best: Profile your app performance • Understand bottlenecks created by conversions • Optimize accordingly

  18. Memory • This code creates a copy of your buffer • char16* buffer; // ... • xmlDoc->LoadXml(ref new String(buffer)); • This one doesn’t • StringReferencesr(buffer); • xmlDoc->LoadXml(sr); • What’s the catch? • You need to guarantee that lifetime of the buffer exceeds the duration of the call and its content remains unchanged • Strings

  19. Memory //User code StringReferencesr(buffer); WinRTCall(sr); • The catch: reentrancy //WinRT code HRESULT WinRTCall(HSTRING s) { Fire_OnWinRTCall(this, s); ... } // User code (callback) void myApp_OnWinRTCall(...) { buffer[n] = ...; }

  20. Memory • Same story as strings. Here’s how to avoid a copy: • auto buffer = ref new Array<uint8>(count); • memcpy(buffer->Data, bytes, count); • writer->WriteBytes(buffer); • Arrays ArrayReference<uint8> buffer(bytes, count); Same catch You need to guarantee that lifetime of the buffer exceeds the duration of the call and the its content remains unchanged

  21. Buffers (demo) • To avoid an extra copy when reading data from streams, use IBuffer rather than DataReader • Memory

  22. Related Sessions • 11/2 12:45 – B33 McKinley Herb Sutter: The Future of C++ • 11/1 8:30 – B33 Baker – Max McMullen: Performance tips for Windows Store apps using DirectX and C++ • 11/1 12:00 – B33 Kodiak –Alan Ludwig: Building mixed-language apps • 11/1 16:15 – B92 Magellan – (or)11/2 8:30 – B33 McKinley – Peter Torr: WP8 Using C++ in your application

  23. Got Feedback? No time at BUILD?

  24. Backup Slides

  25. Clear boundary (How) • File compilation mode • Avoids type collisions between your types and WinRT types • Turn off /ZW per compile unit • Data conversions • Code constructs • “It would be a mistake, and we are absolutely not telling you, to go rush out and say, 'every class I ever wrote should now be a ref class or a value class and I shouldn't use those old standard things any more” • Herb Sutter • //BUILD/ 2011 Not a problem in practice

  26. Clear BoundaryCode constructs • Ref class everywhere • Class vs. ref class • Type embedding

  27. Clear BoundaryCode constructs Platform-specific (C++/CX) Standard C++ • using namespace Windows::Devices::Sensors; • class light_sensor { • public: • float illuminance(); • boolis_available(); • private: • LightSensor^ _sensor; • }; #include “lightsensor.h” auto s = make_shared<light_sensor>(); float illum = s->is_available() ? s->illuminance() : .0f;

More Related