Skip to content

Commit

Permalink
Implement async_ support also for static methods and global functions
Browse files Browse the repository at this point in the history
  • Loading branch information
pavouk committed Nov 20, 2016
1 parent 222db34 commit a7e928e
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 26 deletions.
6 changes: 3 additions & 3 deletions lgi/component.lua
@@ -1,8 +1,8 @@
------------------------------------------------------------------------------
--
-- LGI Basic repo type component implementation
-- lgi Basic repo type component implementation
--
-- Copyright (c) 2010, 2011, 2012, 2013 Pavel Holejsovsky
-- Copyright (c) 2010, 2011, 2012, 2013, 2016 Pavel Holejsovsky
-- Licensed under the MIT license:
-- http://www.opensource.org/licenses/mit-license.php
--
Expand Down Expand Up @@ -152,7 +152,7 @@ function component.mt:_resolve()
end

-- Implementation of _access method, which is called by _core when
-- repo instance is accessed for reading or writing.
-- instance of repo-based type is accessed for reading or writing.
function component.mt:_access(instance, symbol, ...)
-- Invoke _element, which converts symbol to element and category.
local element, category = self:_element(instance, symbol)
Expand Down
15 changes: 11 additions & 4 deletions lgi/namespace.lua
@@ -1,8 +1,8 @@
------------------------------------------------------------------------------
--
-- LGI Support for repository namespace
-- lgi Support for repository namespace
--
-- Copyright (c) 2010, 2011 Pavel Holejsovsky
-- Copyright (c) 2010, 2011,2016 Pavel Holejsovsky
-- Licensed under the MIT license:
-- http://www.opensource.org/licenses/mit-license.php
--
Expand Down Expand Up @@ -61,7 +61,9 @@ end
local namespace = {
mt = {
_categories = { '_class', '_interface', '_struct', '_union', '_enum',
'_function', '_constant', } }
'_function', '_constant', },
_category_mt = {},
}
}

-- Gets symbol of the specified namespace, if not present yet, tries to load it
Expand Down Expand Up @@ -103,7 +105,12 @@ function namespace.mt:__index(symbol)
if val then
local cat = rawget(self, category)
if not cat then
cat = {}
local mt = namespace.mt._category_mt[category]
if not mt then
mt = {}
namespace.mt._category_mt[category] = mt
end
cat = setmetatable({ _namespace = self }, mt)
self[category] = cat
end
-- Store symbol into the repo, but only if it is not already
Expand Down
67 changes: 48 additions & 19 deletions lgi/override/Gio.lua
Expand Up @@ -2,7 +2,7 @@
--
-- lgi Gio override module.
--
-- Copyright (c) 2010, 2011, 2013 Pavel Holejsovsky
-- Copyright (c) 2010, 2011, 2013, 2016 Pavel Holejsovsky
-- Licensed under the MIT license:
-- http://www.opensource.org/licenses/mit-license.php
--
Expand All @@ -18,6 +18,8 @@ local GObject = lgi.GObject
local Gio = lgi.Gio

local component = require 'lgi.component'
local class = require 'lgi.class'
local namespace = require 'lgi.namespace'
local core = require 'lgi.core'
local gi = core.gi

Expand Down Expand Up @@ -100,22 +102,18 @@ end
-- xxx_async()/xxx_finish() sequence using currently running
-- coroutine.
local tag_int = gi.GObject.ParamSpecEnum.fields.default_value.typeinfo.tag
local inherited_element = GObject.Object._element
function GObject.Object:_element(object, name)
local element, category = inherited_element(self, object, name)
if element or not object then return element, category end

local function async_element(name, accessor, param_self, param_object)
-- Check, whether we have async_xxx request.
local name_root = name:match('^async_(.+)$')
local name_root = type(name) == 'string' and name:match('^async_(.+)$')
if name_root then
local async = inherited_element(self, object, name_root .. '_async')
local finish = inherited_element(self, object, name_root .. '_finish')
local async = accessor(param_self, param_object, name_root .. '_async')
local finish = accessor(param_self, param_object, name_root .. '_finish')

-- Some clients name async method just 'name' and use
-- 'name_sync' for synchronous variant.
if finish and not async
and inherited_element(self, object, name_root .. '_sync') then
async = inherited_element(self, object, name_root)
if finish and not async and accessor(param_self, param_object,
name_root .. '_sync') then
async = accessor(param_self, param_object, name_root)
end

-- We have async/finish pair, create element table containing
Expand Down Expand Up @@ -147,12 +145,7 @@ function GObject.Object:_element(object, name)
end
end

function GObject.Object:_access_async(object, element, ...)
if select('#', ...) > 0 then
error(("%s: `%s' not writable"):format(
core.object.query(object, 'repo')._name, name))
end

local function async_access(element, process_yield)
-- Generate wrapper method calling _async/_finish pair automatically.
return function(...)
-- Check that we are running inside context.
Expand All @@ -177,8 +170,44 @@ function GObject.Object:_access_async(object, element, ...)
args[element.in_args] = coroutine.running()

element.async(unpack(args, 1, element.in_args))
return element.finish(coroutine.yield())
return element.finish(process_yield(coroutine.yield()))
end
end

local inherited_class_element = class.class_mt._element
function class.class_mt:_element(object, name)
local element, category = inherited_class_element(self, object, name)
if element then return element, category end
return async_element(name, inherited_class_element, self, object)
end

function class.class_mt:_index_async(element)
return async_access(element, function(_, ...) return ... end)
end

local inherited_gobject_element = GObject.Object._element
function GObject.Object:_element(object, name)
local element, category = inherited_gobject_element(self, object, name)
if element then return element, category end
return async_element(name, inherited_gobject_element, self, object)
end

function GObject.Object:_access_async(object, element, ...)
if select('#', ...) > 0 then
error(("%s: `%s' not writable"):format(
core.object.query(object, 'repo')._name, name))
end

return async_access(element, function(...) return ... end)
end

-- Enforce that Gio._function category is already created
local _ = Gio.bus_get
function namespace.mt._category_mt._function:__index(key)
local element = async_element(key, function(_, _, name)
return self._namespace[name]
end)
return element and async_access(element, function(_, ...) return ... end)
end

function Gio.Initable._init2(object)
Expand Down
41 changes: 41 additions & 0 deletions tests/gio.lua
Expand Up @@ -8,6 +8,8 @@
--]]--------------------------------------------------------------------------
local type = type
local lgi = require 'lgi'
local core = require 'lgi.core'
Expand Down Expand Up @@ -37,3 +39,42 @@ function gio.read()
checkv(line, nil, "nil")
checkv(length, 0, "number")
end
function gio.async_access()
local Gio = lgi.Gio
local res
res = Gio.DBusProxy.async_new
check(res ~= nil)
check(type(res) == 'function')
res = Gio.DBusProxy.async_call
check(res ~= nil)
check(type(res) == 'function')
res = Gio.async_bus_get
check(res ~= nil)
check(type(res) == 'function')
local file = Gio.File.new_for_path('.')
res = Gio.Async.call(function(target)
return target:async_query_info('standard::size',
'NONE')
end)(file)
check(res ~= nil)
local b = Gio.Async.call(function()
return Gio.async_bus_get('SESSION')
end)()
check(Gio.DBusConnection:is_type_of(b))
local proxy = Gio.Async.call(function(bus)
return Gio.DBusProxy.async_new(
bus, 'NONE', nil,
'org.freedesktop.DBus',
'/',
'org.freedesktop.DBus')
end)(b)
check(Gio.DBusProxy:is_type_of(proxy))
end

0 comments on commit a7e928e

Please sign in to comment.