Exemple #1
0
        void PerformMerge(GLPoolResourceNode left, GLPoolResourceTicket ticket, GLPoolResourceNode right)
        {
            bool leftMerge  = left != null && (ticket.First == (left.Last + 1));
            bool rightMerge = right != null && ((ticket.Last + 1) == right.First);

            ValidateTicket(ticket);
            ValidateLocation(left, ticket, right);

            if (leftMerge && rightMerge)
            {
                Debug.Assert(ReferenceEquals(left.Next, right));

                var finalCount = left.Count + ticket.Count + right.Count;
                Debug.Assert(finalCount == (right.Last - left.First + 1));

                left.Count = finalCount;
                left.Last  = right.Last;
                left.Next  = right.Next;
            }
            else if (leftMerge)
            {
                var finalCount = left.Count + ticket.Count;
                Debug.Assert(finalCount == (ticket.Last - left.First + 1));

                left.Count = finalCount;
                left.Last  = ticket.Last;
            }
            else if (rightMerge)
            {
                var finalCount = right.Count + ticket.Count;
                Debug.Assert(finalCount == (right.Last - ticket.First + 1));

                right.Count = finalCount;
                right.First = ticket.First;
            }
            else
            {
                var inBetween = new GLPoolResourceNode
                {
                    First = ticket.First,
                    Last  = ticket.Last,
                    Count = ticket.Count,
                };

                // REPLACE HEAD
                if (left == null)
                {
                    Debug.Assert(ReferenceEquals(right, Head));
                    inBetween.Next = Head;
                    Head           = inBetween;
                }
                else
                {
                    left.Next      = inBetween;
                    inBetween.Next = right;
                }
            }
        }
Exemple #2
0
 void ValidateLocation(GLPoolResourceNode previous, GLPoolResourceTicket ticket, GLPoolResourceNode current)
 {
     if (previous != null && previous.Last >= ticket.First)
     {
         throw new InvalidOperationException();
     }
     if (current != null && current.First <= ticket.Last)
     {
         throw new InvalidOperationException();
     }
 }
Exemple #3
0
        public bool Free(GLPoolResourceTicket ticket)
        {
            if (Head == null)
            {
                Head = new GLPoolResourceNode
                {
                    First = ticket.First,
                    Last  = ticket.Last,
                    Count = ticket.Count,
                };
                return(true);
            }
            else
            {
                GLPoolResourceNode previous = null;
                GLPoolResourceNode current  = Head;

                while (current != null)
                {
                    // SAME TICKET RANGE RECOVERY
                    if (ticket.First == current.First)
                    {
                        // DO NOTHING IF INSIDE RANGE
                        if (ticket.Last <= current.Last && ticket.Count <= current.Count)
                        {
                            return(true);
                        }
                        else
                        {
                            AdjustTicketsSpan(ticket, current);
                            return(true);
                        }
                    }
                    // GAP-BASED SLOT RECOVERY
                    else if (ticket.First < current.First)
                    {
                        PerformMerge(previous, ticket, current);
                        return(true);
                    }

                    previous = current;
                    current  = current.Next;
                }

                // At end of linked list
                PerformMerge(previous, ticket, null);
                return(true);
            }
        }
Exemple #4
0
        public void RightMerge()
        {
            GLPoolResourceTicket ticket_0;
            var initialCheck = PoolResource.Allocate(NO_OF_ITEMS, out ticket_0);

            Assert.IsTrue(initialCheck);
            Assert.IsNull(PoolResource.Head);

            {
                var ticket_1 = new GLPoolResourceTicket
                {
                    First = 2,
                    Last  = 2,
                    Count = 1,
                };

                var actual_1 = PoolResource.Free(ticket_1);

                Assert.IsTrue(actual_1);
                var head = PoolResource.Head;
                Assert.IsNotNull(head);
                Assert.IsNull(head.Next);

                Assert.AreEqual(ticket_1.First, head.First);
                Assert.AreEqual(ticket_1.Last, head.Last);
                Assert.AreEqual(ticket_1.Count, head.Count);
            }

            {
                var ticket_2 = new GLPoolResourceTicket
                {
                    First = 1,
                    Last  = 1,
                    Count = 1,
                };

                var actual_2 = PoolResource.Free(ticket_2);

                Assert.IsTrue(actual_2);
                var head = PoolResource.Head;
                Assert.IsNotNull(head);
                Assert.IsNull(head.Next);

                Assert.AreEqual(1, head.First);
                Assert.AreEqual(2, head.Last);
                Assert.AreEqual(2, head.Count);
            }
        }
Exemple #5
0
        public void TwoNodesAppended()
        {
            GLPoolResourceTicket ticket_0;
            var initialCheck = PoolResource.Allocate(NO_OF_ITEMS, out ticket_0);

            Assert.IsTrue(initialCheck);
            Assert.IsNull(PoolResource.Head);

            var ticket_1 = new GLPoolResourceTicket
            {
                First = 0,
                Last  = 0,
                Count = 1,
            };

            var actual_1 = PoolResource.Free(ticket_1);

            Assert.IsTrue(actual_1);
            var head = PoolResource.Head;

            Assert.IsNotNull(head);
            Assert.IsNull(head.Next);

            Assert.AreEqual(ticket_1.First, head.First);
            Assert.AreEqual(ticket_1.Last, head.Last);
            Assert.AreEqual(ticket_1.Count, head.Count);

            var ticket_2 = new GLPoolResourceTicket
            {
                First = 2,
                Last  = 2,
                Count = 1,
            };

            var actual_2 = PoolResource.Free(ticket_2);

            Assert.IsTrue(actual_2);
            head = PoolResource.Head;
            Assert.IsNotNull(head);

            var next = head.Next;

            Assert.IsNotNull(next);
            Assert.AreEqual(ticket_2.First, next.First);
            Assert.AreEqual(ticket_2.Last, next.Last);
            Assert.AreEqual(ticket_2.Count, next.Count);
        }
Exemple #6
0
        public void SpamTest_OutsideRange_0()
        {
            GLPoolResourceTicket ticket_0;
            var initialCheck = PoolResource.Allocate(NO_OF_ITEMS, out ticket_0);

            Assert.IsTrue(initialCheck);
            Assert.IsNull(PoolResource.Head);

            var ticket_1 = new GLPoolResourceTicket
            {
                First = 0,
                Last  = 2,
                Count = 3,
            };

            {
                var actual = PoolResource.Free(ticket_1);

                Assert.IsTrue(actual);
                var head = PoolResource.Head;
                Assert.IsNotNull(head);
                Assert.IsNull(head.Next);
                Assert.AreEqual(ticket_1.First, head.First);
                Assert.AreEqual(ticket_1.Last, head.Last);
                Assert.AreEqual(ticket_1.Count, head.Count);
            }

            {
                var ticket_2 = new GLPoolResourceTicket
                {
                    First = 0,
                    Last  = 3,
                    Count = 4,
                };

                var actual = PoolResource.Free(ticket_2);

                Assert.IsTrue(actual);
                var head = PoolResource.Head;
                Assert.IsNotNull(head);
                Assert.IsNull(head.Next);

                Assert.AreEqual(ticket_2.First, head.First);
                Assert.AreEqual(ticket_2.Last, head.Last);
                Assert.AreEqual(ticket_2.Count, head.Count);
            }
        }
Exemple #7
0
 void ValidateTicket(GLPoolResourceTicket ticket)
 {
     if ((ticket.First + ticket.Count) > Count)
     {
         throw new InvalidOperationException();
     }
     if (ticket.Count == 0)
     {
         throw new InvalidOperationException();
     }
     if ((ticket.First + ticket.Count - 1) != ticket.Last)
     {
         throw new InvalidOperationException();
     }
     if (ticket.Last > Count)
     {
         throw new InvalidOperationException();
     }
 }
Exemple #8
0
        void AdjustTicketsSpan(GLPoolResourceTicket ticket, GLPoolResourceNode parent)
        {
            GLPoolResourceNode lastNode = null;
            bool intercepts             = false;

            GLPoolResourceNode current = parent.Next;

            while (current != null)
            {
                lastNode = current;
                if (current.Last > ticket.Last)
                {
                    intercepts = (current.First <= ticket.Last);
                    break;
                }

                // remove from the list
                parent.Next = current.Next;
                current     = current.Next;
            }

            parent.Last  = (lastNode != null && intercepts) ? lastNode.Last : ticket.Last;
            parent.Count = parent.Last - parent.First + 1;

            if (current == null)
            {
                // ITERATED THRU THEN POINT TO END
                parent.Next = null;
            }
            else if (lastNode != null && intercepts)
            {
                // INCLUDE LAST NODE
                parent.Next = lastNode.Next;
            }
            else
            {
                // OUTSIDE OF LAST NODE
                parent.Next = lastNode;
            }
        }
Exemple #9
0
 public bool Free(GLPoolResourceTicket ticket)
 {
     throw new NotImplementedException();
 }
Exemple #10
0
 public bool Allocate(uint request, out GLPoolResourceTicket ticket)
 {
     throw new NotImplementedException();
 }
Exemple #11
0
        public void SpamTest_OutsideRange_2()
        {
            GLPoolResourceTicket ticket_0;
            var initialCheck = PoolResource.Allocate(NO_OF_ITEMS, out ticket_0);

            Assert.IsTrue(initialCheck);
            Assert.IsNull(PoolResource.Head);

            var ticket_1 = new GLPoolResourceTicket
            {
                First = 0,
                Last  = 0,
                Count = 1,
            };

            {
                var actual = PoolResource.Free(ticket_1);

                Assert.IsTrue(actual);
                var head = PoolResource.Head;
                Assert.IsNotNull(head);
                Assert.IsNull(head.Next);

                Assert.AreEqual(ticket_1.First, head.First);
                Assert.AreEqual(ticket_1.Last, head.Last);
                Assert.AreEqual(ticket_1.Count, head.Count);
            }

            var ticket_2 = new GLPoolResourceTicket
            {
                First = 2,
                Last  = 3,
                Count = 2,
            };

            {
                var actual = PoolResource.Free(ticket_2);

                Assert.IsTrue(actual);
                var head = PoolResource.Head;
                Assert.IsNotNull(head);

                Assert.AreEqual(ticket_1.First, head.First);
                Assert.AreEqual(ticket_1.Last, head.Last);
                Assert.AreEqual(ticket_1.Count, head.Count);

                var next_0 = head.Next;
                Assert.IsNotNull(next_0);

                Assert.AreEqual(ticket_2.First, next_0.First);
                Assert.AreEqual(ticket_2.Last, next_0.Last);
                Assert.AreEqual(ticket_2.Count, next_0.Count);
            }

            var ticket_3 = new GLPoolResourceTicket
            {
                First = 5,
                Last  = 5,
                Count = 1,
            };

            {
                var actual = PoolResource.Free(ticket_3);

                Assert.IsTrue(actual);
                var head = PoolResource.Head;
                Assert.IsNotNull(head);

                Assert.AreEqual(ticket_1.First, head.First);
                Assert.AreEqual(ticket_1.Last, head.Last);
                Assert.AreEqual(ticket_1.Count, head.Count);

                var next_0 = head.Next;
                Assert.IsNotNull(next_0);

                Assert.AreEqual(ticket_2.First, next_0.First);
                Assert.AreEqual(ticket_2.Last, next_0.Last);
                Assert.AreEqual(ticket_2.Count, next_0.Count);

                var next_1 = next_0.Next;
                Assert.IsNotNull(next_1);

                Assert.AreEqual(ticket_3.First, next_1.First);
                Assert.AreEqual(ticket_3.Last, next_1.Last);
                Assert.AreEqual(ticket_3.Count, next_1.Count);
            }

            {
                var ticket_4 = new GLPoolResourceTicket
                {
                    First = 0,
                    Last  = 2,
                    Count = 3,
                };

                var actual = PoolResource.Free(ticket_4);

                Assert.IsTrue(actual);
                var head = PoolResource.Head;
                Assert.IsNotNull(head);

                Assert.AreEqual(0, head.First);
                Assert.AreEqual(3, head.Last);
                Assert.AreEqual(4, head.Count);

                var next = head.Next;
                Assert.IsNotNull(next);

                Assert.AreEqual(ticket_3.First, next.First);
                Assert.AreEqual(ticket_3.Last, next.Last);
                Assert.AreEqual(ticket_3.Count, next.Count);
            }
        }
Exemple #12
0
        public bool Allocate(uint request, out GLPoolResourceTicket range)
        {
            if (request == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(request) + " must be greater than 0");
            }

            {
                // FIRST LOOP : SCAN FOR EXACT MATCHES
                GLPoolResourceNode current  = Head;
                GLPoolResourceNode previous = null;
                while (current != null)
                {
                    if (current.Count == request)
                    {
                        range = new GLPoolResourceTicket
                        {
                            First = current.First,
                            Last  = current.Last,
                            Count = current.Count,
                        };

                        // remove current from linked list
                        if (previous != null)
                        {
                            previous.Next = current.Next;
                        }

                        // remove from head
                        if (ReferenceEquals(Head, current))
                        {
                            Head = current.Next;
                        }

                        return(true);
                    }
                    previous = current;
                    current  = current.Next;
                }
            }

            {
                // SECOND LOOP : FIND FIRST BLOCK LARGE ENOUGH AND SPLIT
                GLPoolResourceNode current = Head;
                while (current != null)
                {
                    if (current.Count > request)
                    {
                        range = new GLPoolResourceTicket
                        {
                            First = current.First,
                            Last  = request + current.First - 1,
                            Count = request,
                        };

                        // adjust current
                        current.First += request;
                        current.Count -= request;
                        return(true);
                    }
                    current = current.Next;
                }
            }

            // NOT FOUND
            range = null;
            return(false);
        }