anchor.diff:      member private this.Swapping =
           lock swapLock (fun () -> swap)
   
  +    member private this.Run () =
  +
  +        // create renderer
  +        let renderer = createRenderer2d () : Renderer2d
  +
  +        // mark as started
  +        lock startedLock (fun () -> started <- true)
  +
  +        // loop until terminated
  +        while not this.Terminated do
  +
  +            // loop until submission exists
  +            while Option.isNone this.SubmissionOpt && not this.Terminated do
  +                Thread.Sleep 0
  +
  +            // receive submission
  +            let (eyePosition, eyeSize, eyeMargin) =
  +                lock submissionLock (fun () ->
  +                    let submission = Option.get submissionOpt
  +                    submissionOpt <- None
  +                    submission)
  +
  +            // receive messages
  +            let messagesReceived =
  +                lock messagesLock (fun () ->
  +                    let messagesReceived = messages
  +                    messages <- List ()
  +                    messagesReceived)
  +
  +            // render
  +            renderer.Render eyePosition eyeSize eyeMargin messagesReceived
  +
  +            // loop until swapping
  +            while not this.Swapping && not this.Terminated do
  +                Thread.Sleep 0
  +
  +            // swap
  +            renderer.Swap ()
  +
  +            // clear swap
  +            lock swapLock (fun () -> swap <- false)
  +
  +        // clean up
  +        renderer.CleanUp ()
  +
       interface RenderProcess2d with
   
           member this.Started =
  
positive.code:             lock terminatedLock (fun () -> terminated)
  
          member this.Start () =
  
              // run thread as task
              let task = new Task (fun () ->
  
                  // create renderer
                  let renderer = createRenderer2d () : Renderer2d
  
                  // mark as started
                  lock startedLock (fun () -> started <- true)
  
                  // loop until terminated
                  while not this.Terminated do
  
                      // loop until submission exists
                      while Option.isNone this.SubmissionOpt && not this.Terminated do
                          Thread.Sleep 0
  
                      // receive submission
                      let (eyePosition, eyeSize, eyeMargin) =
                          lock submissionLock (fun () ->
                              let submission = Option.get submissionOpt
                              submissionOpt <- None
                              submission)
  
                      // receive messages
                      let messagesReceived =
                          lock messagesLock (fun () ->
                              let messagesReceived = messages
                              messages <- List ()
                              messagesReceived)
  
                      // render
                      renderer.Render eyePosition eyeSize eyeMargin messagesReceived
  
                      // loop until swapping
                      while not this.Swapping && not this.Terminated do
                          Thread.Sleep 0
  
                      // swap
                      renderer.Swap ()
  
                      // clear swap
                      lock swapLock (fun () -> swap <- false)
  
                  // clean up
                  renderer.CleanUp ())
  
              // remember task
              taskOpt <- Some task
  
              // start task
              task.Start ()
  
              // wait until started (renderer initialized)
              while not this.Started do Thread.Sleep 0
  
          member this.EnqueueMessage message =
  
negative.code: /// A threaded 2d render process.
  type RenderThread2d (createRenderer2d) =
  
      let mutable threadOpt = None
      let startedLock = obj ()
      let mutable started = false
      let terminatedLock = obj ()
  