You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnosygnu_xowa/100_core/src/gplx/core/brys/Bry_bfr_mkr_mgr.java

105 lines
3.6 KiB

/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.core.brys;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.Err_;
import gplx.Int_;
import gplx.Int_ary_;
import gplx.objects.arrays.ArrayUtl;
public class Bry_bfr_mkr_mgr {
private final Object thread_lock = new Object();
private final byte mgr_id; private final int reset;
private Bry_bfr[] used = Bry_bfr_.Ary_empty; private int used_len = 0, used_max = 0;
private int[] free; private int free_len;
public Bry_bfr_mkr_mgr(byte mgr_id, int reset) {// NOTE: random IndexOutOfBounds errors in Get around free[--free_len] with free_len being -1; put member variable initialization within thread_lock to try to avoid; DATE:2014-09-21
this.mgr_id = mgr_id;
this.reset = reset;
this.free = Int_ary_.Empty;
this.free_len = 0;
}
public Bry_bfr Get() {
synchronized (thread_lock) {
Bry_bfr rv = null; int rv_idx = -1;
if (free_len > 0) {
try {rv_idx = free[--free_len];} catch (Exception e) {throw Err_.new_exc(e, "core", "failed to get free", "idx", free_len, "free_len", free.length);}
try {rv = used[rv_idx];} catch (Exception e) {throw Err_.new_exc(e, "core", "failed to get used", "idx", rv_idx, "used_len", used.length);}
}
else {
if (used_len == used_max) Expand();
rv_idx = used_len++;
rv = used[rv_idx];
if (rv == null) {
rv = Bry_bfr_.Reset(reset);
used[rv_idx] = rv;
}
}
rv.Mkr_init(this, rv_idx);
return rv.Clear(); // NOTE: ALWAYS call Clear when doing Get. caller may forget to call Clear, and reused bfr may have leftover bytes. unit tests will not catch, and difficult to spot in app
}
}
public void Rls(int idx) {
synchronized (thread_lock) {
if (idx == -1) throw Err_.new_wo_type("rls called on bfr that was not created by factory");
int new_used_len = used_len - 1;
if (idx == new_used_len)
used_len = new_used_len;
else
free[free_len++] = idx;
}
}
public void Clear_fail_check() {
synchronized (thread_lock) {
for (int i = 0; i < used_max; i++) {
Bry_bfr itm = used[i];
if (itm != null) {
if (!itm.Mkr_idx_is_null()) throw Err_.new_wo_type("failed to clear bfr", "mgr_id", mgr_id, "idx", Int_.To_str(i));
itm.Clear();
}
used[i] = null;
}
used = Bry_bfr_.Ary_empty;
free = Int_ary_.Empty;
free_len = used_len = used_max = 0;
}
}
public void Clear() {
synchronized (thread_lock) {
for (int i = 0; i < used_max; i++) {
Bry_bfr itm = used[i];
if (itm != null) itm.Clear();
used[i] = null;
}
used = Bry_bfr_.Ary_empty;
free = Int_ary_.Empty;
free_len = 0;
used_len = used_max = 0;
}
}
@gplx.Internal protected Bry_bfr[] Used() {return used;}
@gplx.Internal protected int Used_len() {return used_len;}
private void Expand() {
int new_max = used_max == 0 ? 2 : used_max * 2;
Bry_bfr[] new_ary = new Bry_bfr[new_max];
ArrayUtl.CopyTo(used, 0, new_ary, 0, used_max);
used = new_ary;
used_max = new_max;
int[] new_free = new int[used_max];
ArrayUtl.CopyTo(free, 0, new_free, 0, free_len);
free = new_free;
}
}