|
@@ -6,10 +6,12 @@ namespace Invercargill.DataStructures {
|
|
|
private int n_items = 0;
|
|
|
private SafeReadFunc<T>? safe_read;
|
|
|
private SafeWriteFunc<T>? safe_write;
|
|
|
+ private RWLock rw_lock;
|
|
|
|
|
|
private const int INITIAL_SIZE = 2;
|
|
|
|
|
|
public Vector() {
|
|
|
+ rw_lock = RWLock();
|
|
|
array = new T[INITIAL_SIZE];
|
|
|
safe_read = get_safe_read_function_for<T>();
|
|
|
safe_write = get_safe_write_function_for<T>();
|
|
@@ -19,6 +21,13 @@ namespace Invercargill.DataStructures {
|
|
|
return n_items;
|
|
|
}
|
|
|
|
|
|
+ public override int count(PredicateDelegate<T>? predicate = null) {
|
|
|
+ if(predicate == null) {
|
|
|
+ return n_items;
|
|
|
+ }
|
|
|
+ return base.count(predicate);
|
|
|
+ }
|
|
|
+
|
|
|
public override EnumerableInfo get_info() {
|
|
|
return new EnumerableInfo.infer_ultimate (this, EnumerableCategory.IN_MEMORY);
|
|
|
}
|
|
@@ -28,81 +37,85 @@ namespace Invercargill.DataStructures {
|
|
|
}
|
|
|
|
|
|
public override T[] to_array () {
|
|
|
- lock(array) {
|
|
|
- var a2 = new T[n_items];
|
|
|
- if(safe_write != null) {
|
|
|
- for(var i = 0; i < n_items; i++) {
|
|
|
- safe_write(a2, i, array_read(i));
|
|
|
- }
|
|
|
+ rw_lock.reader_lock();
|
|
|
+ var a2 = new T[n_items];
|
|
|
+ if(safe_write != null) {
|
|
|
+ for(var i = 0; i < n_items; i++) {
|
|
|
+ safe_write(a2, i, array_read(i));
|
|
|
}
|
|
|
- else {
|
|
|
- for(var i = 0; i < n_items; i++) {
|
|
|
- a2[i] = array[i];
|
|
|
- }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ for(var i = 0; i < n_items; i++) {
|
|
|
+ a2[i] = array[i];
|
|
|
}
|
|
|
- return a2;
|
|
|
}
|
|
|
+ rw_lock.reader_unlock();
|
|
|
+ return a2;
|
|
|
}
|
|
|
|
|
|
public void add(T item) {
|
|
|
- lock(array) {
|
|
|
- ensure_room(1);
|
|
|
- array_write(n_items, item);
|
|
|
- n_items++;
|
|
|
- }
|
|
|
+ rw_lock.writer_lock();
|
|
|
+ ensure_room(1);
|
|
|
+ array_write(n_items, item);
|
|
|
+ n_items++;
|
|
|
+ rw_lock.writer_unlock();
|
|
|
}
|
|
|
|
|
|
public override void add_all(Enumerable<T> items) {
|
|
|
- lock(array) {
|
|
|
- foreach (var item in items) {
|
|
|
- ensure_room(1);
|
|
|
- array_write(n_items, item);
|
|
|
- n_items++;
|
|
|
- }
|
|
|
+ rw_lock.writer_lock();
|
|
|
+ foreach (var item in items) {
|
|
|
+ ensure_room(1);
|
|
|
+ array_write(n_items, item);
|
|
|
+ n_items++;
|
|
|
}
|
|
|
+ rw_lock.writer_unlock();
|
|
|
}
|
|
|
|
|
|
public new T @get(uint index) throws IndexError {
|
|
|
IndexError? e = null;
|
|
|
- lock(array) {
|
|
|
- if(index < 0) {
|
|
|
- e = new IndexError.INDEX_EXCEEDS_LOWER_BOUNDS("Index is less than 0");
|
|
|
- }
|
|
|
- else if(index >= n_items) {
|
|
|
- e = new IndexError.INDEX_EXCEEDS_UPPER_BOUNDS(@"Tried to access index $(index) on a vector with $(n_items) item(s)");
|
|
|
- }
|
|
|
- else {
|
|
|
- return array_read(index);
|
|
|
- }
|
|
|
+ rw_lock.reader_lock();
|
|
|
+ if(index < 0) {
|
|
|
+ e = new IndexError.INDEX_EXCEEDS_LOWER_BOUNDS("Index is less than 0");
|
|
|
}
|
|
|
+ else if(index >= n_items) {
|
|
|
+ e = new IndexError.INDEX_EXCEEDS_UPPER_BOUNDS(@"Tried to access index $(index) on a vector with $(n_items) item(s)");
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ var item = array_read(index);
|
|
|
+ rw_lock.reader_unlock();
|
|
|
+ return item;
|
|
|
+ }
|
|
|
+ rw_lock.reader_unlock();
|
|
|
throw e;
|
|
|
}
|
|
|
|
|
|
public bool try_get(uint index, out T value) {
|
|
|
- lock(array) {
|
|
|
- if(index >= 0 && index < n_items) {
|
|
|
- value = array_read(index);
|
|
|
- return true;
|
|
|
- }
|
|
|
+ rw_lock.reader_lock();
|
|
|
+ if(index >= 0 && index < n_items) {
|
|
|
+ value = array_read(index);
|
|
|
+ rw_lock.reader_unlock();
|
|
|
+ return true;
|
|
|
}
|
|
|
+ rw_lock.reader_unlock();
|
|
|
value = null;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
public new void @set(int index, T value) throws IndexError {
|
|
|
IndexError? e = null;
|
|
|
- lock(array) {
|
|
|
- if(index < 0) {
|
|
|
- e = new IndexError.INDEX_EXCEEDS_LOWER_BOUNDS("Index is less than 0");
|
|
|
- }
|
|
|
- else if(index >= n_items) {
|
|
|
- e = new IndexError.INDEX_EXCEEDS_UPPER_BOUNDS(@"Tried to set index $(index) on a vector with $(n_items) item(s)");
|
|
|
- }
|
|
|
- else {
|
|
|
- array_write(index, value);
|
|
|
- return;
|
|
|
- }
|
|
|
+ rw_lock.writer_lock();
|
|
|
+ if(index < 0) {
|
|
|
+ e = new IndexError.INDEX_EXCEEDS_LOWER_BOUNDS("Index is less than 0");
|
|
|
+ }
|
|
|
+ else if(index >= n_items) {
|
|
|
+ e = new IndexError.INDEX_EXCEEDS_UPPER_BOUNDS(@"Tried to set index $(index) on a vector with $(n_items) item(s)");
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ array_write(index, value);
|
|
|
+ rw_lock.writer_unlock();
|
|
|
+ return;
|
|
|
}
|
|
|
+ rw_lock.writer_unlock();
|
|
|
throw e;
|
|
|
}
|
|
|
|
|
@@ -121,24 +134,24 @@ namespace Invercargill.DataStructures {
|
|
|
|
|
|
private IndexError? remove_internal(uint index) {
|
|
|
IndexError? e = null;
|
|
|
- lock(array) {
|
|
|
- if(index < 0) {
|
|
|
- e = new IndexError.INDEX_EXCEEDS_LOWER_BOUNDS("Index is less than 0");
|
|
|
- }
|
|
|
- else if(index >= n_items) {
|
|
|
- e = new IndexError.INDEX_EXCEEDS_UPPER_BOUNDS(@"Tried to set index $(index) on a vector with $(n_items) item(s)");
|
|
|
- }
|
|
|
- else {
|
|
|
- for(uint i = index; i < n_items; i++) {
|
|
|
- if(i+1 < n_items) {
|
|
|
- array_write(i, array_read(i+1));
|
|
|
- continue;
|
|
|
- }
|
|
|
- array[i] = null;
|
|
|
+ rw_lock.writer_lock();
|
|
|
+ if(index < 0) {
|
|
|
+ e = new IndexError.INDEX_EXCEEDS_LOWER_BOUNDS("Index is less than 0");
|
|
|
+ }
|
|
|
+ else if(index >= n_items) {
|
|
|
+ e = new IndexError.INDEX_EXCEEDS_UPPER_BOUNDS(@"Tried to set index $(index) on a vector with $(n_items) item(s)");
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ for(uint i = index; i < n_items; i++) {
|
|
|
+ if(i+1 < n_items) {
|
|
|
+ array_write(i, array_read(i+1));
|
|
|
+ continue;
|
|
|
}
|
|
|
- n_items --;
|
|
|
+ array[i] = null;
|
|
|
}
|
|
|
+ n_items --;
|
|
|
}
|
|
|
+ rw_lock.writer_unlock();
|
|
|
return e;
|
|
|
}
|
|
|
|
|
@@ -148,14 +161,16 @@ namespace Invercargill.DataStructures {
|
|
|
}
|
|
|
|
|
|
SequenceError? e = null;
|
|
|
- lock(array) {
|
|
|
- if(n_items == 0) {
|
|
|
- e = new SequenceError.NO_ELEMENTS("The sequence contains no elements");
|
|
|
- }
|
|
|
- else {
|
|
|
- return array_read(n_items -1);
|
|
|
- }
|
|
|
+ rw_lock.reader_lock();
|
|
|
+ if(n_items == 0) {
|
|
|
+ e = new SequenceError.NO_ELEMENTS("The sequence contains no elements");
|
|
|
}
|
|
|
+ else {
|
|
|
+ var item = array_read(n_items -1);
|
|
|
+ rw_lock.reader_unlock();
|
|
|
+ return item;
|
|
|
+ }
|
|
|
+ rw_lock.reader_unlock();
|
|
|
throw e;
|
|
|
}
|
|
|
|
|
@@ -164,13 +179,15 @@ namespace Invercargill.DataStructures {
|
|
|
return base.last_or_default((owned)predicate);
|
|
|
}
|
|
|
|
|
|
- lock(array) {
|
|
|
- if(n_items == 0) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- else {
|
|
|
- return array_read(n_items -1);
|
|
|
- }
|
|
|
+ rw_lock.reader_lock();
|
|
|
+ if(n_items == 0) {
|
|
|
+ rw_lock.reader_unlock();
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ var item = array_read(n_items -1);
|
|
|
+ rw_lock.reader_unlock();
|
|
|
+ return item;
|
|
|
}
|
|
|
}
|
|
|
|