Explorar o código

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

Billy Barrow hai 3 semanas
pai
achega
11c0d74395
Modificáronse 2 ficheiros con 137 adicións e 83 borrados
  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 int n_items = 0;
         private SafeReadFunc<T>? safe_read;
         private SafeReadFunc<T>? safe_read;
         private SafeWriteFunc<T>? safe_write;
         private SafeWriteFunc<T>? safe_write;
+        private RWLock rw_lock;
 
 
         private const int INITIAL_SIZE = 2;
         private const int INITIAL_SIZE = 2;
 
 
         public Vector() {
         public Vector() {
+            rw_lock = RWLock();
             array = new T[INITIAL_SIZE];
             array = new T[INITIAL_SIZE];
             safe_read = get_safe_read_function_for<T>();
             safe_read = get_safe_read_function_for<T>();
             safe_write = get_safe_write_function_for<T>();
             safe_write = get_safe_write_function_for<T>();
@@ -19,6 +21,13 @@ namespace Invercargill.DataStructures {
             return n_items;
             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() {
         public override EnumerableInfo get_info() {
             return new EnumerableInfo.infer_ultimate (this, EnumerableCategory.IN_MEMORY);
             return new EnumerableInfo.infer_ultimate (this, EnumerableCategory.IN_MEMORY);
         }
         }
@@ -28,81 +37,85 @@ namespace Invercargill.DataStructures {
         }
         }
 
 
         public override T[] to_array () {
         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) {
         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) {
         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 {
         public new T @get(uint index) throws IndexError {
             IndexError? e = null;
             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;
             throw e;
         }
         }
 
 
         public bool try_get(uint index, out T value) {
         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;
             value = null;
             return false;
             return false;
         }
         }
 
 
         public new void @set(int index, T value) throws IndexError {
         public new void @set(int index, T value) throws IndexError {
             IndexError? e = null;
             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;
             throw e;
         }
         }
 
 
@@ -121,24 +134,24 @@ namespace Invercargill.DataStructures {
 
 
         private IndexError? remove_internal(uint index) {
         private IndexError? remove_internal(uint index) {
             IndexError? e = null;
             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;
             return e;
         }
         }
 
 
@@ -148,14 +161,16 @@ namespace Invercargill.DataStructures {
             }
             }
 
 
             SequenceError? e = null;
             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;
             throw e;
         }
         }
 
 
@@ -164,13 +179,15 @@ namespace Invercargill.DataStructures {
                 return base.last_or_default((owned)predicate);
                 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_PROGRAM = "\x1b[97m";
         private const string COLOUR_CLASS = "\x1b[92m";
         private const string COLOUR_CLASS = "\x1b[92m";
         private const string COLOUR_CATEGORY = "\x1b[96m";
         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) {
         private static string format_colour(string colour, string message) {
             return colour + message + COLOUR_RESET;
             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"));
             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 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) {
         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 += "  ";
             for(int i = 0; i < indents; i++) indent += "  ";
             var has_sources = info.sources.any();
             var has_sources = info.sources.any();
             var known_count = info.count != null;
             var known_count = info.count != null;
+            var interfaces = notable_interfaces(info.enumerable_type);
             output(
             output(
                 format_colour(COLOUR_DEBUG, indent) +
                 format_colour(COLOUR_DEBUG, indent) +
                 format_colour(COLOUR_CATEGORY, info.category.to_string()) +
                 format_colour(COLOUR_CATEGORY, info.category.to_string()) +
                 format_colour(COLOUR_DEBUG, " Enumerable ") +
                 format_colour(COLOUR_DEBUG, " Enumerable ") +
                 format_colour(COLOUR_CLASS, info.enumerable_type.name()) +
                 format_colour(COLOUR_CLASS, info.enumerable_type.name()) +
                 format_colour(COLOUR_DEBUG, " with ") +
                 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_CLASS, info.element_type.name() ?? "UNKNOWN") +
                 format_colour(COLOUR_DEBUG, info.count == 1 ? " element" : " elements") +
                 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"
                 "\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> {
     internal class TraceEnumerable<T> : Enumerable<T> {
@@ -102,6 +137,7 @@ namespace Invercargill {
         private string additional_message;
         private string additional_message;
         private DebugOutputDelegate? output_func;
         private DebugOutputDelegate? output_func;
         private bool formatting;
         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) {
         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;
             this.input = (owned)input;
@@ -130,7 +166,8 @@ namespace Invercargill {
                 () => tracker.has_next(),
                 () => tracker.has_next(),
                 () => {
                 () => {
                     var item = tracker.get_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;
                     return item;
                 }
                 }
             );
             );