Пример #1
0
        public bool Remove(int key, Element elem)
        {
            if (elem == null)
            {
                throw new Exception("Invalid element to remove");
            }

            RegionLock.EnterWriteLock();
            try
            {
                // get region to remove from
                GetRegion(elem.X, elem.Y, out int row, out int column);

                // check if this is an item that would span multiple regions
                if (IsOversized(elem) || IsOutofRange(row, column))
                {
                    return(Oversized.Remove(key));
                }

                // add to the region specified (or span multiple regions)
                return(Regions[row][column].Remove(key));
            }
            finally
            {
                RegionLock.ExitWriteLock();
            }
        }
Пример #2
0
        public void Add(int key, Element elem)
        {
            if (elem == null)
            {
                throw new Exception("Invalid element to add");
            }

            RegionLock.EnterWriteLock();
            try
            {
                // get region to insert into
                GetRegion(elem.X, elem.Y, out int row, out int column);

                // check if this is an item that would span multiple regions
                if (IsOversized(elem) || IsOutofRange(row, column))
                {
                    Oversized.Add(key, elem);
                    return;
                }

                // add to the region specified (or span multiple regions)
                Regions[row][column].Add(key, elem);
            }
            finally
            {
                RegionLock.ExitWriteLock();
            }
        }
Пример #3
0
        public IEnumerable <Element> Values(float x1, float y1, float x2, float y2)
        {
            RegionLock.EnterReadLock();
            try
            {
                // get the starting row,col and ending row,col
                GetRegion(x1, y1, out int r1, out int c1, validate: false);
                GetRegion(x2, y2, out int r2, out int c2, validate: false);

                // assuming we start to 0,0 in the upper left and corner and increase right and down
                // ensure r1,c1 if the upper left and corner
                if (r2 < r1)
                {
                    // swap
                    var tmp = r1;
                    r1 = r2;
                    r2 = tmp;
                }
                if (c2 < c1)
                {
                    var tmp = c1;
                    c1 = c2;
                    c2 = tmp;
                }

                // expand the region
                r1 -= 1; c1 -= 1;
                r2 += 1; c2 += 1;

                // hold the lock for the duration of this call
                for (int r = (r1 >= 0 ? r1 : 0); r <= r2 && r < Regions.Length; r++)
                {
                    for (int c = (c1 >= 0 ? c1 : 0); c <= c2 && c < Regions[r].Length; c++)
                    {
                        if (Regions[r][c].Count == 0)
                        {
                            continue;
                        }
                        foreach (var elem in Regions[r][c].Values)
                        {
                            yield return(elem);
                        }
                    }
                }

                // always return the oversized items
                foreach (var elem in Oversized.Values)
                {
                    yield return(elem);
                }
            }
            finally
            {
                RegionLock.ExitReadLock();
            }
        }
Пример #4
0
        public Region GetRegion(Element elem)
        {
            if (elem == null)
            {
                throw new Exception("Invalid element to get region");
            }

            RegionLock.EnterReadLock();
            try
            {
                if (IsOversized(elem))
                {
                    return(new Region(-1, -1));
                }

                GetRegion(elem.X, elem.Y, out int row, out int column);
                return(new Region(row, column));
            }
            finally
            {
                RegionLock.ExitReadLock();
            }
        }
Пример #5
0
        public void Move(int key, Region src, Region dst)
        {
            RegionLock.EnterWriteLock();
            try
            {
                // get element (either in oversized or a Region)
                Element elem;
                if (Oversized.TryGetValue(key, out elem))
                {
                    // if elment is Oversized or the dst is out of range, keep it here
                    if (IsOversized(elem))
                    {
                        return;
                    }

                    // assert that this element is currently out of range
                    if (!IsOutofRange(src))
                    {
                        throw new Exception("Invalid state in internal datastructures");
                    }

                    // if it remains out of range, keep it here
                    if (IsOutofRange(dst))
                    {
                        return;
                    }

                    // remove it from the oversized, as it is moving to a region
                    if (!Oversized.Remove(key))
                    {
                        throw new Exception("Failed to remove this element");
                    }
                }
                else
                {
                    // find it and remove it
                    if (!Regions[src.Row][src.Col].TryGetValue(key, out elem))
                    {
                        throw new Exception("Failed to location the element to move");
                    }
                    if (!Regions[src.Row][src.Col].Remove(key))
                    {
                        throw new Exception("Failed to remove this element");
                    }
                }

                // add element (either oversized or a Region)
                if (IsOutofRange(dst))
                {
                    Oversized.Add(key, elem);
                }
                else
                {
                    Regions[dst.Row][dst.Col].Add(key, elem);
                }
            }
            finally
            {
                RegionLock.ExitWriteLock();
            }
        }