示例#1
0
        public void DisposeHandles()
        {
            // Ensure that disposed handles correctly remove their virtual and physical regions.

            RegionHandle handle = _tracking.BeginTracking(0, PageSize);

            handle.Reprotect();

            Assert.AreEqual((1, 1), _tracking.GetRegionCounts());

            handle.Dispose();

            Assert.AreEqual((0, 0), _tracking.GetRegionCounts());

            // Two handles, small entirely contains big.
            // We expect there to be three regions after creating both, one for the small region and two covering the big one around it.
            // Regions are always split to avoid overlapping, which is why there are three instead of two.

            RegionHandle handleSmall = _tracking.BeginTracking(PageSize, PageSize);
            RegionHandle handleBig   = _tracking.BeginTracking(0, PageSize * 4);

            Assert.AreEqual((3, 3), _tracking.GetRegionCounts());

            // After disposing the big region, only the small one will remain.
            handleBig.Dispose();

            Assert.AreEqual((1, 1), _tracking.GetRegionCounts());

            handleSmall.Dispose();

            Assert.AreEqual((0, 0), _tracking.GetRegionCounts());
        }
示例#2
0
        public void SingleRegion()
        {
            RegionHandle handle = _tracking.BeginTracking(0, PageSize);

            (ulong address, ulong size)? readTrackingTriggered = null;
            handle.RegisterAction((address, size) =>
            {
                readTrackingTriggered = (address, size);
            });

            bool dirtyInitial = handle.Dirty;

            Assert.True(dirtyInitial); // Handle starts dirty.

            handle.Reprotect();

            bool dirtyAfterReprotect = handle.Dirty;

            Assert.False(dirtyAfterReprotect); // Handle is no longer dirty.

            _tracking.VirtualMemoryEvent(PageSize * 2, 4, true);
            _tracking.VirtualMemoryEvent(PageSize * 2, 4, false);

            bool dirtyAfterUnrelatedReadWrite = handle.Dirty;

            Assert.False(dirtyAfterUnrelatedReadWrite); // Not dirtied, as the write was to an unrelated address.

            Assert.IsNull(readTrackingTriggered);       // Hasn't been triggered yet

            _tracking.VirtualMemoryEvent(0, 4, false);

            bool dirtyAfterRelatedRead = handle.Dirty;

            Assert.False(dirtyAfterRelatedRead);                // Only triggers on write.
            Assert.AreEqual(readTrackingTriggered, (0UL, 4UL)); // Read action was triggered.

            readTrackingTriggered = null;
            _tracking.VirtualMemoryEvent(0, 4, true);

            bool dirtyAfterRelatedWrite = handle.Dirty;

            Assert.True(dirtyAfterRelatedWrite); // Dirty flag should now be set.

            _tracking.VirtualMemoryEvent(4, 4, true);
            bool dirtyAfterRelatedWrite2 = handle.Dirty;

            Assert.True(dirtyAfterRelatedWrite2); // Dirty flag should still be set.

            handle.Reprotect();

            bool dirtyAfterReprotect2 = handle.Dirty;

            Assert.False(dirtyAfterReprotect2); // Handle is no longer dirty.

            handle.Dispose();

            bool dirtyAfterDispose = TestSingleWrite(handle, 0, 4);

            Assert.False(dirtyAfterDispose); // Handle cannot be triggered when disposed
        }
示例#3
0
        public void OverlappingRegions()
        {
            RegionHandle allHandle = _tracking.BeginTracking(0, PageSize * 16);

            allHandle.Reprotect();

            (ulong address, ulong size)? readTrackingTriggeredAll = null;
            Action registerReadAction = () =>
            {
                readTrackingTriggeredAll = null;
                allHandle.RegisterAction((address, size) =>
                {
                    readTrackingTriggeredAll = (address, size);
                });
            };

            registerReadAction();

            // Create 16 page sized handles contained within the allHandle.
            RegionHandle[] containedHandles = new RegionHandle[16];

            for (int i = 0; i < 16; i++)
            {
                containedHandles[i] = _tracking.BeginTracking((ulong)i * PageSize, PageSize);
                containedHandles[i].Reprotect();
            }

            for (int i = 0; i < 16; i++)
            {
                // No handles are dirty.
                Assert.False(allHandle.Dirty);
                Assert.IsNull(readTrackingTriggeredAll);
                for (int j = 0; j < 16; j++)
                {
                    Assert.False(containedHandles[j].Dirty);
                }

                _tracking.VirtualMemoryEvent((ulong)i * PageSize, 1, true);

                // Only the handle covering the entire range and the relevant contained handle are dirty.
                Assert.True(allHandle.Dirty);
                Assert.AreEqual(readTrackingTriggeredAll, ((ulong)i * PageSize, 1UL)); // Triggered read tracking
                for (int j = 0; j < 16; j++)
                {
                    if (j == i)
                    {
                        Assert.True(containedHandles[j].Dirty);
                    }
                    else
                    {
                        Assert.False(containedHandles[j].Dirty);
                    }
                }

                // Clear flags and reset read action.
                registerReadAction();
                allHandle.Reprotect();
                containedHandles[i].Reprotect();
            }
        }
示例#4
0
        public void PhysicalMemoryMapping()
        {
            // Tracking is done in the virtual space usually, but we also support tracking on physical regions.
            // The physical regions that make up a virtual region are determined when the region is created,
            // or when a mapping changes.

            // These tests verify that the region cannot be signalled after unmapping, and can after remapping.

            RegionHandle handle = _tracking.BeginTracking(PageSize, PageSize);

            Assert.True(handle.Dirty);

            bool trackedWriteTriggers = TestSingleWrite(handle, PageSize, 1, true);

            Assert.True(trackedWriteTriggers);

            _memoryManager.NoMappings = true;
            _tracking.Unmap(PageSize, PageSize);
            bool unmappedWriteTriggers = TestSingleWrite(handle, PageSize, 1, true);

            Assert.False(unmappedWriteTriggers);

            _memoryManager.NoMappings = false;
            _tracking.Map(PageSize, PageSize, PageSize);
            bool remappedWriteTriggers = TestSingleWrite(handle, PageSize, 1, true);

            Assert.True(remappedWriteTriggers);
        }
示例#5
0
            private ConcurrentDictionary <NodeHandle, NodeEdges> regionFactory(RegionHandle region)
            {
                var ret = new ConcurrentDictionary <NodeHandle, NodeEdges>();

                ReadFromFile(region, ret);
                recentRegions.AddOrUpdate(region, TotalTime.ElapsedMilliseconds);
                return(ret);
            }
示例#6
0
            public NodeEdges AddOrUpdate(NodeHandle n, NodeEdges newValue, Func <NodeHandle, NodeEdges, NodeEdges> valueFactory)
            {
                RegionHandle r = Region(n);

                recentRegions.AddOrUpdate(r, TotalTime.ElapsedMilliseconds);
                SetDirty(r);
                return(Regions.GetOrAdd(r, regionFactory).AddOrUpdate(n, newValue, valueFactory));
            }
示例#7
0
        private bool TestSingleWrite(RegionHandle handle, ulong address, ulong size)
        {
            handle.Reprotect();

            _tracking.VirtualMemoryEvent(address, size, true);

            return(handle.Dirty);
        }
示例#8
0
 protected override void DeSerialise(byte[] buf, ref int o, int length)
 {
     SoundId  = BinarySerializer.DeSerializeGuid(buf, ref o, length);
     OwnerId  = BinarySerializer.DeSerializeGuid(buf, ref o, length);
     ObjectId = BinarySerializer.DeSerializeGuid(buf, ref o, length);
     ParentId = BinarySerializer.DeSerializeGuid(buf, ref o, length);
     Handle   = new RegionHandle(BinarySerializer.DeSerializeUInt64_Le(buf, ref o, length));
     Position = BinarySerializer.DeSerializeVector3(buf, ref o, buf.Length);
 }
示例#9
0
        public void PreciseAction()
        {
            RegionHandle handle = _tracking.BeginTracking(0, PageSize);

            (ulong address, ulong size, bool write)? preciseTriggered = null;
            handle.RegisterPreciseAction((address, size, write) =>
            {
                preciseTriggered = (address, size, write);

                return(true);
            });

            (ulong address, ulong size)? readTrackingTriggered = null;
            handle.RegisterAction((address, size) =>
            {
                readTrackingTriggered = (address, size);
            });

            handle.Reprotect();

            _tracking.VirtualMemoryEvent(0, 4, false, precise: true);

            Assert.IsNull(readTrackingTriggered);                 // Hasn't been triggered - precise action returned true.
            Assert.AreEqual(preciseTriggered, (0UL, 4UL, false)); // Precise action was triggered.

            _tracking.VirtualMemoryEvent(0, 4, true, precise: true);

            Assert.IsNull(readTrackingTriggered); // Still hasn't been triggered.
            bool dirtyAfterPreciseActionTrue = handle.Dirty;

            Assert.False(dirtyAfterPreciseActionTrue);           // Not dirtied - precise action returned true.
            Assert.AreEqual(preciseTriggered, (0UL, 4UL, true)); // Precise action was triggered.

            // Handle is now dirty.
            handle.Reprotect(true);
            preciseTriggered = null;

            _tracking.VirtualMemoryEvent(4, 4, true, precise: true);
            Assert.AreEqual(preciseTriggered, (4UL, 4UL, true)); // Precise action was triggered even though handle was dirty.

            handle.Reprotect();
            handle.RegisterPreciseAction((address, size, write) =>
            {
                preciseTriggered = (address, size, write);

                return(false); // Now, we return false, which indicates that the regular read/write behaviours should trigger.
            });

            _tracking.VirtualMemoryEvent(8, 4, true, precise: true);

            Assert.AreEqual(readTrackingTriggered, (8UL, 4UL)); // Read action triggered, as precise action returned false.
            bool dirtyAfterPreciseActionFalse = handle.Dirty;

            Assert.True(dirtyAfterPreciseActionFalse);           // Dirtied, as precise action returned false.
            Assert.AreEqual(preciseTriggered, (8UL, 4UL, true)); // Precise action was triggered.
        }
示例#10
0
 public static void ReadFromFile(RegionHandle region, ConcurrentDictionary <NodeHandle, NodeEdges> output)
 {
     try {
         totalReadTimer.Start();
         uint r = (uint)region >> 7;
         ReadFromFile(region, $"scripts/NavMesh/{r}/{region}.mesh", output);
     } finally {
         totalReadTimer.Stop();
     }
 }
示例#11
0
 protected override void DeSerialise(byte[] buf, ref int o, int length)
 {
     AgentId        = BinarySerializer.DeSerializeGuid(buf, ref o, length);
     SessionId      = BinarySerializer.DeSerializeGuid(buf, ref o, length);
     Position       = BinarySerializer.DeSerializeVector3(buf, ref o, length);
     LookAt         = BinarySerializer.DeSerializeVector3(buf, ref o, length);
     RegionHandle   = new RegionHandle(BinarySerializer.DeSerializeUInt64_Le(buf, ref o, length));
     TimeStamp      = BinarySerializer.DeSerializeDateTime(buf, ref o, length);
     ChannelVersion = BinarySerializer.DeSerializeString(buf, ref o, length, 2);
 }
示例#12
0
            public void Set(NodeHandle n, NodeEdges e)
            {
                RegionHandle r = Region(n);

                Regions
                .GetOrAdd(r, regionFactory)
                .AddOrUpdate(n, e, (k, o) => e);
                recentRegions.AddOrUpdate(r, TotalTime.ElapsedMilliseconds);
                SetDirty(r);
            }
示例#13
0
            public NodeEdges Get(NodeHandle n)
            {
                RegionHandle r = Region(n);

                if (Regions.GetOrAdd(r, regionFactory).TryGetValue(n, out NodeEdges edges))
                {
                    recentRegions.AddOrUpdate(r, TotalTime.ElapsedMilliseconds);
                    return(edges);
                }
                return(NodeEdges.Empty);
            }
示例#14
0
 private bool TestSingleWrite(RegionHandle handle, ulong address, ulong size, bool physical = false)
 {
     handle.Reprotect();
     if (physical)
     {
         _tracking.PhysicalMemoryEvent(address, true);
     }
     else
     {
         _tracking.VirtualMemoryEvent(address, size, true);
     }
     return(handle.Dirty);
 }
示例#15
0
        protected override LResult WindowProcedure(WindowHandle window, MessageType message, WParam wParam, LParam lParam)
        {
            switch (message)
            {
            case MessageType.Size:
                cxClient = lParam.LowWord;
                cyClient = lParam.HighWord;

                CursorHandle hCursor = Windows.SetCursor(CursorId.Wait);
                Windows.ShowCursor(true);

                hRgnClip.Dispose();

                Span <RegionHandle> hRgnTemp = stackalloc RegionHandle[6];

                hRgnTemp[0] = Gdi.CreateEllipticRegion(Rectangle.FromLTRB(0, cyClient / 3, cxClient / 2, 2 * cyClient / 3));
                hRgnTemp[1] = Gdi.CreateEllipticRegion(Rectangle.FromLTRB(cxClient / 2, cyClient / 3, cxClient, 2 * cyClient / 3));
                hRgnTemp[2] = Gdi.CreateEllipticRegion(Rectangle.FromLTRB(cxClient / 3, 0, 2 * cxClient / 3, cyClient / 2));
                hRgnTemp[3] = Gdi.CreateEllipticRegion(Rectangle.FromLTRB(cxClient / 3, cyClient / 2, 2 * cxClient / 3, cyClient));
                hRgnTemp[4] = Gdi.CreateRectangleRegion(Rectangle.FromLTRB(0, 0, 1, 1));
                hRgnTemp[5] = Gdi.CreateRectangleRegion(Rectangle.FromLTRB(0, 0, 1, 1));
                hRgnClip    = Gdi.CreateRectangleRegion(Rectangle.FromLTRB(0, 0, 1, 1));
                hRgnTemp[4].CombineRegion(hRgnTemp[0], hRgnTemp[1], CombineRegionMode.Or);
                hRgnTemp[5].CombineRegion(hRgnTemp[2], hRgnTemp[3], CombineRegionMode.Or);
                hRgnClip.CombineRegion(hRgnTemp[4], hRgnTemp[5], CombineRegionMode.Xor);
                for (int i = 0; i < 6; i++)
                {
                    hRgnTemp[i].Dispose();
                }

                Windows.SetCursor(hCursor);
                Windows.ShowCursor(false);

                return(0);

            case MessageType.Paint:
                using (DeviceContext dc = window.BeginPaint())
                {
                    dc.SetViewportOrigin(new Point(cxClient / 2, cyClient / 2));
                    dc.SelectClippingRegion(hRgnClip);

                    double fRadius = Hypotenuse(cxClient / 2.0, cyClient / 2.0);

                    for (double fAngle = 0.0; fAngle < TWO_PI; fAngle += TWO_PI / 360)
                    {
                        dc.MoveTo(default);
                        dc.LineTo(new Point(
                                      (int)(fRadius * Math.Cos(fAngle) + 0.5),
                                      (int)(-fRadius * Math.Sin(fAngle) + 0.5)));
                    }
                }
示例#16
0
        public static void ReadFromFile(RegionHandle region, string filename, ConcurrentDictionary <NodeHandle, NodeEdges> output)
        {
            if (!LoadEnabled)
            {
                return;
            }

            var s = new Stopwatch();

            s.Start();
            try {
                using (BinaryReader r = Codec.Reader(filename)) {
                    readBytesTimer.Start();
                    int magic = r.ReadInt32();
                    if (magic == 0x000FEED9)
                    {
                        int count = r.ReadInt32();
                        if (count <= 0)
                        {
                            Log($"Invalid count: {count}");
                            return;
                        }
                        byte[]  buf;
                        ulong[] handles = new ulong[count];
                        ulong[] edges   = new ulong[count];
                        buf = r.ReadBytes(count * sizeof(ulong));
                        Buffer.BlockCopy(buf, 0, handles, 0, buf.Length);
                        buf = r.ReadBytes(count * sizeof(ulong));
                        Buffer.BlockCopy(buf, 0, edges, 0, buf.Length);
                        readBytesTimer.Stop();
                        applyBytesTimer.Start();
                        Parallel.For(0, count, (i) => {
                            output.TryAdd((NodeHandle)handles[i], (NodeEdges)edges[i]);
                        });
                        Log($"[{region}] Loaded {count} (ver. 9) nodes in {s.ElapsedMilliseconds}ms");
                        applyBytesTimer.Stop();
                    }
                    else
                    {
                        Log($"Invalid magic bytes: {magic}");
                        return;
                    }
                }
            } catch (DirectoryNotFoundException) {
                // Log($"[{region}] Loaded 0 nodes ({filename} not found) in {s.ElapsedMilliseconds}ms");
            } catch (FileNotFoundException) {
                // Log($"[{region}] Loaded 0 nodes ({filename} not found) in {s.ElapsedMilliseconds}ms");
            }
            s.Stop();
            return;
        }
示例#17
0
        public void PageAlignment(
            [Values(1ul, 512ul, 2048ul, 4096ul, 65536ul)][Random(1ul, 65536ul, RndCnt)] ulong address,
            [Values(1ul, 4ul, 1024ul, 4096ul, 65536ul)][Random(1ul, 65536ul, RndCnt)] ulong size)
        {
            ulong alignedStart = (address / PageSize) * PageSize;
            ulong alignedEnd   = ((address + size + PageSize - 1) / PageSize) * PageSize;
            ulong alignedSize  = alignedEnd - alignedStart;

            RegionHandle handle = _tracking.BeginTracking(address, size);

            // Anywhere inside the pages the region is contained on should trigger.

            bool originalRangeTriggers = TestSingleWrite(handle, address, size);

            Assert.True(originalRangeTriggers);

            bool alignedRangeTriggers = TestSingleWrite(handle, alignedStart, alignedSize);

            Assert.True(alignedRangeTriggers);

            bool alignedStartTriggers = TestSingleWrite(handle, alignedStart, 1);

            Assert.True(alignedStartTriggers);

            bool alignedEndTriggers = TestSingleWrite(handle, alignedEnd - 1, 1);

            Assert.True(alignedEndTriggers);

            // Outside the tracked range should not trigger.

            bool alignedBeforeTriggers = TestSingleWrite(handle, alignedStart - 1, 1);

            Assert.False(alignedBeforeTriggers);

            bool alignedAfterTriggers = TestSingleWrite(handle, alignedEnd, 1);

            Assert.False(alignedAfterTriggers);
        }
示例#18
0
        internal static void SaveToFile(RegionHandle region)
        {
            Log($"Saving region {region}");
            uint r = (uint)region >> 7;

            Directory.CreateDirectory($"scripts/NavMesh/{r}/");
            var file = $"scripts/NavMesh/{r}/{region}.mesh";

            using (BinaryWriter w = Codec.Writer(file + ".tmp")) {
                w.Write(versionBytes);
                var     result  = AllNodes.Regions[region];                                    // we know it's there bc it's dirty
                ulong[] handles = result.Keys.Cast <ulong>().ToArray();
                ulong[] edges   = handles.Select(h => (ulong)result[(NodeHandle)h]).ToArray(); // use Select this way to guarantee they match the order of handles
                byte[]  buf;
                try {
                    w.Write(handles.Length);
                    buf = new byte[handles.Length * sizeof(NodeHandle)];
                    Buffer.BlockCopy(handles, 0, buf, 0, buf.Length);
                    w.Write(buf);
                } catch (Exception err) {
                    Log("Failed to write handles to file: " + err.ToString());
                    return;
                }
                try {
                    buf = new byte[edges.Length * sizeof(ulong)];
                    Buffer.BlockCopy(edges, 0, buf, 0, buf.Length);
                    w.Write(buf);
                } catch (Exception err) {
                    Log("Failed to write edges to file: " + err.ToString());
                    return;
                }
            }
            try { File.Delete(file); } catch (FileNotFoundException) { }
            try { File.Move(file + ".tmp", file); } catch (Exception e) {
                Log("File.Move Failed: " + e.ToString());
            }
        }
示例#19
0
 internal CpuRegionHandle(RegionHandle impl)
 {
     _impl = impl;
 }
示例#20
0
        static LRESULT WindowProcedure(WindowHandle window, WindowMessage message, WPARAM wParam, LPARAM lParam)
        {
            switch (message)
            {
            case WindowMessage.Size:
                cxClient = lParam.LowWord;
                cyClient = lParam.HighWord;

                CursorHandle hCursor = Windows.SetCursor(CursorId.Wait);
                Windows.ShowCursor(true);

                hRgnClip?.Dispose();

                RegionHandle[] hRgnTemp = new RegionHandle[6];

                hRgnTemp[0] = Windows.CreateEllipticRegion(0, cyClient / 3, cxClient / 2, 2 * cyClient / 3);
                hRgnTemp[1] = Windows.CreateEllipticRegion(cxClient / 2, cyClient / 3, cxClient, 2 * cyClient / 3);
                hRgnTemp[2] = Windows.CreateEllipticRegion(cxClient / 3, 0, 2 * cxClient / 3, cyClient / 2);
                hRgnTemp[3] = Windows.CreateEllipticRegion(cxClient / 3, cyClient / 2, 2 * cxClient / 3, cyClient);
                hRgnTemp[4] = Windows.CreateRectangleRegion(0, 0, 1, 1);
                hRgnTemp[5] = Windows.CreateRectangleRegion(0, 0, 1, 1);
                hRgnClip    = Windows.CreateRectangleRegion(0, 0, 1, 1);
                hRgnTemp[4].CombineRegion(hRgnTemp[0], hRgnTemp[1], CombineRegionMode.Or);
                hRgnTemp[5].CombineRegion(hRgnTemp[2], hRgnTemp[3], CombineRegionMode.Or);
                hRgnClip.CombineRegion(hRgnTemp[4], hRgnTemp[5], CombineRegionMode.Xor);
                for (int i = 0; i < 6; i++)
                {
                    hRgnTemp[i]?.Dispose();
                }

                Windows.SetCursor(hCursor);
                Windows.ShowCursor(false);

                return(0);

            case WindowMessage.Paint:
                using (DeviceContext dc = window.BeginPaint())
                {
                    dc.SetViewportOrigin(cxClient / 2, cyClient / 2);
                    dc.SelectClippingRegion(hRgnClip);

                    double fRadius = Hypotenuse(cxClient / 2.0, cyClient / 2.0);

                    for (double fAngle = 0.0; fAngle < TWO_PI; fAngle += TWO_PI / 360)
                    {
                        dc.MoveTo(0, 0);
                        dc.LineTo(
                            (int)(fRadius * Math.Cos(fAngle) + 0.5),
                            (int)(-fRadius * Math.Sin(fAngle) + 0.5));
                    }
                }
                return(0);

            case WindowMessage.Destroy:
                hRgnClip?.Dispose();
                Windows.PostQuitMessage(0);
                return(0);
            }

            return(Windows.DefaultWindowProcedure(window, message, wParam, lParam));
        }
示例#21
0
    public Region AddRegion(RegionHandle handle, Host host)
    {
        Region     region;
        Capability seedCapability = null;

        if (RegionByHandle.ContainsKey(handle))
        {
            // Region already exists
            region = RegionByHandle[handle];
            Host oldHost = region.Host;
            if (host == oldHost && region.Alive)
            {
                Logger.LogInfo($"Region with handle {handle} already exists and is alive, using existing region.");
                return(region);
            }

            if (host != oldHost)
            {
                Logger.LogWarning($"Region with handle {handle} already exists but with a different host. Removing and creating new.");
            }
            if (region.Alive == false)
            {
                Logger.LogWarning($"Region with handle {handle} already exists but it isn't alive. Removing and creating new.");
            }

            // Save capabilities seed URL
            seedCapability = region.GetCapability(Capability.SEED_CAPABILITY_NAME);

            // Kill the old host, and then we can continue on and add the new host.  We have to kill even if the host
            // matches, because all the agent state for the new camera is completely different.
            RemoveRegion(oldHost);
        }
        else
        {
            Logger.LogInfo($"Region with handle {handle} does not exist, creating a new one.");
        }

        UInt32 iindex = handle.X;
        UInt32 jindex = handle.Y;

        int x = (int)(iindex / WIDTH);
        int y = (int)(jindex / WIDTH);

        Logger.LogInfo($"Adding new region {handle} on {host}.");

        Vector3Double origin_global = handle.ToVector3Double();

        region = new Region(handle, host, WIDTH, WORLD_PATCH_SIZE, WIDTH_IN_METRES);

        if (seedCapability != null)
        {
            region.SetCapability(seedCapability);
        }

        RegionList.Add(region);
        ActiveRegionList.Add(region);
        CulledRegionList.Add(region);
        RegionByHandle[handle] = region;
        RegionByHost[host]     = region;

        // Find all the adjacent regions, and attach them.
        // Generate handles for all of the adjacent regions, and attach them in the correct way.
        // connect the edges
        float        adj_x      = 0f;
        float        adj_y      = 0f;
        float        region_x   = handle.X;
        float        region_y   = handle.Y;
        RegionHandle adj_handle = new RegionHandle(0);

        float width = WIDTH_IN_METRES;

        // Iterate through all directions, and connect neighbors if there.
        for (int dir = 0; dir < 8; dir++)
        {
            adj_x = region_x + width * DirectionAxes[dir, 0];
            adj_y = region_y + width * DirectionAxes[dir, 1];
            if (adj_x >= 0)
            {
                adj_handle.X = (UInt32)adj_x;
            }
            if (adj_y >= 0)
            {
                adj_handle.Y = (UInt32)adj_y;
            }

            if (RegionByHandle.ContainsKey(adj_handle))
            {
                region.ConnectNeighbour(RegionByHandle[adj_handle], (DirectionIndex)dir);
            }
        }

        // TODO: UpdateWaterObjects();

        return(region);
    }
 public static RegionType CombineRegion(this RegionHandle destination, RegionHandle sourceOne, RegionHandle sourceTwo, CombineRegionMode mode) =>
 GdiMethods.CombineRegion(destination, sourceOne, sourceTwo, mode);
 public static RegionType SelectClippingRegion(this DeviceContext deviceContext, RegionHandle region) => GdiMethods.SelectClippingRegion(deviceContext, region);
示例#24
0
        public void Multithreading()
        {
            // Multithreading sanity test
            // Multiple threads can easily read/write memory regions from any existing handle.
            // Handles can also be owned by different threads, though they should have one owner thread.
            // Handles can be created and disposed at any time, by any thread.

            // This test should not throw or deadlock due to invalid state.

            const int threadCount      = 1;
            const int handlesPerThread = 16;
            long      finishedTime     = 0;

            RegionHandle[] handles    = new RegionHandle[threadCount * handlesPerThread];
            Random         globalRand = new Random();

            for (int i = 0; i < handles.Length; i++)
            {
                handles[i] = _tracking.BeginTracking((ulong)i * PageSize, PageSize);
                handles[i].Reprotect();
            }

            List <Thread> testThreads = new List <Thread>();

            // Dirty flag consumer threads
            int dirtyFlagReprotects = 0;

            for (int i = 0; i < threadCount; i++)
            {
                int randSeed = i;
                testThreads.Add(new Thread(() =>
                {
                    int handleBase = randSeed * handlesPerThread;
                    while (Stopwatch.GetTimestamp() < finishedTime)
                    {
                        Random random       = new Random(randSeed);
                        RegionHandle handle = handles[handleBase + random.Next(handlesPerThread)];

                        if (handle.Dirty)
                        {
                            handle.Reprotect();
                            Interlocked.Increment(ref dirtyFlagReprotects);
                        }
                    }
                }));
            }

            // Write trigger threads
            int writeTriggers = 0;

            for (int i = 0; i < threadCount; i++)
            {
                int randSeed = i;
                testThreads.Add(new Thread(() =>
                {
                    Random random    = new Random(randSeed);
                    ulong handleBase = (ulong)(randSeed * handlesPerThread * PageSize);
                    while (Stopwatch.GetTimestamp() < finishedTime)
                    {
                        _tracking.VirtualMemoryEvent(handleBase + (ulong)random.Next(PageSize * handlesPerThread), PageSize / 2, true);
                        Interlocked.Increment(ref writeTriggers);
                    }
                }));
            }

            // Handle create/delete threads
            int handleLifecycles = 0;

            for (int i = 0; i < threadCount; i++)
            {
                int randSeed = i;
                testThreads.Add(new Thread(() =>
                {
                    int maxAddress = threadCount * handlesPerThread * PageSize;
                    Random random  = new Random(randSeed + 512);
                    while (Stopwatch.GetTimestamp() < finishedTime)
                    {
                        RegionHandle handle = _tracking.BeginTracking((ulong)random.Next(maxAddress), (ulong)random.Next(65536));

                        handle.Dispose();

                        Interlocked.Increment(ref handleLifecycles);
                    }
                }));
            }

            finishedTime = Stopwatch.GetTimestamp() + Stopwatch.Frequency / 2; // Run for 500ms;

            foreach (Thread thread in testThreads)
            {
                thread.Start();
            }

            foreach (Thread thread in testThreads)
            {
                thread.Join();
            }

            Assert.Greater(dirtyFlagReprotects, 10);
            Assert.Greater(writeTriggers, 10);
            Assert.Greater(handleLifecycles, 10);
        }
示例#25
0
        public void ReadActionThreadConsumption()
        {
            // Read actions should only be triggered once for each registration.
            // The implementation should use an interlocked exchange to make sure other threads can't get the action.

            RegionHandle handle = _tracking.BeginTracking(0, PageSize);

            int  triggeredCount    = 0;
            int  registeredCount   = 0;
            int  signalThreadsDone = 0;
            bool isRegistered      = false;

            Action registerReadAction = () =>
            {
                registeredCount++;
                handle.RegisterAction((address, size) =>
                {
                    isRegistered = false;
                    Interlocked.Increment(ref triggeredCount);
                });
            };

            const int threadCount    = 16;
            const int iterationCount = 10000;

            Thread[] signalThreads = new Thread[threadCount];

            for (int i = 0; i < threadCount; i++)
            {
                int randSeed = i;
                signalThreads[i] = new Thread(() =>
                {
                    Random random = new Random(randSeed);
                    for (int j = 0; j < iterationCount; j++)
                    {
                        _tracking.VirtualMemoryEvent((ulong)random.Next(PageSize), 4, false);
                    }
                    Interlocked.Increment(ref signalThreadsDone);
                });
            }

            for (int i = 0; i < threadCount; i++)
            {
                signalThreads[i].Start();
            }

            while (signalThreadsDone != -1)
            {
                if (signalThreadsDone == threadCount)
                {
                    signalThreadsDone = -1;
                }

                if (!isRegistered)
                {
                    isRegistered = true;
                    registerReadAction();
                }
            }

            // The action should trigger exactly once for every registration,
            // then we register once after all the threads signalling it cease.
            Assert.AreEqual(registeredCount, triggeredCount + 1);
        }
示例#26
0
        public void InheritHandles()
        {
            // Test merging the following into a granular region handle:
            // - 3x gap (creates new granular handles)
            // - 3x from multiregion: not dirty, dirty and with action
            // - 2x gap
            // - 3x single page: not dirty, dirty and with action
            // - 3x two page: not dirty, dirty and with action (handle is not reused, but its state is copied to the granular handles)
            // - 1x gap
            // For a total of 18 pages.

            bool[] actionsTriggered = new bool[3];

            MultiRegionHandle granular = _tracking.BeginGranularTracking(PageSize * 3, PageSize * 3, null, PageSize);

            PreparePages(granular, 3, PageSize * 3);

            // Write to the second handle in the multiregion.
            _tracking.VirtualMemoryEvent(PageSize * 4, PageSize, true);

            // Add an action to the third handle in the multiregion.
            granular.RegisterAction(PageSize * 5, PageSize, (_, _) => { actionsTriggered[0] = true; });

            RegionHandle[] singlePages = new RegionHandle[3];

            for (int i = 0; i < 3; i++)
            {
                singlePages[i] = _tracking.BeginTracking(PageSize * (8 + (ulong)i), PageSize);
                singlePages[i].Reprotect();
            }

            // Write to the second handle.
            _tracking.VirtualMemoryEvent(PageSize * 9, PageSize, true);

            // Add an action to the third handle.
            singlePages[2].RegisterAction((_, _) => { actionsTriggered[1] = true; });

            RegionHandle[] doublePages = new RegionHandle[3];

            for (int i = 0; i < 3; i++)
            {
                doublePages[i] = _tracking.BeginTracking(PageSize * (11 + (ulong)i * 2), PageSize * 2);
                doublePages[i].Reprotect();
            }

            // Write to the second handle.
            _tracking.VirtualMemoryEvent(PageSize * 13, PageSize * 2, true);

            // Add an action to the third handle.
            doublePages[2].RegisterAction((_, _) => { actionsTriggered[2] = true; });

            // Finally, create a granular handle that inherits all these handles.

            IEnumerable <IRegionHandle>[] handleGroups = new IEnumerable <IRegionHandle>[]
            {
                granular.GetHandles(),
                                          singlePages,
                                          doublePages
            };

            MultiRegionHandle combined = _tracking.BeginGranularTracking(0, PageSize * 18, handleGroups.SelectMany((handles) => handles), PageSize);

            bool[] expectedDirty = new bool[]
            {
                true, true, true,                       // Gap.
                false, true, false,                     // Multi-region.
                true, true,                             // Gap.
                false, true, false,                     // Individual handles.
                false, false, true, true, false, false, // Double size handles.
                true                                    // Gap.
            };

            for (int i = 0; i < 18; i++)
            {
                bool modified = false;
                combined.QueryModified(PageSize * (ulong)i, PageSize, (_, _) => { modified = true; });

                Assert.AreEqual(expectedDirty[i], modified);
            }

            Assert.AreEqual(new bool[3], actionsTriggered);

            _tracking.VirtualMemoryEvent(PageSize * 5, PageSize, false);
            Assert.IsTrue(actionsTriggered[0]);

            _tracking.VirtualMemoryEvent(PageSize * 10, PageSize, false);
            Assert.IsTrue(actionsTriggered[1]);

            _tracking.VirtualMemoryEvent(PageSize * 15, PageSize, false);
            Assert.IsTrue(actionsTriggered[2]);

            // The double page handles should be disposed, as they were split into granular handles.
            foreach (RegionHandle doublePage in doublePages)
            {
                // These should have been disposed.
                bool throws = false;

                try
                {
                    doublePage.Dispose();
                }
                catch (ObjectDisposedException)
                {
                    throws = true;
                }

                Assert.IsTrue(throws);
            }

            IEnumerable <IRegionHandle> combinedHandles = combined.GetHandles();

            Assert.AreEqual(handleGroups[0].ElementAt(0), combinedHandles.ElementAt(3));
            Assert.AreEqual(handleGroups[0].ElementAt(1), combinedHandles.ElementAt(4));
            Assert.AreEqual(handleGroups[0].ElementAt(2), combinedHandles.ElementAt(5));

            Assert.AreEqual(singlePages[0], combinedHandles.ElementAt(8));
            Assert.AreEqual(singlePages[1], combinedHandles.ElementAt(9));
            Assert.AreEqual(singlePages[2], combinedHandles.ElementAt(10));
        }
示例#27
0
文件: Region.cs 项目: Siccity/UnitySL
    /// <summary>
    /// Creates a new region
    /// </summary>
    /// <param name="handle"></param>
    /// <param name="host"></param>
    /// <param name="gridsPerRegionEdge"></param>
    /// <param name="gridsPerPatchEdge"></param>
    /// <param name="regionWidth"> in metres</param>
    public Region(RegionHandle handle, Host host, UInt32 gridsPerRegionEdge, UInt32 gridsPerPatchEdge, float regionWidth)
    {
        Host         = host;
        Handle       = handle;
        TimeDilation = 1.0f;

        Name   = "";
        Zoning = "";

        IsCurrentPlayerEstateOwner = false;

        RegionFlags     = RegionFlags.Default;
        RegionProtocols = RegionProtocols.None;
        SimAccess       = SimAccess.Min;

        BillableFactor = 1.0f;

        MaxTasks = DEFAULT_MAX_REGION_WIDE_PRIM_COUNT;

        CentralBakeVersion = 1;

        CpuClassId = 0;
        CpuRatio   = 0;

        ColoName       = "unknown";
        ProductSku     = "unknown";
        ProductName    = "unknown";
        ViewerAssetUrl = "";

        CacheLoaded = false;
        CacheDirty  = false;

        ReleaseNotesRequested     = false;
        CapabilitiesReceived      = false;
        SimulatorFeaturesReceived = false;

        BitsReceived    = 0f;
        PacketsReceived = 0f;

        Dead = false;
        // TODO: LastVisitedEntry = null;
        InvisibilityCheckHistory = 0xffffffff;
        Paused = false;
        RegionCacheHitCount  = 0;
        RegionCacheMissCount = 0;

        Width        = regionWidth;
        OriginGlobal = handle.ToVector3Double();
        //TODO: updateRenderMatrix();

        Land = new Surface(SurfaceType.Land, null);  //TODO: Why not set the region right away?

        // Create the composition layer for the surface
        //Composition = new VolumeLayerComposition (Land, gridsPerRegionEdge, regionWidth / gridsPerRegionEdge);
        //Composition.SetSurface (Land);

        // Create the surfaces
        Land.SetRegion(this);
        Land.Create(gridsPerRegionEdge, gridsPerPatchEdge, OriginGlobal, Width);

        //TODO: ParcelOverlay = new LLViewerParcelOverlay(this, regionWidth);

        //TODO: CalculateCenterGlobal();

        // Create the object lists
        // TODO: InitStats();

        //TODO: create object partitions
        //MUST MATCH declaration of eObjectPartitions
        //ObjectPartition.Add (new LLHUDPartition(this));        //PARTITION_HUD
        //ObjectPartition.Add (new LLTerrainPartition(this));    //PARTITION_TERRAIN
        //ObjectPartition.Add (new LLVoidWaterPartition(this));  //PARTITION_VOIDWATER
        //ObjectPartition.Add (new LLWaterPartition(this));      //PARTITION_WATER
        //ObjectPartition.Add (new LLTreePartition(this));       //PARTITION_TREE
        //ObjectPartition.Add (new LLParticlePartition(this));   //PARTITION_PARTICLE
        //ObjectPartition.Add (new LLGrassPartition(this));      //PARTITION_GRASS
        //ObjectPartition.Add (new LLVolumePartition(this)); //PARTITION_VOLUME
        //ObjectPartition.Add (new LLBridgePartition(this)); //PARTITION_BRIDGE
        //ObjectPartition.Add (new LLAvatarPartition(this)); //PARTITION_AVATAR
        //ObjectPartition.Add (new LLControlAVPartition(this));  //PARTITION_CONTROL_AV
        //ObjectPartition.Add (new LLHUDParticlePartition(this));//PARTITION_HUD_PARTICLE
        //ObjectPartition.Add (new LLVOCachePartition(this)); //PARTITION_VO_CACHE
        //ObjectPartition.Add (null);                    //PARTITION_NONE
        //VOCachePartition = getVOCachePartition();

        // TODO: setCapabilitiesReceivedCallback(boost::bind(&LLAvatarRenderInfoAccountant::scanNewRegion, _1));
    }
示例#28
0
        protected override void DeSerialise(byte[] buf, ref int o, int length)
        {
            RegionHandle = new RegionHandle(BinarySerializer.DeSerializeUInt64_Le(buf, ref o, length));
            TimeDilation = BinarySerializer.DeSerializeUInt16_Le(buf, ref o, length);

            int nObjects = buf[o++];

            for (int i = 0; i < nObjects; i++)
            {
                int len;
                ObjectUpdateMessage.ObjectData data = new ObjectUpdateMessage.ObjectData();
                Objects.Add(data);

                data.LocalId = BinarySerializer.DeSerializeUInt32_Le(buf, ref o, length);
                data.State   = buf[o++];

                data.FullId         = BinarySerializer.DeSerializeGuid(buf, ref o, length);
                data.Crc            = BinarySerializer.DeSerializeUInt32_Le(buf, ref o, length);
                data.PCode          = (PCode)buf[o++];
                data.Material       = (MaterialType)buf[o++];
                data.ClickAction    = (ClickAction)buf[o++];
                data.Scale          = BinarySerializer.DeSerializeVector3(buf, ref o, buf.Length);
                data.MovementUpdate = DeSerializeMovementUpdate(buf, ref o, buf.Length);

                data.ParentId    = BinarySerializer.DeSerializeUInt32_Le(buf, ref o, length);
                data.UpdateFlags = (ObjectUpdateFlags)BinarySerializer.DeSerializeUInt32_Le(buf, ref o, length);

                data.PathCurve        = (PathType)buf[o++];
                data.ProfileCurve     = (ProfileType)buf[o++];
                data.PathBegin        = BinarySerializer.DeSerializeUInt16_Le(buf, ref o, length) * CUT_QUANTA;
                data.PathEnd          = BinarySerializer.DeSerializeUInt16_Le(buf, ref o, length) * CUT_QUANTA;
                data.PathScaleX       = buf[o++] * SCALE_QUANTA;
                data.PathScaleY       = buf[o++] * SCALE_QUANTA;
                data.PathShearX       = buf[o++] * SHEAR_QUANTA;
                data.PathShearY       = buf[o++] * SHEAR_QUANTA;
                data.PathTwist        = (sbyte)buf[o++] * SCALE_QUANTA;
                data.PathTwistBegin   = (sbyte)buf[o++] * SCALE_QUANTA;
                data.PathRadiusOffset = (sbyte)buf[o++] * SCALE_QUANTA;
                data.PathTaperX       = (sbyte)buf[o++] * TAPER_QUANTA;
                data.PathTaperY       = (sbyte)buf[o++] * TAPER_QUANTA;
                data.PathRevolutions  = buf[o++] * REV_QUANTA;
                data.PathSkew         = (sbyte)buf[o++] * SCALE_QUANTA;
                data.ProfileBegin     = BinarySerializer.DeSerializeUInt16_Le(buf, ref o, length) * CUT_QUANTA;
                data.ProfileEnd       = BinarySerializer.DeSerializeUInt16_Le(buf, ref o, length) * CUT_QUANTA;
                data.ProfileHollow    = BinarySerializer.DeSerializeUInt16_Le(buf, ref o, length) * HOLLOW_QUANTA;

                data.TextureEntry     = BinarySerializer.DeSerializeTextureEntry(buf, ref o, length);
                data.TextureAnimation = BinarySerializer.DeSerializeTextureAnimation(buf, ref o, length);

                data.NameValue = BinarySerializer.DeSerializeString(buf, ref o, length, 2);
                len            = BinarySerializer.DeSerializeUInt16_Le(buf, ref o, length);
                data.Data2     = new byte[len];
                Array.Copy(buf, o, data.Data2, 0, len);
                o              += len;
                data.Text       = BinarySerializer.DeSerializeString(buf, ref o, length, 1);
                data.TextColour = BinarySerializer.DeSerializeColor(buf, ref o, length);
                data.MediaUrl   = BinarySerializer.DeSerializeString(buf, ref o, length, 1);

                len = buf[o++];
                data.ParticleSystemData = new byte[len];
                Array.Copy(buf, o, data.ParticleSystemData, 0, len);
                o += len;

                len = buf[o++];
                data.ExtraParameters = BinarySerializer.DeSerializeExtraParameters(buf, ref o, o + len);

                data.SoundId    = BinarySerializer.DeSerializeGuid(buf, ref o, length);
                data.OwnerId    = BinarySerializer.DeSerializeGuid(buf, ref o, length);
                data.Gain       = BinarySerializer.DeSerializeUInt32_Le(buf, ref o, buf.Length);
                data.SoundFlags = (SoundFlags)buf[o++];
                data.Radius     = BinarySerializer.DeSerializeFloat_Le(buf, ref o, length);

                data.JointType         = (JointType)buf[o++];
                data.JointPivot        = BinarySerializer.DeSerializeVector3(buf, ref o, buf.Length);
                data.JointAxisOrAnchor = BinarySerializer.DeSerializeVector3(buf, ref o, buf.Length);

                //Logger.LogDebug("ObjectUpdateMessage.DeSerialise", ToString());
            }
        }
        protected override void DeSerialise(byte[] buf, ref int o, int length)
        {
            RegionHandle = new RegionHandle(BinarySerializer.DeSerializeUInt64_Le(buf, ref o, length));
            TimeDilation = BinarySerializer.DeSerializeUInt16_Le(buf, ref o, length);

            string logMessage = $"ObjectUpdateCompressed: RegionHandle={RegionHandle}, TimeDilation={TimeDilation}";
            int    nObjects   = buf[o++];

            for (int i = 0; i < nObjects; i++)
            {
                UInt32 len;
                ObjectUpdateMessage.ObjectData data = new ObjectUpdateMessage.ObjectData();
                Objects.Add(data);

                data.UpdateFlags = (ObjectUpdateFlags)BinarySerializer.DeSerializeUInt32_Le(buf, ref o, length);

                int    compressedLength = BinarySerializer.DeSerializeUInt16_Le(buf, ref o, length);
                byte[] compressedData   = new byte[compressedLength];
                Array.Copy(buf, o, compressedData, 0, compressedLength);
                o += compressedLength;
                int compressedOffset = 0;

                logMessage      += $"\n  Object {i}: UpdateFlags={data.UpdateFlags}, Data({compressedData.Length})={BitConverter.ToString(compressedData)}";
                data.FullId      = BinarySerializer.DeSerializeGuid(compressedData, ref compressedOffset, compressedLength);
                data.LocalId     = BinarySerializer.DeSerializeUInt32_Le(compressedData, ref compressedOffset, compressedLength);
                data.PCode       = (PCode)compressedData[compressedOffset++];
                data.State       = compressedData[compressedOffset++];
                data.Crc         = BinarySerializer.DeSerializeUInt32_Le(compressedData, ref compressedOffset, compressedLength);
                data.Material    = (MaterialType)compressedData[compressedOffset++];
                data.ClickAction = (ClickAction)compressedData[compressedOffset++];
                data.Scale       = BinarySerializer.DeSerializeVector3(compressedData, ref compressedOffset, compressedLength);
                data.Position    = BinarySerializer.DeSerializeVector3(compressedData, ref compressedOffset, compressedLength);
                data.Rotation    = BinarySerializer.DeSerializeQuaternion(compressedData, ref compressedOffset, compressedLength);
                CompressedFlags compressedFlags = (CompressedFlags)BinarySerializer.DeSerializeUInt32_Le(compressedData, ref compressedOffset, compressedLength);

                data.OwnerId = BinarySerializer.DeSerializeGuid(compressedData, ref compressedOffset, compressedLength);

                logMessage += $"\n    FullId={data.FullId}, LocalId={data.LocalId}, PCode={data.PCode}, State={data.State}, Crc={data.Crc}, Material={data.Material}, ClickAction={data.ClickAction}, Scale={data.Scale}, Position={data.Position}, Rotation={data.Rotation}, CompressedFlags=({compressedFlags})";

                if ((compressedFlags & CompressedFlags.HasAngularVelocity) != 0)
                {
                    data.AngularVelocity = BinarySerializer.DeSerializeVector3(compressedData, ref compressedOffset, compressedLength);
                    logMessage          += $", AngularVelocity={data.AngularVelocity}";
                }

                data.ParentId = (compressedFlags & CompressedFlags.HasParent) != 0 ? BinarySerializer.DeSerializeUInt32_Le(compressedData, ref compressedOffset, compressedLength) : (uint)0;
                logMessage   += $", ParentId={data.ParentId}";

                if ((compressedFlags & CompressedFlags.Tree) != 0)
                {
                    byte treeSpecies = compressedData[compressedOffset++];
                    logMessage += $", TreeSpecies={treeSpecies}";
                }

                if ((compressedFlags & CompressedFlags.ScratchPad) != 0)
                {
                    len = compressedData[compressedOffset++];
                    compressedOffset += (int)len; // TODO: These offsets and length should all be UInt32
                    logMessage       += $", Scratchpad({len})";
                }

                if ((compressedFlags & CompressedFlags.HasText) != 0)
                {
                    data.Text       = BinarySerializer.DeSerializeString(compressedData, ref compressedOffset, compressedLength, 0);
                    data.TextColour = BinarySerializer.DeSerializeColor(compressedData, ref compressedOffset, compressedLength);
                    logMessage     += $", Text={data.Text}, TextColour={data.TextColour}";
                }

                if ((compressedFlags & CompressedFlags.MediaURL) != 0)
                {
                    data.MediaUrl = BinarySerializer.DeSerializeString(compressedData, ref compressedOffset, compressedLength, 0);
                    logMessage   += $", MediaUrl={data.MediaUrl}";
                }

                if ((compressedFlags & CompressedFlags.HasParticles) != 0)
                {
                    // TODO: Parse the particle system data. OpenMetaverse says that this is a BitPack of 86 bytes.
                    len = 86;
                    compressedOffset += (int)len;
                    logMessage       += $", ParticleSystem({len})";
                }

                data.ExtraParameters = BinarySerializer.DeSerializeExtraParameters(compressedData, ref compressedOffset, compressedOffset + compressedLength);

                if ((compressedFlags & CompressedFlags.HasSound) != 0)
                {
                    data.SoundId    = BinarySerializer.DeSerializeGuid(compressedData, ref compressedOffset, compressedLength);
                    data.Gain       = BinarySerializer.DeSerializeUInt32_Le(compressedData, ref compressedOffset, compressedLength);
                    data.SoundFlags = (SoundFlags)compressedData[compressedOffset++];
                    data.Radius     = BinarySerializer.DeSerializeFloat_Le(compressedData, ref compressedOffset, compressedLength);
                    logMessage     += $", SoundId={data.SoundId}, Gain={data.Gain}, SoundFlags={data.SoundFlags}, Radius={data.Radius}";
                }

                if ((compressedFlags & CompressedFlags.HasNameValues) != 0)
                {
                    data.NameValue = BinarySerializer.DeSerializeString(compressedData, ref compressedOffset, compressedLength, 0);
                    logMessage    += $", NameValue={data.NameValue}";
                }

                data.PathCurve        = (PathType)compressedData[compressedOffset++];
                data.PathBegin        = BinarySerializer.DeSerializeUInt16_Le(compressedData, ref compressedOffset, length) * CUT_QUANTA;
                data.PathEnd          = BinarySerializer.DeSerializeUInt16_Le(compressedData, ref compressedOffset, length) * CUT_QUANTA;
                data.PathScaleX       = compressedData[compressedOffset++] * SCALE_QUANTA;
                data.PathScaleY       = compressedData[compressedOffset++] * SCALE_QUANTA;
                data.PathShearX       = compressedData[compressedOffset++] * SHEAR_QUANTA;
                data.PathShearY       = compressedData[compressedOffset++] * SHEAR_QUANTA;
                data.PathTwist        = (sbyte)compressedData[compressedOffset++] * SCALE_QUANTA;
                data.PathTwistBegin   = (sbyte)compressedData[compressedOffset++] * SCALE_QUANTA;
                data.PathRadiusOffset = (sbyte)compressedData[compressedOffset++] * SCALE_QUANTA;
                data.PathTaperX       = (sbyte)compressedData[compressedOffset++] * TAPER_QUANTA;
                data.PathTaperY       = (sbyte)compressedData[compressedOffset++] * TAPER_QUANTA;
                data.PathRevolutions  = compressedData[compressedOffset++] * REV_QUANTA;
                data.PathSkew         = (sbyte)compressedData[compressedOffset++] * SCALE_QUANTA;

                data.ProfileCurve  = (ProfileType)compressedData[compressedOffset++];
                data.ProfileBegin  = BinarySerializer.DeSerializeUInt16_Le(compressedData, ref compressedOffset, length) * CUT_QUANTA;
                data.ProfileEnd    = BinarySerializer.DeSerializeUInt16_Le(compressedData, ref compressedOffset, length) * CUT_QUANTA;
                data.ProfileHollow = BinarySerializer.DeSerializeUInt16_Le(compressedData, ref compressedOffset, length) * HOLLOW_QUANTA;

                data.TextureEntry = BinarySerializer.DeSerializeTextureEntry(compressedData, ref compressedOffset, compressedLength, true);
                logMessage       += $", TextureEntry={data.TextureEntry}";

                if ((compressedFlags & CompressedFlags.TextureAnimation) != 0)
                {
                    data.TextureAnimation = BinarySerializer.DeSerializeTextureAnimation(compressedData, ref compressedOffset, compressedLength);
                    logMessage           += ", TextureAnimation";
                }

                data.IsAttachment = (compressedFlags & CompressedFlags.HasNameValues) != 0 && data.ParentId != 0;
            }
            //Logger.LogDebug("ObjectUpdateCompressedMessage.DeSerialise", logMessage);
        }
示例#30
0
        public void ReadAndWriteProtection()
        {
            MemoryPermission protection = MemoryPermission.ReadAndWrite;

            _memoryManager.OnProtect += (va, size, newProtection) =>
            {
                Assert.AreEqual((0, PageSize), (va, size)); // Should protect the exact region all the operations use.
                protection = newProtection;
            };

            RegionHandle handle = _tracking.BeginTracking(0, PageSize);

            // After creating the handle, there is no protection yet.
            Assert.AreEqual(MemoryPermission.ReadAndWrite, protection);

            bool dirtyInitial = handle.Dirty;

            Assert.True(dirtyInitial); // Handle starts dirty.

            handle.Reprotect();

            // After a reprotect, there is write protection, which will set a dirty flag when any write happens.
            Assert.AreEqual(MemoryPermission.Read, protection);

            (ulong address, ulong size)? readTrackingTriggered = null;
            handle.RegisterAction((address, size) =>
            {
                readTrackingTriggered = (address, size);
            });

            // Registering an action adds read/write protection.
            Assert.AreEqual(MemoryPermission.None, protection);

            bool dirtyAfterReprotect = handle.Dirty;

            Assert.False(dirtyAfterReprotect); // Handle is no longer dirty.

            // First we should read, which will trigger the action. This _should not_ remove write protection on the memory.

            _tracking.VirtualMemoryEvent(0, 4, false);

            bool dirtyAfterRead = handle.Dirty;

            Assert.False(dirtyAfterRead);                       // Not dirtied, as this was a read.

            Assert.AreEqual(readTrackingTriggered, (0UL, 4UL)); // Read action was triggered.

            Assert.AreEqual(MemoryPermission.Read, protection); // Write protection is still present.

            readTrackingTriggered = null;

            // Now, perform a write.

            _tracking.VirtualMemoryEvent(0, 4, true);

            bool dirtyAfterWriteAfterRead = handle.Dirty;

            Assert.True(dirtyAfterWriteAfterRead);                      // Should be dirty.

            Assert.AreEqual(MemoryPermission.ReadAndWrite, protection); // All protection is now be removed from the memory.

            Assert.IsNull(readTrackingTriggered);                       // Read tracking was removed when the action fired, as it can only fire once.

            handle.Dispose();
        }