Collections/RingCollection.cs
author moel.mich
Sat, 25 Jun 2011 14:46:28 +0000
changeset 304 16a86362c2ca
child 344 3145aadca3d2
permissions -rw-r--r--
Changed the maximum buffer size for double buffering of controls that isn't disposed after each draw call to the size of the screen. This should reduce the memory allocation and disposing on each sensor update. Also page faults are no longer increasing with this change.
moel@298
     1
/*
moel@298
     2
  
moel@298
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@298
     4
moel@298
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@298
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@298
     7
  the License. You may obtain a copy of the License at
moel@298
     8
 
moel@298
     9
  http://www.mozilla.org/MPL/
moel@298
    10
moel@298
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@298
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@298
    13
  for the specific language governing rights and limitations under the License.
moel@298
    14
moel@298
    15
  The Original Code is the Open Hardware Monitor code.
moel@298
    16
moel@298
    17
  The Initial Developer of the Original Code is 
moel@298
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@298
    19
  Portions created by the Initial Developer are Copyright (C) 2011
moel@298
    20
  the Initial Developer. All Rights Reserved.
moel@298
    21
moel@298
    22
  Contributor(s):
moel@298
    23
moel@298
    24
  Alternatively, the contents of this file may be used under the terms of
moel@298
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@298
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@298
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@298
    28
  of those above. If you wish to allow use of your version of this file only
moel@298
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@298
    30
  use your version of this file under the terms of the MPL, indicate your
moel@298
    31
  decision by deleting the provisions above and replace them with the notice
moel@298
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@298
    33
  the provisions above, a recipient may use your version of this file under
moel@298
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@298
    35
 
moel@298
    36
*/
moel@298
    37
moel@298
    38
using System;
moel@298
    39
using System.Collections;
moel@298
    40
using System.Collections.Generic;
moel@298
    41
moel@298
    42
namespace OpenHardwareMonitor.Collections {
moel@298
    43
  public class RingCollection<T> : IEnumerable<T> {
moel@298
    44
moel@298
    45
    private T[] array;
moel@298
    46
moel@298
    47
    // first item of collection
moel@298
    48
    private int head;
moel@298
    49
moel@298
    50
    // index after the last item of the collection
moel@298
    51
    private int tail;
moel@298
    52
moel@298
    53
    // number of items in the collection
moel@298
    54
    private int size;
moel@298
    55
moel@298
    56
    public RingCollection() : this(0) { }
moel@298
    57
moel@298
    58
    public RingCollection(int capacity) {
moel@298
    59
      if (capacity < 0)
moel@298
    60
        throw new ArgumentOutOfRangeException("capacity");
moel@298
    61
      this.array = new T[capacity];
moel@298
    62
      this.head = 0; 
moel@298
    63
      this.tail = 0;
moel@298
    64
      this.size = 0;
moel@298
    65
    }
moel@298
    66
moel@298
    67
    public int Capacity {
moel@298
    68
      get {
moel@298
    69
        return array.Length;
moel@298
    70
      }
moel@298
    71
      set {
moel@298
    72
        T[] newArray = new T[value];
moel@298
    73
        if (size > 0) {
moel@298
    74
          if (head < tail) {
moel@298
    75
            Array.Copy(array, head, newArray, 0, size);
moel@298
    76
          } else {
moel@298
    77
            Array.Copy(array, head, newArray, 0, array.Length - head);
moel@298
    78
            Array.Copy(array, 0, newArray, array.Length - head, tail);
moel@298
    79
          }
moel@298
    80
        }
moel@298
    81
        this.array = newArray;
moel@298
    82
        this.head = 0;
moel@298
    83
        this.tail = size == value ? 0 : size;
moel@298
    84
      }
moel@298
    85
    }
moel@298
    86
moel@298
    87
    public void Clear() {
moel@298
    88
      
moel@298
    89
      // remove potential references 
moel@298
    90
      if (head < tail) {
moel@298
    91
        Array.Clear(array, head, size);
moel@298
    92
      } else {
moel@298
    93
        Array.Clear(array, 0, tail);
moel@298
    94
        Array.Clear(array, head, array.Length - head);
moel@298
    95
      }
moel@298
    96
moel@298
    97
      this.head = 0;
moel@298
    98
      this.tail = 0;
moel@298
    99
      this.size = 0;
moel@298
   100
    }
moel@298
   101
moel@298
   102
    public void Append(T item) {
moel@298
   103
      if (size == array.Length) {
moel@298
   104
        int newCapacity = array.Length * 3 / 2;
moel@298
   105
        if (newCapacity < array.Length + 8)
moel@298
   106
          newCapacity = array.Length + 8;
moel@298
   107
        Capacity = newCapacity;
moel@298
   108
      }
moel@298
   109
moel@298
   110
      array[tail] = item;
moel@298
   111
      tail = tail + 1 == array.Length ? 0 : tail + 1;
moel@298
   112
      size++;
moel@298
   113
    }
moel@298
   114
moel@298
   115
    public T Remove() {
moel@298
   116
      if (size == 0)
moel@298
   117
        throw new InvalidOperationException();
moel@298
   118
moel@298
   119
      T result = array[head];
moel@298
   120
      array[head] = default(T);
moel@298
   121
      head = head + 1 == array.Length ? 0 : head + 1;
moel@298
   122
      size--;
moel@298
   123
moel@298
   124
      return result;
moel@298
   125
    }
moel@298
   126
moel@298
   127
    public int Count {
moel@298
   128
      get {
moel@298
   129
        return size;
moel@298
   130
      }
moel@298
   131
    }
moel@298
   132
moel@298
   133
    public T this[int index] {
moel@298
   134
      get {
moel@298
   135
        if (index < 0 || index >= size)
moel@298
   136
          throw new IndexOutOfRangeException();
moel@298
   137
        int i = head + index;
moel@298
   138
        if (i >= array.Length)
moel@298
   139
          i -= array.Length;
moel@298
   140
        return array[i];
moel@298
   141
      }
moel@298
   142
      set {
moel@298
   143
        if (index < 0 || index >= size)
moel@298
   144
          throw new IndexOutOfRangeException();
moel@298
   145
        int i = head + index;
moel@298
   146
        if (i >= array.Length)
moel@298
   147
          i -= array.Length;
moel@298
   148
        array[i] = value;
moel@298
   149
      }
moel@298
   150
    }
moel@298
   151
moel@298
   152
    public T First {
moel@298
   153
      get {
moel@298
   154
        if (size == 0)
moel@298
   155
          throw new InvalidOperationException();
moel@298
   156
        return array[head];
moel@298
   157
      }
moel@298
   158
      set {
moel@298
   159
        if (size == 0)
moel@298
   160
          throw new InvalidOperationException();
moel@298
   161
        array[head] = value;
moel@298
   162
      }
moel@298
   163
    }
moel@298
   164
moel@298
   165
    public T Last {
moel@298
   166
      get {
moel@298
   167
        if (size == 0)
moel@298
   168
          throw new InvalidOperationException();
moel@298
   169
        return array[tail == 0 ? array.Length - 1 : tail - 1];
moel@298
   170
      }
moel@298
   171
      set {
moel@298
   172
        if (size == 0)
moel@298
   173
          throw new InvalidOperationException();
moel@298
   174
        array[tail == 0 ? array.Length - 1 : tail - 1] = value;
moel@298
   175
      }
moel@298
   176
    }
moel@298
   177
moel@298
   178
    IEnumerator<T> IEnumerable<T>.GetEnumerator() {
moel@298
   179
      return new RingCollection<T>.Enumerator(this);
moel@298
   180
    }
moel@298
   181
moel@298
   182
    IEnumerator IEnumerable.GetEnumerator() {
moel@298
   183
      return new RingCollection<T>.Enumerator(this);
moel@298
   184
    }
moel@298
   185
moel@298
   186
    private struct Enumerator : IEnumerator<T>, IEnumerator {
moel@298
   187
moel@298
   188
      private RingCollection<T> collection;
moel@298
   189
      private int index;
moel@298
   190
moel@298
   191
      public Enumerator(RingCollection<T> collection) {
moel@298
   192
        this.collection = collection;
moel@298
   193
        this.index = -1;
moel@298
   194
      }
moel@298
   195
moel@298
   196
      public void Dispose() {
moel@298
   197
        this.index = -2;
moel@298
   198
      }
moel@298
   199
moel@298
   200
      public void Reset() {
moel@298
   201
        this.index = -1;
moel@298
   202
      }
moel@298
   203
moel@298
   204
      public T Current {
moel@298
   205
        get {
moel@298
   206
          if (index < 0)
moel@298
   207
            throw new InvalidOperationException();
moel@298
   208
          return collection[index];
moel@298
   209
        }
moel@298
   210
      }
moel@298
   211
moel@298
   212
      object IEnumerator.Current {
moel@298
   213
        get {
moel@298
   214
          if (index < 0)
moel@298
   215
            throw new InvalidOperationException();
moel@298
   216
          return collection[index];
moel@298
   217
        }
moel@298
   218
      }
moel@298
   219
moel@298
   220
      public bool MoveNext() {
moel@298
   221
        if (index == -2)
moel@298
   222
          return false;
moel@298
   223
moel@298
   224
        index++;
moel@298
   225
moel@298
   226
        if (index == collection.size) {
moel@298
   227
          index = -2;
moel@298
   228
          return false;
moel@298
   229
        }
moel@298
   230
moel@298
   231
        return true;
moel@298
   232
      }
moel@298
   233
    }
moel@298
   234
  }
moel@298
   235
}