     public private(set) var frameIndex: Int = 0
     public private(set) var time: NSTimeInterval = 0
     
-    private var handler: (image: UIImage?, index: Int, duration: NSTimeInterval) -> Void
+    private var handler: (image: UIImage, index: Int, duration: NSTimeInterval) -> Void
     private let image: AnimatedImage
     private var link: CADisplayLink!
+    
+    private var spinLock = OS_SPINLOCK_INIT
+    private var buffer: [Int: ImageState] = [:]
+    private var miss = true
+    
+    private let operationQueue = NSOperationQueue()
     
     public init(scale: CGFloat = UIScreen.mainScreen().scale,
         runloopMode: String = NSRunLoopCommonModes,
         image: AnimatedImage,
-        handler: (image: UIImage?, index: Int, duration: NSTimeInterval) -> Void) {
+        handler: (image: UIImage, index: Int, duration: NSTimeInterval) -> Void) {
             self.handler = handler
             self.scale = scale
             self.image = image

                break
            }
        }
        // TODO: async load image if needed. maybe cancel loading
        if index != frameIndex {
            frameIndex = index
            handler(image: image.imageAtIndex(index), index: index, duration: durations[index])
        }
    }
    

    
    @objc private func linkFired(link: CADisplayLink) {
        let nextTime = time - floor(time / totalTime) * totalTime + link.duration
        update(nextTime, lastDuration: link.duration)
    }
    
    private func update(nextTime: NSTimeInterval, lastDuration: NSTimeInterval = 0) {
        var index = 0
        for var temp: NSTimeInterval = 0, i = 0; i < frameCount; ++i {
            temp += durations[i]
