فهرست منبع

Change vector to use RWLock and add count override back. Improvements to debug formatting

Billy Barrow 11 ماه پیش
والد
کامیت
11c0d74395
2فایلهای تغییر یافته به همراه137 افزوده شده و 83 حذف شده
  1. 94 77
      src/lib/DataStructures/Vector.vala
  2. 43 6
      src/lib/Debug.vala

+ 94 - 77
src/lib/DataStructures/Vector.vala

@@ -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;
             }
         }
 

+ 43 - 6
src/lib/Debug.vala

@@ -7,6 +7,8 @@ namespace Invercargill {
         private const string COLOUR_PROGRAM = "\x1b[97m";
         private const string COLOUR_CLASS = "\x1b[92m";
         private const string COLOUR_CATEGORY = "\x1b[96m";
+        private const string COLOUR_NUMBER = "\x1b[93m";
+        private const string COLOUR_INTERFACE = "\x1b[95m";
 
         private static string format_colour(string colour, string message) {
             return colour + message + COLOUR_RESET;
@@ -57,10 +59,10 @@ namespace Invercargill {
             output(format_colour(COLOUR_DEBUG, "Trace registered, output will be printed when the enumerable is iterated.\n"));
         }
 
-        public static void print_trace(string message, string additional_message = "", DebugOutputDelegate? output_func = null, bool formatting = true) {
+        public static void print_trace(uint count, string message, string additional_message = "", DebugOutputDelegate? output_func = null, bool formatting = true) {
             var output = get_delegate(output_func, formatting);
-            var seperator = (additional_message != null && additional_message.length > 0) ? ": " : "";
-            output(format_colour(COLOUR_DEBUG, "[TRACE] ") + format_colour(COLOUR_PROGRAM, additional_message) + format_colour(COLOUR_DEBUG, seperator) + format_colour(COLOUR_PROGRAM, message) + "\n");
+            var formatted_additional = additional_message.length > 0 ? additional_message + " " : "";
+            output(format_colour(COLOUR_DEBUG, "[TRACE] ") + format_colour(COLOUR_PROGRAM, formatted_additional) + format_colour(COLOUR_NUMBER, @"$count") + format_colour(COLOUR_DEBUG, ":\t") + format_colour(COLOUR_PROGRAM, message) + "\n");
         }
 
         public static void print_trace_debug_message(string message, string additional_message = "", DebugOutputDelegate? output_func = null, bool formatting = true) {
@@ -76,16 +78,19 @@ namespace Invercargill {
             for(int i = 0; i < indents; i++) indent += "  ";
             var has_sources = info.sources.any();
             var known_count = info.count != null;
+            var interfaces = notable_interfaces(info.enumerable_type);
             output(
                 format_colour(COLOUR_DEBUG, indent) +
                 format_colour(COLOUR_CATEGORY, info.category.to_string()) +
                 format_colour(COLOUR_DEBUG, " Enumerable ") +
                 format_colour(COLOUR_CLASS, info.enumerable_type.name()) +
                 format_colour(COLOUR_DEBUG, " with ") +
-                (known_count ? format_colour(COLOUR_PROGRAM, @"$(info.count) ") : "") +
+                (known_count ? format_colour(COLOUR_NUMBER, @"$(info.count) ") : "") +
                 format_colour(COLOUR_CLASS, info.element_type.name() ?? "UNKNOWN") +
                 format_colour(COLOUR_DEBUG, info.count == 1 ? " element" : " elements") +
-                (has_sources ? format_colour(COLOUR_DEBUG, ", sources from:") : ".") +
+                (interfaces.any() ? format_colour(COLOUR_DEBUG, " conforms to ") : "") +
+                interfaces.to_string(s => format_colour(COLOUR_INTERFACE, s), format_colour(COLOUR_DEBUG, ", ")) +
+                (has_sources ? format_colour(COLOUR_DEBUG, ", sources from:") : format_colour(COLOUR_DEBUG, ".")) +
                 "\n"
             );
 
@@ -94,6 +99,36 @@ namespace Invercargill {
 
         }
 
+        private static Enumerable<string> notable_interfaces(Type type) {
+            var names = new DataStructures.Vector<string>();
+            if(type.is_a(typeof(Lot))) {
+                names.add("Lot");
+            }
+            if(type.is_a(typeof(ReadOnlyAddressable))) {
+                names.add("Addressable");
+            }
+            if(type.is_a(typeof(ReadOnlyAssociative))) {
+                names.add("Associative");
+            }
+            if(type.is_a(typeof(ReadOnlyCollection))) {
+                names.add("Collection");
+            }
+            if(type.is_a(typeof(ReadOnlySet))) {
+                names.add("Collection");
+            }
+            if(type.is_a(typeof(Elements))) {
+                names.add("Elements");
+            }
+            if(type.is_a(typeof(Properties))) {
+                names.add("Elements");
+            }
+            if(type.is_a(typeof(Promotion))) {
+                names.add("Promotion");
+            }
+
+            return names;
+        }
+
     }
 
     internal class TraceEnumerable<T> : Enumerable<T> {
@@ -102,6 +137,7 @@ namespace Invercargill {
         private string additional_message;
         private DebugOutputDelegate? output_func;
         private bool formatting;
+        private uint counter = 0;
 
         public TraceEnumerable(owned Enumerable<T> input, EnumerableInfo info, owned TransformDelegate<T, string> stringifier, string additional_message = "", owned DebugOutputDelegate? output_func, bool formatting) {
             this.input = (owned)input;
@@ -130,7 +166,8 @@ namespace Invercargill {
                 () => tracker.has_next(),
                 () => {
                     var item = tracker.get_next();
-                    DebugPrinter.print_trace(stringifier(item), additional_message, output_func, formatting);
+                    DebugPrinter.print_trace(counter, stringifier(item), additional_message, output_func, formatting);
+                    counter++;
                     return item;
                 }
             );