170 lines
5.1 KiB
Lua
170 lines
5.1 KiB
Lua
--------------------------------------------------------------------------------
|
|
------------------------------ ##### ## ------------------------------
|
|
------------------------------ ## ## # ## ------------------------------
|
|
------------------------------ ## ## ## ## ------------------------------
|
|
------------------------------ ## ## # ## ------------------------------
|
|
------------------------------ ##### ### ###### ------------------------------
|
|
-------------------------------- --------------------------------
|
|
----------------------- An Object Request Broker in Lua ------------------------
|
|
--------------------------------------------------------------------------------
|
|
-- Project: OiL - ORB in Lua: An Object Request Broker in Lua --
|
|
-- Release: 0.4 --
|
|
-- Title : Remote Object Proxies --
|
|
-- Authors: Renato Maia <maia@inf.puc-rio.br> --
|
|
--------------------------------------------------------------------------------
|
|
-- proxies:Facet
|
|
-- proxy:object proxyto(reference:table)
|
|
--
|
|
-- invoker:Receptacle
|
|
-- [results:object], [except:table] invoke(reference, operation, args...)
|
|
--------------------------------------------------------------------------------
|
|
|
|
local assert = assert
|
|
local error = error
|
|
local pairs = pairs
|
|
local rawget = rawget
|
|
local select = select
|
|
local setmetatable = setmetatable
|
|
local unpack = unpack
|
|
|
|
local table = require "loop.table"
|
|
|
|
local oo = require "oil.oo" --[[VERBOSE]] local verbose = require "oil.verbose"
|
|
|
|
module("oil.kernel.base.Proxies", oo.class)
|
|
|
|
context = false
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
Results = oo.class{}
|
|
|
|
function Results:results()
|
|
return self.success, unpack(self, 1, self.resultcount)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
local DefaultHandler
|
|
|
|
function callhandler(self, ...)
|
|
local handler = rawget(self, "__exceptions") or
|
|
rawget(oo.classof(self), "__exceptions") or
|
|
DefaultHandler or
|
|
error((...))
|
|
return handler(self, ...)
|
|
end
|
|
|
|
function packresults(...)
|
|
return Results{ success = true, resultcount = select("#", ...), ... }
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function assertcall(self, operation, reply, except)
|
|
return reply or packresults(callhandler(self, except, operation))
|
|
end
|
|
|
|
function assertresults(self, operation, success, except, ...)
|
|
if not success then
|
|
return callhandler(self, except, operation)
|
|
end
|
|
return except, ...
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function newcache(methodmaker)
|
|
return setmetatable(oo.initclass(), {
|
|
__mode = "v",
|
|
__call = oo.rawnew,
|
|
__index = function(cache, operation)
|
|
local function invoker(self, ...) --[[VERBOSE]] verbose:proxies("call to ",operation, ...)
|
|
return self.__context.invoker:invoke(self.__reference, operation, ...)
|
|
end
|
|
invoker = methodmaker(invoker, operation)
|
|
cache[operation] = invoker
|
|
return invoker
|
|
end,
|
|
})
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function makemethod(invoker, operation)
|
|
return function(self, ...)
|
|
return assertresults(self, operation,
|
|
assertcall(self, operation, invoker(self, ...)):results()
|
|
)
|
|
end
|
|
end
|
|
|
|
Proxy = newcache(makemethod)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
function makeprotected(invoker)
|
|
return function(self, ...)
|
|
local reply, except = invoker(self, ...)
|
|
if reply
|
|
then return reply:results()
|
|
else return false, except
|
|
end
|
|
end
|
|
end
|
|
|
|
Protected = newcache(makeprotected)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
FailedFuture = oo.class()
|
|
function FailedFuture:ready() return true end
|
|
function FailedFuture:results() return false, self[1] end
|
|
function evaluatefuture(self) --[[VERBOSE]] verbose:proxies("getting deferred results of ",self.operation)
|
|
return assertresults(
|
|
self.proxy,
|
|
self.operation,
|
|
self:results()
|
|
)
|
|
end
|
|
|
|
function makedeferred(invoker, operation)
|
|
return function(self, ...)
|
|
local reply, except = invoker(self, ...)
|
|
if reply == nil then reply = FailedFuture{ except } end
|
|
reply.proxy = self
|
|
reply.operation = operation
|
|
reply.evaluate = evaluatefuture
|
|
return reply
|
|
end
|
|
end
|
|
|
|
Deferred = newcache(makedeferred)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
Extras = {
|
|
__deferred = Deferred,
|
|
__try = Protected,
|
|
}
|
|
|
|
function proxyto(self, reference)
|
|
local proxy = Proxy{
|
|
__context = self.context,
|
|
__reference = reference,
|
|
}
|
|
for label, class in pairs(Extras) do
|
|
proxy[label] = class{
|
|
__context = self.context,
|
|
__reference = reference,
|
|
}
|
|
end
|
|
return proxy
|
|
end
|
|
|
|
function excepthandler(self, handler)
|
|
DefaultHandler = handler
|
|
return true
|
|
end
|