Changes between Version 7 and Version 8 of Building/CrossCompiling/iOS


Ignore:
Timestamp:
Mar 1, 2013 1:30:08 AM (2 years ago)
Author:
StephenBlackheath
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Building/CrossCompiling/iOS

    v7 v8  
    160160Each time you modify your Haskell code you'll need to re-compile from the command line before re-building in Xcode. It is possible to automate this in Xcode if you wish. 
    161161 
    162 == Loose Ends == 
     162== Adjustor pools == 
     163 
     164A declaration for a "wrapper" callback looks like this: 
     165 
     166{{{ 
     167foreign import ccall safe "wrapper" 
     168        mkDelegate :: IO () -> IO (FunPtr (IO ())) 
     169}}} 
     170 
     171To implement these, GHC normally generates a small piece of executable code at runtime, called an "adjustor".  The purpose of these "wrapper" declarations is to generate a C-callable function pointer that executes Haskell code. 
     172 
     173Due to Apple's requirements for code-signing, the iOS kernel enforces a ban on self-modifying code. 
     174 
     175We solve this conundrum by pre-compiling a pool of functions, and allocating from it.  Because the pool size for each wrapper is fixed, this creates the problem that the pool can run out.  If this happens, the application will die with this message: 
     176 
     177{{{ 
     178HaskellDraw: internal error: createPooledAdjustor - adjustor pool 'Main_d1tU' is empty (capacity 32) 
     179}}} 
     180 
     181(The name of the module where the "wrapper" was declared appears before the underscore character.) 
     182 
     183Each "wrapper" declaration has its own pool, whose size defaults to 32.  This means that at any one time, there can exist no more than 32 adjustors created by the defined wrapper constructor function (in this example, mkDelegate).  '''Foreign.Ptr.freeHaskellFunPtr''' is the IO action to free an adjustor, and in this implementation this returns it to the pool. 
     184 
     185If the pool is too small for a given application, you can increase it by using a {-# POOLSIZE x #-} pragma, which must appear after the "wrapper" token.  e.g. 
     186 
     187{{{ 
     188foreign import ccall safe "wrapper" {-# POOLSIZE 100 #-} 
     189        mkDelegate :: IO () -> IO (FunPtr (IO ())) 
     190}}} 
     191 
     192Because pool sizes are limited, it should be considered unsafe to call freeHaskellFunPtr in a finalizer, because garbage collection is not predictable. 
     193 
     194The {{{POOLSIZE}}} pragma generates a compiler warning only on GHC versions where it isn't supported, so in practice it's portable. 
     195 
     196== Loose ends == 
    163197 
    164198Outstanding issues we should fix in rough priority order.