예제 #1
0
        public void RefCountedPipeline()
        {
            var sharedPool = new SharedPool <int[]>(() => new int[ArraySize], ParallelBranchCount * TransformCount);

            this.RunPipeline <Shared <int[]> >(
                create: i => sharedPool.GetOrCreate(),
                initialize: (old, i) =>
            {
                old.Dispose();
                var tgt = sharedPool.GetOrCreate();
                Set(tgt.Resource, i);
                return(tgt);
            },
                increment: (old, a) =>
            {
                old.Dispose();
                var tgt = sharedPool.GetOrCreate();
                Inc(tgt.Resource, a.Resource, 1);
                return(tgt);
            },
                add: (old, a, b) =>
            {
                old.Dispose();
                var tgt = sharedPool.GetOrCreate();
                Add(tgt.Resource, a.Resource, b.Resource);
                return(tgt);
            },
                extract: a => a.Resource[0],
                validateNoLoss: true,
                validateSync: false);
        }
예제 #2
0
        public void RefCountedTest()
        {
            var sharedPool = new SharedPool <UnmanagedBuffer>(() => UnmanagedBuffer.Allocate(100), 1);
            var shared     = sharedPool.GetOrCreate(); // refcount = 1

            // a private copy shoudl point to the same resource
            var otherShared = shared.DeepClone(); // refcount = 1 + 1

            Assert.AreNotEqual(shared, otherShared);
            Assert.AreEqual(shared.Inner, otherShared.Inner);
            Assert.AreEqual(shared.Resource, otherShared.Resource);

            // a clone should point to the same resource, but should not reuse the container
            var cloned = otherShared;

            Serializer.Clone(shared, ref cloned, new SerializationContext()); // refcount = 2 - 1 + 1
            Assert.AreNotEqual(shared, cloned);
            Assert.AreEqual(shared.Inner, cloned.Inner);
            Assert.AreEqual(shared.Resource, cloned.Resource);

            // disposing should not affect other copies
            shared.Dispose(); // refcount = 2 - 1
            Assert.AreEqual(0, sharedPool.AvailableCount);
            Assert.IsNull(shared.Inner);
            Assert.IsNull(shared.Resource);
            Assert.IsNotNull(cloned.Inner);
            Assert.IsNotNull(cloned.Resource);

            // disposing the last copy should return the resource to the pool
            cloned.Dispose(); // refcount = 1 - 1
            Assert.AreEqual(1, sharedPool.AvailableCount);
            Assert.IsNull(cloned.Inner);
            Assert.IsNull(cloned.Resource);
        }
예제 #3
0
        public void JoinOfShared()
        {
            var sum = 0;

            using (var p = Pipeline.Create())
            {
                var pool = new SharedPool <int[]>(() => new int[1], 1);
                var g    = Generators.Range(p, 0, 10);
                var s1   = g.Process <int, Shared <int[]> >(
                    (i, e, emitter) =>
                {
                    using (var shared = pool.GetOrCreate())
                    {
                        shared.Resource[0] = i;
                        emitter.Post(shared, e.OriginatingTime);
                    }
                });

                var j = s1.Join(g);
                j.Select(t => t.Item2 - t.Item1.Resource[0]).Do(v => sum = sum + v);
                p.Run();

                Assert.AreEqual(0, sum);
                Assert.IsTrue(pool.TotalCount > 0);
                Assert.AreEqual(pool.TotalCount, pool.AvailableCount);
            }
        }
예제 #4
0
        public void SerializeGraph()
        {
            var buffer = new BufferWriter(100);
            var pool   = new SharedPool <byte[]>(() => new byte[10], 1);

            Shared <byte[]> s = pool.GetOrCreate();

            s.Resource[0] = 255;
            s.Resource[9] = 128;

            var t = Tuple.Create(s, s);

            Serializer.Serialize(buffer, t, new SerializationContext());
            Tuple <Shared <byte[]>, Shared <byte[]> > target = null;

            Serializer.Deserialize(new BufferReader(buffer.Buffer), ref target, new SerializationContext());

            Assert.ReferenceEquals(target.Item1, target.Item2);
            Assert.AreEqual(255, target.Item1.Resource[0]);
            Assert.AreEqual(0, target.Item1.Resource[1]);
            Assert.AreEqual(0, target.Item1.Resource[8]);
            Assert.AreEqual(128, target.Item1.Resource[9]);
            s.Dispose();
            target.Item1.Dispose();
        }
예제 #5
0
        public void AddRefReleaseTest()
        {
            SharedPool <object> pool = new SharedPool <object>(() => new int?(1234), 1);

            // Verify that nothing is available (no objects have been allocated in the pool yet)
            Assert.AreEqual(pool.AvailableCount, 0);

            // Create our first object
            var origObj = pool.GetOrCreate();

            Assert.AreEqual(pool.TotalCount, 1);     // One object in pool
            Assert.AreEqual(pool.AvailableCount, 0); // None available for use (since only object is in use)

            // Take another reference on the object
            var refObj = origObj.AddRef();

            // Sanity check that underlying resource is the same
            Assert.AreEqual(refObj.Resource, 1234);
            Assert.AreEqual(origObj.Resource, 1234);

            // Get rid of our second reference. There should still be none available
            // in the pool since the refObj.inner hasn't been released yet
            refObj.Dispose();
            Assert.AreEqual(pool.AvailableCount, 0);

            // Next release the original object. Now everything should be released
            origObj.Dispose();
            Assert.AreEqual(pool.AvailableCount, 1);

            Assert.AreEqual(origObj.Inner, null);
        }
예제 #6
0
        public void PipelineOfShared()
        {
            int sum = 0;

            using (var p = Pipeline.Create())
            {
                var pool = new SharedPool <int[]>(1);
                var g    = Generators
                           .Range(p, 0, 10)
                           .Process <int, Shared <int[]> >(
                    (i, e, emitter) =>
                {
                    using (var shared = pool.GetOrCreate(() => new int[1]))
                    {
                        shared.Resource[0] = i;
                        emitter.Post(shared, e.OriginatingTime);
                    }
                });
                g.Select(a => a.Resource[0]).Do(v => sum = sum + v);
                p.Run();

                Assert.AreEqual(5 * 9, sum);
                Assert.IsTrue(pool.TotalCount > 0);
                Assert.AreEqual(pool.TotalCount, pool.AvailableCount);
            }
        }
예제 #7
0
        public void Serialize()
        {
            var buffer = new BufferWriter(100);
            var pool   = new SharedPool <byte[]>(() => new byte[10], 1);

            Shared <byte[]> s = pool.GetOrCreate();

            s.Resource[0] = 255;
            s.Resource[9] = 128;

            Shared <byte[]> s2 = pool.GetOrCreate();

            s2.Resource[0] = 1;
            s2.Resource[9] = 1;

            // serialize twice
            Serializer.Serialize(buffer, s, new SerializationContext());
            Serializer.Serialize(buffer, s2, new SerializationContext());
            Shared <byte[]> target = null;
            var             reader = new BufferReader(buffer.Buffer);

            Serializer.Deserialize(reader, ref target, new SerializationContext());

            Assert.AreEqual(255, target.Resource[0]);
            Assert.AreEqual(0, target.Resource[1]);
            Assert.AreEqual(0, target.Resource[8]);
            Assert.AreEqual(128, target.Resource[9]);

            // deserialize again reusing the first instance, make sure the first instance is not trampled over
            var firstTarget = target.AddRef();

            Serializer.Deserialize(reader, ref target, new SerializationContext());
            Assert.IsFalse(object.ReferenceEquals(firstTarget, target));
            Assert.IsFalse(object.ReferenceEquals(firstTarget.Inner, target.Inner));
            Assert.IsFalse(object.ReferenceEquals(firstTarget.Resource, target.Resource));
            Assert.AreEqual(1, target.Resource[0]);
            Assert.AreEqual(0, target.Resource[1]);
            Assert.AreEqual(0, target.Resource[8]);
            Assert.AreEqual(1, target.Resource[9]);

            // this should not throw, since refcount should be 1 on both
            firstTarget.Dispose();
            target.Dispose();
        }
예제 #8
0
        public void DoubleDispose()
        {
            var sharedPool = new SharedPool <UnmanagedBuffer>(() => UnmanagedBuffer.Allocate(100), 1);
            var shared     = sharedPool.GetOrCreate();

            shared.Dispose();
            try
            {
                shared.Dispose();
                Assert.Fail("Expected an exception from the second Dispose call");
            }
            catch (Exception e)
            {
                Assert.IsTrue(e is ObjectDisposedException);
            }
        }
예제 #9
0
        public void RecyclerPerf()
        {
            var sharedPool = new SharedPool <UnmanagedBuffer>(() => UnmanagedBuffer.Allocate(100), 1);
            var shared     = sharedPool.GetOrCreate();

            shared.Dispose();

            Stopwatch sw         = Stopwatch.StartNew();
            int       iterations = 10;

            for (int i = 0; i < iterations; i++)
            {
                sharedPool.TryGet(out shared);
                shared.Dispose();
            }

            sw.Stop();
            Console.WriteLine($"Get + Release = {sw.ElapsedMilliseconds * 1000000d / iterations} ns");
        }
예제 #10
0
        // [TestMethod, Timeout(60000)]
        public void RefCountedFinalizationTest()
        {
            var sharedPool  = new SharedPool <UnmanagedBuffer>(() => UnmanagedBuffer.Allocate(100), 1);
            var shared      = sharedPool.GetOrCreate();
            var otherShared = shared.DeepClone();

            shared = null;

            // after GC and finalization, the live copy is not affected
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Assert.AreNotEqual(IntPtr.Zero, otherShared.Resource.Data);
            otherShared = null;

            // after GC and finalization of all live copies, the resource goes back to the pool without being finalized itself
            GC.Collect();
            GC.WaitForPendingFinalizers();
            var wasRecycled = sharedPool.TryGet(out shared);

            Assert.IsTrue(wasRecycled);
            Assert.IsNotNull(shared.Resource);
            Assert.AreNotEqual(IntPtr.Zero, shared.Resource.Data);
        }
예제 #11
0
        public void DeserializePooled()
        {
            const int iterations = 10;
            var       writer     = new BufferWriter(100);
            var       pool       = new SharedPool <byte[]>(() => new byte[10], 1);

            using (var s = pool.GetOrCreate())
            {
                for (int i = 0; i < iterations; i++)
                {
                    Serializer.Serialize(writer, s, new SerializationContext());
                }
            }

            // the array should be back in the pool
            Assert.AreEqual(1, pool.AvailableCount);
            Assert.AreEqual(1, pool.TotalCount);

            var reader = new BufferReader(writer.Buffer);

            Assert.IsTrue(pool.TryGet(out Shared <byte[]> s2), "Expected a free entry in the pool!");
            for (int i = 0; i < iterations; i++)
            {
                Serializer.Deserialize(reader, ref s2, new SerializationContext());

                // verify that the pool doesn't grow
                Assert.AreEqual(pool, s2.SharedPool);
                Assert.AreEqual(0, pool.AvailableCount);
                Assert.AreEqual(1, pool.TotalCount);
            }

            s2.Dispose();

            // disposing the last deserialized shared should release the array back to the pool
            Assert.AreEqual(1, pool.AvailableCount);
        }
예제 #12
0
        /// <summary>
        /// Called once all the subscriptions are established.
        /// </summary>
        private unsafe void OnPipelineStart()
        {
            this.camera = new MediaCaptureInternal(this.configuration.DeviceId);
            this.camera.Open();
            var isFormatSupported = false;

            foreach (var format in this.camera.SupportedPixelFormats())
            {
                if (format.Pixels == this.configuration.PixelFormat)
                {
                    this.camera.SetVideoFormat(this.configuration.Width, this.configuration.Height, format);
                    isFormatSupported = true;
                }
            }

            if (!isFormatSupported)
            {
                throw new ArgumentException($"Pixel format {this.configuration.PixelFormat} is not supported by the camera");
            }

            var current = this.camera.GetVideoFormat();

            if (current.Width != this.configuration.Width || current.Height != this.configuration.Height)
            {
                throw new ArgumentException($"Width/height {this.configuration.Width}x{this.configuration.Height} is not supported by the camera");
            }

            this.camera.OnFrame += (_, frame) =>
            {
                var originatingTime = this.pipeline.GetCurrentTime();

                if (this.Raw.HasSubscribers)
                {
                    var len = frame.Length;
                    using (Shared <byte[]> shared = RawPool.GetOrCreate(() => new byte[len]))
                    {
                        var buffer = shared.Resource.Length >= len ? shared : new Shared <byte[]>(new byte[len], shared.Recycler);
                        Marshal.Copy(frame.Start, buffer.Resource, 0, len);
                        this.Raw.Post(buffer, originatingTime);
                    }
                }

                if (this.Out.HasSubscribers)
                {
                    using (var sharedImage = ImagePool.GetOrCreate(this.configuration.Width, this.configuration.Height, PixelFormat.BGR_24bpp))
                    {
                        if (this.configuration.PixelFormat == PixelFormatId.BGR24)
                        {
                            sharedImage.Resource.CopyFrom((IntPtr)frame.Start);
                            this.Out.Post(sharedImage, this.pipeline.GetCurrentTime());
                        }
                        else if (this.configuration.PixelFormat == PixelFormatId.YUYV)
                        {
                            // convert YUYV -> BGR24 (see https://msdn.microsoft.com/en-us/library/ms893078.aspx)
                            var len = (int)(frame.Length * 1.5);
                            using (Shared <byte[]> shared = RawPool.GetOrCreate(() => new byte[len]))
                            {
                                var buffer = shared.Resource.Length >= len ? shared : new Shared <byte[]>(new byte[len], shared.Recycler);
                                var bytes  = buffer.Resource;
                                var pY     = (byte *)frame.Start.ToPointer();
                                var pU     = pY + 1;
                                var pV     = pY + 2;
                                for (var i = 0; i < len;)
                                {
                                    var y = (*pY - 16) * 298;
                                    var u = *pU - 128;
                                    var v = *pV - 128;
                                    var b = (y + (516 * u) + 128) >> 8;
                                    var g = (y - (100 * u) - (208 * v) + 128) >> 8;
                                    var r = (y + (409 * v) + 128) >> 8;
                                    bytes[i++] = (byte)(b < 0 ? 0 : b > 255 ? 255 : b);
                                    bytes[i++] = (byte)(g < 0 ? 0 : g > 255 ? 255 : g);
                                    bytes[i++] = (byte)(r < 0 ? 0 : r > 255 ? 255 : r);
                                    pY        += 2;
                                    pU        += 4;
                                    pV        += 4;
                                }

                                this.Raw.Post(buffer, originatingTime);
                            }
                        }
                    }
                }

#if TEST_DROPPED_FRAMES
                System.Threading.Thread.Sleep(1000); // for testing dropped frames
#endif // TEST_DROPPED_FRAMES

                frame.Dispose(); // release back to driver!
            };

            this.camera.StreamBuffers();
        }
예제 #13
0
 /// <summary>
 /// Gets or creates an encoded image from the pool.
 /// </summary>
 /// <returns>A shared encoded image from the pool.</returns>
 public static Shared <EncodedImage> GetOrCreate()
 {
     return(Instance.GetOrCreate());
 }