240 likes | 446 Vues
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
E N D
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: staticstd::unique_ptr<Singleton> s_instance; staticstd::once_flags_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(); }); automyTask = 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 non-blocking 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; usingnamespace Windows::System::Threading; // Non-blocking call with normal priority. Dispatcher->RunAsync(CoreDispatcherPriority::Normal, refnewDispatchedHandler([]{ /*...*/})); // 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. • eventkeyword. • WinRT EventRegistrationToken class: • Used to register the delegates for corresponding events.
Using delegates for callbacks • A very simple class that reacts to events publicdelegatevoidMyEventHandler(); publicrefclassMyEventsManagersealed { public: staticeventMyEventHandler^ OnMyEvent; staticvoidFireMyEvent() { OnMyEvent(); } };
Using delegates for callbacks • Use EventRegistrationToken // Class declaration classMyClass { // ... private: Windows::Foundation::EventRegistrationToken token; } // Class implementation token = MyEventsManager::OnMyEvent += refnewMyEventHandler([]{ /* ... */ }); • 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-Windows-Store-app-Beginners-tutorial • Marc Grégoire Blog • http://www.nuonsoft.com/blog/