GPII Framework Asynchrony

From wiki.gpii
Jump to: navigation, search

Framework-Level Support for Asynchrony

The GPII real-time framework is implemented as an asynchronous architecture. This approach is supported by the JavaScript language and Node.js system used by the GPII, and it is intended to help make the system more scalable by reducing the amount of time spent waiting on contentious tasks such as I/O (e.g. reading or writing from disk or a network connection). Asynchronous, event-driven programming "offers a more efficient, scalable alternative that provides developers much more control... it prevents the application from getting blocked while waiting" (Tilkov and Vinoski 80-1). In particular, this approach makes significantly more efficient use of a single programming thread, which in turn reduces the need to resort to complex multithreaded programming idioms. Multithreading is difficult, error-prone, and more complex for programmers to reason about (Lee 33).

Despite the benefits of asynchronous, event-based programming, it can still be complex. GPII’s innovative declarative programming approach using JSON is intended to reduce or completely avoid assumptions about synchrony and sequencing within program logic, simplifying the process of working in an asynchronous environment (Clark et al 375). For example, an integrator who is configuring GPII to work with their assistive technology will typically never need to be concerned with the complexities of callbacks and asynchrony.

Nonetheless, lower-level supports are still required to assist GPII developers with common asynchronous programming tasks. To this end, a recent release of the real-time framework introduced ubiquitous support for Promises, a technique that allows developers to more easily interact with asynchronous APIs. Barbara Liskov, who coined the term, describes a Promise as “a placeholder for a value that will exist in the future. It is created at the time a call is made. The call computes the value of the promise, running in parallel with the program that made the call” (260). This technique helps developers write code that is less dependent on specifically when a value is resolved. Client code works the same way regardless of whether a value is available now or later, simplifying one of the common sources of code complexity when working with asynchronous APIs.

In particular, Promises are now used by all Settings Handlers to abstract away the variability between underlying APIs in regards to whether they are synchronous or asynchronous. Promises are also used for framework-level data access such as when making remote HTTP requests or accessing the filesystem.


Asynchronous Settings Handlers

Settings Handlers are components that implement a particular strategy for getting and setting preferences using a form of persistent storage. For example, Settings Handlers have been built for a variety of common cross-platform interchange formats such as XML, JSON, and INI files, as well as platform-specific registries and databases such as the Windows Registry and System Parameters Info APIs, GNOME’s GSettings API, and Android’s System Settings API.

In previous versions of the GPII real-time framework, Settings Handlers were synchronous. This approach had two notable consequences:

  1. A Settings Handler blocked any further progress of the system until it completed
  2. The GPII system assumed, when a call to a Settings Handler method such as get() or set() returned, that the underlying setting had actually been set. For example, if a Settings Handler was asked to set the operating system’s font size to a larger value, the system assumed that the font size had actually been changed correctly at the moment of return.

In many cases (and on some platforms) these assumptions were appropriate and inconsequential. For example, on Linux, the GSettings API is fully synchronous; it will only return from an API call when a setting has fully been applied.

However, after implementing a large number of Settings Handlers (over a dozen Settings Handlers have been written and put into production so far), we discovered that many Windows APIs, such as SystemParametersInfo (SPI) , appear to work synchronously but are in fact asynchronous in nature. For example, SPI makes no guarantee about when a particular setting will actually be applied; in practice, there is an indeterminate delay between the time when an SPI call returns and when Windows actually applies the change. More significantly, subsequent calls to SPI within a short interval will actually cause the system to become corrupted.

In order to address these issues, as well as to make the GPII architecture more consistent overall, we re-architected the Settings Handler API to be fully asynchronous. This was implemented with the new framework-level support for Promises, discussed above.

The end result is that Settings Handlers are substantially more reliable, particularly on Windows. This impacts both functional and non-functional requirements. From the functional perspective, the system now has a clearer model for when changes are actually applied on the system and usable by end-users. Infrastructurally, our acceptance testing system is more stable as result of this change, contributing to greater overall testability and technical verifiability for GPII.

References

Clark, C., Antranig Basman, Simon Bates, and Kasper Markus. “Enabling Architecture: How the GPII Supports Inclusive Software Development.” Universal Access in Human-Computer Interaction. Design for All and Accessibility Practice (2014): 368-377.

Lee, Edward A. "The problem with threads." Computer 39.5 (2006): 33-42.

Liskov, Barbara and Liuba Shrira. “Promises: Linguistic Support for Efficient Asynchronous Procedure Calls in Distributed Systems.” Proceedings of the SIGPLAN ‘88 Conference on Programming Language Design and Implementation (1998): 260-267.

Tilkov, Stefan, and Steve Vinoski. "Node. js: Using JavaScript to build high-performance network programs." IEEE Internet Computing 14.6 (2010): 80-83.


Colin Clark, December 2014