1# Gio support 2 3Most of the Gio facilities are supported natively through 4gobject-introspection layer. However, lgi provides `Gio.Async` which 5help in using Gio-style asynchronous I/O operations. 6 7## Asynchronous IO support 8 9Native Gio asynchronous operations are based on traditional callback 10scheme, i.e. the operation is started, pushed to be performed on the 11background and when it finishes, it calls registered callback with 12operation results as arguments. While this scheme is widely used for 13asynchronous programming, it leads to spaghetti code full of 14callbacks. Lua provides coroutines, which can be used to make the 15code look 'synchronous' again, but still retaining the advantage of 16non-blocking I/O operations. 17 18Gio-style asynchronous functions come as pair of two methods; 19`name_async` which starts operation and registers callback, and 20`name_finish`, which should be called in the context of registered 21callback and allows retrieveing operation results. When `Gio` 22override is loaded, lgi detects any of these pairs (in any object, not 23just from Gio namespace) and when found, it synthesizes `async_name` 24operations, which wraps native methods and uses Lua coroutines to 25convert callbacks into synchronous code. In order for `async_method` 26to work, these methods have to be called in the context of functions 27called through `Gio.Async` spawning facilities; either 28`Gio.Async.call` for synchronous calls and `Gio.Async.start` for 29starting routine on background. 30 31### Gio.Async class 32 33This helper class implemented by lgi (not originating from 34introspected Gio module) contains interface for using lgi asynchronous 35support. This class contains only static methods and attributes, it 36is not possible to instantiate it. 37 38### Gio.Async.call and Gio.Async.start 39 40 local call_results = Gio.Async.call(user_function[, cancellable[, io_priority])(user_args) 41 local resume_results = Gio.Async.start(user_function[, cancellable[, io_priority])(user_args) 42 43These methods accept user function to be run as argument and return 44function which starts execution of the user function in async-enabled 45context. 46 47Any `async_name` methods called inside context do not accept 48`io_priority` and `cancellable` arguments (as their `name_async` 49original counterparts do), instead global cancellable and io_priority 50values given as arguments to `Gio.Async.call/start` are used. 51 52### Gio.Async.cancellable and Gio.Async.io_priority 53 54Code running inside async-enabled context can query or change value of 55context-default `cancellable` and `io_priority` attributes by getting 56or setting them as attributes of `Gio.Async` class. 57 58If `cancellable` or `io_priority` arguments are not provided to 59`Gio.Async.start` or `Gio.Async.call`, they are automatically 60inherited from currently running async-enabled coroutine, or default 61values are used (if caller is not running in async-enabled context). 62 63### Simple asynchronous I/O example 64 65Following example reacts on the press of button, reads contents of 66`/etc/passwd` and dumps it to standard output. 67 68 local window = Gtk.Window { 69 ... Gtk.Button { id = 'button', label = 'Breach' }, ... 70 } 71 72 function window.child.button:on_clicked() 73 local function dump_file(filename) 74 local file = Gio.File.new_for_path(filename) 75 local info = file:async_query_info('standard::size', 'NONE') 76 local stream = file:async_read() 77 local bytes = stream:async_read_bytes(info:get_size()) 78 print(bytes.data) 79 stream:async_close() 80 end 81 Gio.Async.start(dump_file)('/etc/passwd') 82 end 83 84Note that all reading happens running on background, on_clicked() 85handler finished when the operation is still running on background, so 86if you have a few gigabytes worth /etc/passwd file, the application 87will not freeze while dumping it. 88 89`samples/giostream.lua` provides far more involved sample illustrating 90use of asynchronous operations. 91