Question

I have a post-hook function that receives some data for itself, reference to another function and arguments for that arbitrary function in .... This function does some post-processing, after referenced function returns. For simplicity let's just note time:

function passthrough(tag, func, ...)
    metric1[tag] = os.time()
    func(...)
    metric2[tag] = os.time()
end

Since I need to postprocess, I can't immediately return func(...) and I don't know in advance how many returns there will be. How can I passthrough those returns after I'm done with post-processing?

So far I can think only of packing call in local results = { func(...) } and then using return unpack(results) or making a postprocessor factory that'd generate postprocessing closure with all necessary data as upvalues:

local function generate_postprocessor(tag)
    return function(...)
        metric2[tag] = os.time()
        return ...
    end
end

function passthrough2(tag, func, ...)
    metric1[tag] = os.time()
    return generate_postprocessor(tag)(func(...))
end

However, both those approaches would introduce some overhead that is undesirable, considering high amount of iterations and real-time nature of application. Is there anything simpler?

Was it helpful?

Solution

You don't need the closure. func is called before calling your closure generator anyway. You just need a function that passes its arguments straight through to its return values to give you a hook point for your second tag:

function passthrough_return(tag, ...)
    metric2[tag] = os.time()
    return ...
end

function passthrough(tag, func, ...)
    metric1[tag] = os.time()
    return passthrough_return(tag, func(...))
end

You're still getting the overhead of an extra function call, but that's better than creating a closure or a table and far less than the overhead of your pre/post processing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top