cvs commit: fptools/hdirect/comlib Com.lhs ComPrim.idl ComPrimSrc.c ComServ.lhs fptools/hdirect/src MarshallCore.lhs MarshallType.lhs

Simon Marlow <[email protected]> Tue, 26 Oct 2004 05:24:42 -0700
Newsgroups gmane.comp.lang.haskell.cvs.hdirect
Message-ID <[email protected]>
simonmar    2004/10/26 05:24:42 PDT

  Modified files:        (Branch: hdirect-ifaces-are-ptrs)
    hdirect/comlib       Com.lhs ComPrim.idl ComPrimSrc.c 
                         ComServ.lhs 
    hdirect/src          MarshallCore.lhs MarshallType.lhs 
  Log:
  [committing on the branch this time]
  Yet another branch of H/Direct.
  
  On this branch, COM interface pointers are simply Ptrs rather than
  ForeignPtrs.  You must addRef/release interface pointers according to
  the rules of COM, rather than relying on the finalisers to do the
  business.
  
  The ForeignPtr/finaliser story didn't work well for us, particularly
  when implementing a COM server, for a couple of reasons:
  
    - When a method you're implementing gets passed an interface ptr,
      H/Direct arranges to AddRef() the interface and sets up a finalizer
      to Release() it.  One problem is that the Release() might not
      happen for a long time.  In a C++ implementation, this
      AddRef()/Release() combo would never happen for an ordinary
      method parameter.
  
    - A worse problem is that the Release() finaliser might happen in a
      different OS thread.  The original OS thread that made the call-in
      is probably no longer available - it's off outside Haskell land
      doing other stuff.
  
  Furthermore, interfaces as Ptrs is much more efficient.  Marshalling
  and unmarshalling are essentially no-ops, compared to creating a
  ForeignPtr, an extra AddRef() & Release(), and the cost of running the
  finalizer itself.
  
  The down side is having to be careful about your addRefs/releases.  I
  handled one of the common cases, queryInterface, like this:
  
    withQueryInterface :: IID (IUnknown a) -> IUnknown b
  		     -> (IUnknown b -> IO c) -> IO c
  
  with the obvious implementation using bracket.
  
  I imagine we could implement some automatic checking to catch missing
  addRefs & releases, perhaps with a special DEBUG version of comlib.
  eg. go back to using ForeignPtrs, but have the finaliser just check
  that you had called release.
  
  Revision  Changes    Path
  1.13.4.1  +9 -11     fptools/hdirect/comlib/Com.lhs
  1.8.4.1   +11 -15    fptools/hdirect/comlib/ComPrim.idl
  1.4.4.1   +0 -29     fptools/hdirect/comlib/ComPrimSrc.c
  1.7.4.1   +9 -11     fptools/hdirect/comlib/ComServ.lhs
  1.57.4.1  +3 -2      fptools/hdirect/src/MarshallCore.lhs
  1.135.4.1 +1 -1      fptools/hdirect/src/MarshallType.lhs