
package master.flame.danmaku.controller;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.Log;
import master.flame.danmaku.danmaku.model.IDisplayer;
import master.flame.danmaku.danmaku.model.RingBuffer;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public abstract class DrawingCache {

    private static final String TAG = "DrawingCache";
    public Object mBufferLock = new Object();

    Thread mThread = new Thread(TAG) {

        public static final String TAG = "DrawingCache";

        @Override
        public void run() {

            while (!quitFlag) {

                while (true) {
                    synchronized (mBufferLock) {

                        if (mScrapList.size() > 0) {
                            DrawingCacheHolder holder = mScrapList.get(0);
                            mScrapList.remove(0);
                            drawCache(holder);
                            mBuffer.put(holder);
                        }

                        if (mScrapList.isEmpty()) {
                            break;
                        }
                        try {
                            Thread.sleep(5);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

                synchronized (this) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }

        }

    };

    private IDisplayer mDisp;

    private HolderRingBuffer mBuffer;

    private List<DrawingCacheHolder> mScrapList = new ArrayList<DrawingCacheHolder>();

    private boolean quitFlag;

    public DrawingCache(int capacity, IDisplayer disp) {
        mBuffer = new HolderRingBuffer(capacity);
        mDisp = disp;
        for (int i = 0; i < capacity; i++) {
            mScrapList.add(new DrawingCacheHolder(disp.getWidth(), disp.getHeight()));
        }
    }

    public Bitmap getCache() {
        Bitmap bmp = null;
        synchronized (mBufferLock) {
            DrawingCacheHolder holder = mBuffer.get();
            if (holder != null) {
                bmp = holder.bitmap;
                mScrapList.add(holder);
            }
            Log.e(TAG, "buffered:" + mBuffer.size() + ",scrap:" + mScrapList.size());
        }
        return bmp;
    }

    /**
     * 使用cache之后调用
     */
    public void fillNext() {
        synchronized (mThread) {
            mThread.notify();
        }
    }

    protected abstract void drawCache(DrawingCacheHolder holder);

    public void start() {
        mThread.start();
    }

    public void quit() {
        quitFlag = true;
        fillNext();
        recyle();
    }

    public void recyle() {
        clear();
        synchronized (mBufferLock) {
            if (mScrapList != null) {
                Iterator<DrawingCacheHolder> it = mScrapList.iterator();
                while (it.hasNext()) {
                    DrawingCacheHolder holder = it.next();
                    holder.recycle();
                    it.remove();
                }
            }
        }
    }

    public void clear() {
        synchronized (mBufferLock) {
            while (!mBuffer.isEmpty()) {
                getCache();
            }
        }
    }

    public class DrawingCacheHolder {

        public Canvas canvas;

        public Bitmap bitmap;

        public Object extra;

        public DrawingCacheHolder(int w, int h) {
            bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            canvas = new Canvas(bitmap);
        }

        public void recycle() {
            bitmap.recycle();
            bitmap = null;
            canvas = null;
            extra = null;
        }

    }

    public class HolderRingBuffer extends RingBuffer<DrawingCacheHolder> {

        public HolderRingBuffer(int capacity) {
            super(capacity);
        }

        @Override
        protected DrawingCacheHolder[] createBuffer(int capacity) {
            return new DrawingCacheHolder[capacity];
        }
    }

}

@@ -104,33 +104,8 @@
 as;%0A
-import android.util.Log;%0A
 impo
@@ -154,16 +154,16 @@
 player;%0A
+
 import m
@@ -471,66 +471,8 @@
  %7B%0A%0A
-        public static final String TAG = %22DrawingCache%22;%0A%0A
     
@@ -574,24 +574,26 @@
 le (true) %7B%0A
+%0A%0A
             
@@ -1040,32 +1040,51 @@
           %7D%0A    
+                %7D%0A%0A
                 
@@ -1085,36 +1085,32 @@
           try %7B%0A
-    
                 
@@ -1146,36 +1146,32 @@
                 
-    
 %7D catch (Interru
@@ -1205,36 +1205,32 @@
                 
-  
-  
 e.printStackTrac
@@ -1238,34 +1238,8 @@
 ();%0A
-                        %7D%0A
     
@@ -2266,32 +2266,32 @@
 st.add(holder);%0A
+
             %7D%0A  
@@ -2292,94 +2292,8 @@
   %7D%0A
-            Log.e(TAG, %22buffered:%22 + mBuffer.size() + %22,scrap:%22 + mScrapList.size());%0A
     

修复synchronized thread sleep可能造成的读取效率问题