280 likes | 673 Views
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
E N D
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 • Minimize concept count
Good, Better, Best • Some lessons learned from writing Windows Store apps with C++/CX
Correctness • Some lessons learned from writing Windows Store apps with C++/CX
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
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
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;}
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;
Performance • Some lessons learned from writing Windows Store apps with C++/CX
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
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
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
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());
Clear BoundaryC++/CX and standard C++ code • Some lessons learned from writing Windows Store apps with C++/CX
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
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
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
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] = ...; }
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
Buffers (demo) • To avoid an extra copy when reading data from streams, use IBuffer rather than DataReader • Memory
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
Got Feedback? No time at BUILD?
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
Clear BoundaryCode constructs • Ref class everywhere • Class vs. ref class • Type embedding
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;