Effective WinRT with C++ Tips and tricks for developing WinRT applications in C++ Effective WinRT with C++ • How WinRT works with C++ • Thread safety ▫ Thread-safe singletons ▫ Using lambdas for callbacks Using the PPL Exception handling • General hints with WinRT ▫ Error handling for permissions ▫ Using delegates for callbacks How WinRT works with C++ • C++ implementation choices: ▫ XAML based. ▫ DirectX (Direct2D and/or Direct3D) based. ▫ A subset of win32 API is available. • Windows Store apps are sandboxed, so there are some limitations. ▫ Disk and hardware access is restricted. ▫ Fully multithreaded design. Using C++ to implement WinRT classes • public interface: ▫ WinRT types and conventions only. • private (or internal) interface: ▫ Standard C++ containers, classes and conventions can be used. • Enumerated types: ▫ Strongly typed enums (enum class) are accepted. Using new standard language features • WinRT containers can be constructed from standard library containers. • Range-based for loops work with WinRT classes (include collection.h). • Move semantics is available. • Lambdas are accepted as delegates/function pointers. • Thread safety is very important. Thread safety in modern C++ • Example of a thread-safe singleton class Singleton { public: virtual ~Singleton(); static Singleton& Get(); private: static std::unique_ptr<Singleton> s_instance; static std::once_flag s_creationFlag; Singleton(); Singleton(const Singleton& other) /* = delete */; Singleton& operator=(const Singleton& other) /* = delete */; } Thread safety in modern C++ • Example of a thread-safe singleton std::unique_ptr<Singleton> Singletion::s_instance = nullptr; std::once_flag Singleton::s_creationFlag; Singleton& Singleton::Get() { std::call_once(s_creationFlag, []{ s_instance.reset(new Singleton); }); return *s_instance.get(); } Multithreading in WinRT • Every command* runs in its own thread. • Avoid the callback spaghetti: ▫ Parallel Patterns Library ▫ Use delegates for event handling * That potentially lasts longer than 50 ms Parallel Patterns Library The Parallel Patterns Library (PPL) provides an imperative programming model that promotes scalability and ease-of-use for developing concurrent applications. - MSDN (http://msdn.microsoft.com/en-us/library/dd492418.aspx) Parallel Patterns Library • Task objects, analogous to std::future objects. using namespace concurrency; task<void> myTask([]{ do_something(); }); auto myTask = concurrency::create_task([]{ do_something(); }); // Non-blocking or blocking call to retrieve the result myTask.get(); // Blocking call, retrieves the status myTask.wait(); • Allows an imperative style when launching nonblocking tasks myTask.then([]{ do_what_comes_next(); }); Asynchronous calls made easy concurrency::task<void> Singleton::ComplexTask() { /* ... */ } // Define a sequence of tasks Singleton::Get().ComplexTask() .then([] { // ... }) .then([] { // ... }); WinRT CoreDispatcher class • Every XAML page can access the CoreDispatcher object through the Dispatcher member • Issue tasks in the main thread, from any thread. using namespace Windows::Core::UI; using namespace Windows::System::Threading; // Non-blocking call with normal priority. Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([]{ /*...*/ })); // Check whether the current thread can be accessed Dispatcher->HasThreadAccess(); Capturing objects in task chains concurrency::task<void> MyClass::ExecuteTask() { // ... return concurrency::create_task( [this, local_variable] // <-- avoid locals by reference! { m_cached_value = local_variable; }) .then([this] { }); // and so on... }; Exception handling concurrency::create_task([] { }) // A few tasks “later”... .then([this](concurrency::task<void> t) { try { t.get(); } catch(Platform::Exception^ except) { // Handle except } }); Special cases in error handling • Handle connection to devices ▫ Windows handles first access for you. Geolocation, camera, phone functionality, etc. • When using webcam or microphone ▫ Permission errors are handled by checking: E_ACCESSDENIED HRESULT_FROM_WIN32(ERROR_FILE_HANDLE_REVOKED) • When sending SMS (Windows Phone 8) ▫ Permission errors handled by checking: E_ACCESSDENIED Special cases in error handling • Examples of error handling for webcam capture ▫ Initialization error: // (continued task chain including call to InitializeAsync) .then([this](task<void> t) { try { t.get(); } catch(Exception^ e) { if(e->HResult == E_ACCESSDENIED) // Handle permissions error else // Check if camera is not connected } } ▫ Spontaneous error: void CameraCallback(MediaCapture^ currentCaptureObject, MediaCaptureFailedEventArgs^ currentFailure) { if(currentFailure->Code == HRESULT_FROM_WIN32(ERROR_FILE_HANDLE_REVOKED)) // Handle revoked permissions else // Check if camera was suddenly disconnected } Special cases in error handling Short Demonstration Granting permissions • File system access may be needed for logging ▫ Add the targeted folder read/write access to ALL APPLICATION PACKAGES Using delegates for callbacks • In WinRT applications, callbacks can be registered through a generic mechanism. • Non-standard language extensions: ▫ delegate keyword. ▫ event keyword. • WinRT EventRegistrationToken class: ▫ Used to register the delegates for corresponding events. Using delegates for callbacks • A very simple class that reacts to events public delegate void MyEventHandler(); public ref class MyEventsManager sealed { public: static event MyEventHandler^ OnMyEvent; static void FireMyEvent() { OnMyEvent(); } }; Using delegates for callbacks • Use EventRegistrationToken // Class declaration class MyClass { // ... private: Windows::Foundation::EventRegistrationToken token; } // Class implementation token = MyEventsManager::OnMyEvent += ref new MyEventHandler([]{ /* ... */ }); • Finally, trigger the event when needed by calling MyEventsManager::FireMyEvent(); Using delegates for callbacks Short Demonstration References and useful sources • ISO Standard C++ official page ▫ http://www.isocpp.org/ • MSDN (Microsoft Developer Network) ▫ http://msdn.microsoft.com/library/windows/apps/ • CodeProject ▫ http://www.codeproject.com/Articles/472009/Creating-WindowsStore-app-Beginners-tutorial • Marc Grégoire Blog ▫ http://www.nuonsoft.com/blog/ Thank you