> I appreciate it's not Malcolm Wallace's fault that NHC can't > implement a form of dynamic wrapper which can be used at all times. > However since I do not think this problem is going to go away, would > it not be better to put it in the specification but admit that NHC > can't do it? Otherwise the FFI specification will be very good (as > it is) if you want to call languages like C, but will be inadequate > if you want to communicate with other languages which also know > about things like concurrency and garbage-collection, such as > Haskell or even Java.
I think the two of you are getting caught up in implementation details (which always seem fixable) instead of looking at fundamentals (which tend not to be). The issue is that allowing finalizers to be Haskell code or to call Haskell code forces us to add preemptive concurrency to every Haskell implementation. Hugs has cooperative concurrency but that isn't enough, it has to be preemptive. To see why, suppose Hugs is busy calculating sum [1..1000000] and a garbage collection finds it has to run a Haskell function, it can't run it straight away because that would preempt the original execution. Likewise, it can't run it immediately that the GC ends - that's still preemption. Hugs is probably busy evaluating a + or (:) or the like when the GC happens, what if we wait until that finishes and then run the finalizers? Maybe. The world is in a cleaner state at this point but it's still tricky. And, again, you've just added most of the machinery required for implementing preemptive concurrency. Hugs does allow context switches in the IO monad. Could we allow it there? Maybe, we could. It wouldn't do you much good though because Haskell can spend arbitrarily long running pure code so your finalizers might not get run for a long time or maybe never. So what's the objection to adding preemptive concurrency? 1) The goal was to be able to call foreign code and have it call us. It seems like there's something wrong if doing that forces you to add concurrency. 2) Preemptive concurrency is one of those things that you can't just paint on later - you really have to rewrite the whole thing from scratch because it's just too hard to find all the pieces that make the assumption that they are single-threaded. 3) Adding preemptive concurrency guarantees a steady source of hard to repeat bugs - people aren't very good at writing concurrent code. Cooperative concurrency is much easier to handle because context switches happen at times when both tasks are ready for it: the sender because it knows it is passing control over, the receiver because it put itself in a clean state before it handed over control. You ask how garbage collection can work if you can't invoke it at arbitrary times? You ask what use foreign export is if you can't call the exported function at arbitrary times? [I hope I'm paraphrasing your questions appropriately] Both questions start by assuming that you have Haskell and Foosh [or whatever your other language is called] running in separate threads (otherwise things wouldn't happen at arbitrary times). Put them in a single thread and there's no problem: you're not doing things at arbitrary times, you're doing them at quite specific times: Foosh had control and it called into Haskell or Haskell had control and it called into Foosh. In other words, the problems you raise come from wanting preemptive concurrency so it's no wonder that the ffi extension doesn't address them. We could start working on a concurrency extension but that's a different beast. That said, we probably do need a few hooks to make Haskell talk to other GCs better. See the paper I pointed at this afternoon for a sketch of what you need if you're to avoid space leaks. -- Alastair Reid [EMAIL PROTECTED] Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/ _______________________________________________ FFI mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/ffi