<commit_before>package me.xiaopan.sketch.drawable;

import android.graphics.Bitmap;
import android.util.Log;

import me.xiaopan.sketch.Sketch;
import me.xiaopan.sketch.util.SketchUtils;

public class RefBitmap extends SketchBitmap {

    private int cacheRefCount;
    private int displayRefCount;
    private int waitDisplayRefCount;

    private boolean allowRecycle = true;

    public RefBitmap(Bitmap bitmap, String imageId, String imageUri, int originWidth, int originHeight, String mimeType) {
        super(bitmap, imageId, imageUri, originWidth, originHeight, mimeType);
    }

    public void setIsDisplayed(String callingStation, boolean displayed) {
        synchronized (this) {
            if (displayed) {
                displayRefCount++;
            } else {
                if (displayRefCount > 0) {
                    displayRefCount--;
                }
            }
        }
        tryRecycle((displayed ? "display" : "hide"), callingStation);
    }

    public void setIsCached(String callingStation, boolean cached) {
        synchronized (this) {
            if (cached) {
                cacheRefCount++;
            } else {
                if (cacheRefCount > 0) {
                    cacheRefCount--;
                }
            }
        }
        tryRecycle((cached ? "putToCache" : "removedFromCache"), callingStation);
    }

    public void setIsWaitDisplay(String callingStation, boolean waitDisplay) {
        synchronized (this) {
            if (waitDisplay) {
                waitDisplayRefCount++;
            } else {
                if (waitDisplayRefCount > 0) {
                    waitDisplayRefCount--;
                }
            }
        }
        tryRecycle((waitDisplay ? "waitDisplay" : "displayed"), callingStation);
    }

    public boolean isRecycled() {
        Bitmap bitmap = getBitmap();
        return bitmap == null || bitmap.isRecycled();
    }

    public void recycle() {
        Bitmap bitmap = getBitmap();
        if (bitmap != null) {
            bitmap.recycle();
        }
    }

    public boolean canRecycle() {
        return allowRecycle && getBitmap() != null && !getBitmap().isRecycled();
    }

    public boolean isAllowRecycle() {
        return allowRecycle;
    }

    @SuppressWarnings("unused")
    public void setAllowRecycle(boolean allowRecycle) {
        this.allowRecycle = allowRecycle;
    }
<commit_msg>RefBitmap method plus synchronous lock<commit_after>/*
 * Copyright (C) 2016 <NAME> <<EMAIL>>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package me.xiaopan.sketch.drawable;

import android.graphics.Bitmap;
import android.util.Log;

import me.xiaopan.sketch.Sketch;
import me.xiaopan.sketch.util.SketchUtils;

/**
 * 引用Bitmap，能够计算缓存引用、显示引用以及等待显示引用
 */
public class RefBitmap extends SketchBitmap {

    private int cacheRefCount;
    private int displayRefCount;
    private int waitDisplayRefCount;

    private boolean allowRecycle = true;

    public RefBitmap(Bitmap bitmap, String imageId, String imageUri, int originWidth, int originHeight, String mimeType) {
        super(bitmap, imageId, imageUri, originWidth, originHeight, mimeType);
    }

    /**
     * 设置显示引用
     *
     * @param callingStation 调用位置
     * @param displayed      显示
     */
    public synchronized void setIsDisplayed(String callingStation, boolean displayed) {
        synchronized (this) {
            if (displayed) {
                displayRefCount++;
            } else {
                if (displayRefCount > 0) {
                    displayRefCount--;
                }
            }
        }
        tryRecycle((displayed ? "display" : "hide"), callingStation);
    }

    /**
     * 设置缓存引用
     *
     * @param callingStation 调用位置
     * @param cached         缓存
     */
    public synchronized void setIsCached(String callingStation, boolean cached) {
        synchronized (this) {
            if (cached) {
                cacheRefCount++;
            } else {
                if (cacheRefCount > 0) {
                    cacheRefCount--;
                }
            }
        }
        tryRecycle((cached ? "putToCache" : "removedFromCache"), callingStation);
    }

    /**
     * 设置等待缓存怒引用
     *
     * @param callingStation 调用位置
     * @param waitDisplay    等待显示
     */
    public synchronized void setIsWaitDisplay(String callingStation, boolean waitDisplay) {
        synchronized (this) {
            if (waitDisplay) {
                waitDisplayRefCount++;
            } else {
                if (waitDisplayRefCount > 0) {
                    waitDisplayRefCount--;
                }
            }
        }
        tryRecycle((waitDisplay ? "waitDisplay" : "displayed"), callingStation);
    }

    /**
     * 已回收
     */
    public synchronized boolean isRecycled() {
        Bitmap bitmap = getBitmap();
        return bitmap == null || bitmap.isRecycled();
    }

    /**
     * 回收Bitmap
     */
    public synchronized void recycle() {
        Bitmap bitmap = getBitmap();
        if (bitmap != null) {
            bitmap.recycle();
        }
    }

    /**
     * 可以回收？只有三种引用都为0并且允许回收才可以回收
     */
    public synchronized boolean canRecycle() {
        return allowRecycle && getBitmap() != null && !getBitmap().isRecycled();
    }

    /**
     * 允许回收（默认允许）
     */
    @SuppressWarnings("unused")
    public synchronized boolean isAllowRecycle() {
        return allowRecycle;
    }

    /**
     * 设置允许回收
     */
    @SuppressWarnings("unused")
    public synchronized void setAllowRecycle(boolean allowRecycle) {
        this.allowRecycle = allowRecycle;
    }

    /**
     * 尝试回收
     *
     * @param type           类型
     * @param callingStation 调用位置
     */
{'fraction_non_alphanumeric': 0.09627479438800193, 'fraction_numerical': 0.0024189646831156266, 'mean_word_length': 1.9889156626506024, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2559802', 'n_tokens_mistral': 1773, 'n_tokens_neox': 1761, 'n_words': 425}