Yes, I think it will have to be something a bit more involved.
My original plan was to override all of the functions that are in play here (all of the methods defined in CompilationHandler, plus a number of others) so that they use the appropriate data.
However, as I think about this, perhaps the answer is even simpler:
The problem isn't strictly the methods themselves, it's more a matter of making them use the right set of data. Therefore, would it not be just as effective to implement getters/setters on the appropriate datasources:
class ResolutionEnvironment { array pike_module_path = ({}); array pike_include_path = ({}); mapping objects; // etc... }
mapping(Pike.Thread|string:ResolutionEvironment) _multitenant_threads = (["default": ResolutionEvironment()]);
`->pike_module_path() { array x; // do we have a special environment for this thread? if(x = _multitenant_threads[Thread.this_thread()]) { return x->pike_module_path; } // otherwise return the global environment else return _multitentant_threads["default"]->pike_module_path; }
My understanding is that the getter/setters operate at a lower level than standard `->(), so it's impossible to avoid them being called, which is desirable in this case.
Of course, this is all in addition to the necessary machinery to register a given configuration with one or more threads.
Bill
On Sun, 12 Feb 2012, Martin Stjernholm, Roxen IS @ Pike developers forum wrote:
Isn't it necessary for you to implement something similar to the compat master scheme? I.e. not only have separate compilation handlers, but also separate master objects?
Looks like the compat master scheme uses subtyped object pointers, i.e. Pike_N_M_master::xxx, which I doubt would work for you, but you could instead have a global mapping somewhere where you keep track of the master objects for your "tenants".
Note also that some caches in the real master should be possible to keep global. E.g. fc, because it uses paths, and the objects mapping, because it's indexed on the program instances which are different when there is a real difference. The programs mapping also uses paths, but a problem there is the special "/master" entry, so it'd require some sort of wrapper object with `[], `[]= etc.