示例#1
0
        public void TestEqual()
        {
            // Define variables and constants
            const string DOG_STRING_A = "Dog";
            const string DOG_STRING_B = "Dog";
            const string CAT_STRING   = "Cat";

            // Set up context


            // Execute
            Assure.Equal(DOG_STRING_A, DOG_STRING_B);
            try {
                Assure.Equal(DOG_STRING_A, CAT_STRING);
                Assert.Fail();
            }
            catch (AssuranceFailedException) {
            }

            Assure.Equal(1, 1);
            try {
                Assure.Equal(1, 2);
                Assert.Fail();
            }
            catch (AssuranceFailedException) {
            }

            // Assert outcome
        }
示例#2
0
        public static TOut Reinterpret <TIn, TOut>(TIn curValue, int sizeBytes)
            where TIn : struct
            where TOut : struct
        {
            Assure.Equal(SizeOf <TIn>(), SizeOf <TOut>(), "TOut must be a type of identical byte size to TIn.");
            Assure.Equal(
                sizeBytes,
                SizeOf <TIn>(),
                "Provided sizeBytes value (" + sizeBytes + ") is incorrect (sizeof(TIn) == " + SizeOf <TIn>() + ")"
                );
            Assure.True(typeof(TIn).IsBlittable(), "TIn type is not blittable.");
            Assure.True(typeof(TOut).IsBlittable(), "TOut type is not blittable.");

            TOut result = default(TOut);

            /* What I'm doing is using TypedReference as { IntPtr, IntPtr };
             * where the first IntPtr is a pointer to the __makeref referenced value type */
            TypedReference resultRef = __makeref(result);
            byte *         resultPtr = (byte *)*((IntPtr *)&resultRef);

            // Now do the same with curValue
            TypedReference curValueRef = __makeref(curValue);
            byte *         curValuePtr = (byte *)*((IntPtr *)&curValueRef);

            // Finally, copy
            for (int i = 0; i < sizeBytes; ++i)
            {
                resultPtr[i] = curValuePtr[i];
            }

            return(result);
        }
示例#3
0
 /// <summary>
 /// Builds a matrix from the values in the given array. The array slice <see cref="ArraySlice{T}.Length"/> must be
 /// exactly <c>16</c>.
 /// </summary>
 /// <param name="values">The values to build this Matrix from. The values will be interpreted in row-by-row order,
 /// i.e. the first four values will constitute <see cref="RowA"/>, the second four <see cref="RowB"/>, etc.</param>
 public Matrix(ArraySlice <float> values)
 {
     Assure.Equal(values.Length, 16);
     RowA = new Vector4(values[0], values[1], values[2], values[3]);
     RowB = new Vector4(values[4], values[5], values[6], values[7]);
     RowC = new Vector4(values[8], values[9], values[10], values[11]);
     RowD = new Vector4(values[12], values[13], values[14], values[15]);
 }
        public void MasterWaitOnExternalLock(object lockObj, Func <bool> completionPredicate)
        {
            Assure.NotNull(lockObj);
            Assure.NotNull(completionPredicate);
            Assure.True(Monitor.IsEntered(lockObj));
            Assure.Equal(Thread.CurrentThread, LosgapSystem.MasterThread);

            Monitor.Enter(externalLockObjLock);
            externalLockObj = lockObj;
            try {
                while (!completionPredicate())
                {
                    while (masterInvocationQueue.Count > 0)
                    {
                        PipelineMasterInvocation pmi;
                        if (!masterInvocationQueue.TryDequeue(out pmi))
                        {
                            continue;
                        }
                        try {
                            if (pmi.IsSynchronousCall)
                            {
                                Monitor.Enter(pmi.InvocationCompleteMonitor);
                                pmi.Action();
                            }
                            else
                            {
                                pmi.Action();
                            }
                        }
                        catch (Exception e) {
                            if (pmi.IsSynchronousCall)
                            {
                                pmi.RaisedException = e;
                            }
                            else
                            {
                                LosgapSystem.ExitWithError("Exception raised in asynchronous pipeline master invocation.", e);
                            }
                        }
                        finally {
                            if (pmi.IsSynchronousCall)
                            {
                                Monitor.Pulse(pmi.InvocationCompleteMonitor);
                                Monitor.Exit(pmi.InvocationCompleteMonitor);
                            }
                        }
                    }
                    Monitor.Exit(externalLockObjLock);
                    Monitor.Wait(lockObj);
                    Monitor.Enter(externalLockObjLock);
                }
            }
            finally {
                externalLockObj = null;
                Monitor.Exit(externalLockObjLock);
            }
        }
示例#5
0
        /// <summary>
        /// Freeze mutations to sensitive state, blocking any callers to <see cref="AcquirePermit()"/>.
        /// This method will block if mutations are currently ongoing on another thread; and will return once all active <see cref="MutationPermit"/>s
        /// have been disposed.
        /// </summary>
        public void FreezeMutations()
        {
            Assure.False(Monitor.IsEntered(freezeLock), "MutationPermits have not been disposed on current thread or mutations are already frozen.");
            Monitor.Enter(freezeLock);
            var msb = LosgapSystem.ActiveMSB;

            if (msb != null)
            {
                msb.MasterWaitOnExternalLock(freezeLock, freezeMasterBlockPredicate);
            }
            Assure.Equal(activeMutatorsCounter, 0);
        }
 public void MasterOpenBarrier()
 {
     Assure.Equal(Thread.CurrentThread, LosgapSystem.MasterThread);
     Monitor.Enter(barrierClosedLock);
     if (numSlaves > 0U)
     {
         barrierOpen     = true;
         slavesRemaining = numSlaves;
     }
     Monitor.PulseAll(barrierClosedLock);
     Monitor.Exit(barrierClosedLock);
 }
示例#7
0
        public static void WriteGenericToPtr <T>(IntPtr dest, T value, int sizeOfT) where T : struct
        {
            Assure.False(dest == IntPtr.Zero);
            Assure.True(typeof(T).IsBlittable());
            Assure.Equal(sizeOfT, (uint)SizeOf <T>());
            byte *         bytePtr  = (byte *)dest;
            TypedReference valueref = __makeref(value);
            byte *         valuePtr = (byte *)*((IntPtr *)&valueref);

            for (uint i = 0U; i < sizeOfT; ++i)
            {
                bytePtr[i] = valuePtr[i];
            }
        }
        public void MasterWaitForClose()
        {
            Assure.Equal(Thread.CurrentThread, LosgapSystem.MasterThread);
            Monitor.Enter(barrierOpenLock);

hydrateInvocationQueue:
            while (masterInvocationQueue.Count > 0)
            {
                PipelineMasterInvocation pmi;
                if (!masterInvocationQueue.TryDequeue(out pmi))
                {
                    continue;
                }
                try {
                    if (pmi.IsSynchronousCall)
                    {
                        Monitor.Enter(pmi.InvocationCompleteMonitor);
                        pmi.Action();
                    }
                    else
                    {
                        pmi.Action();
                    }
                }
                catch (Exception e) {
                    if (pmi.IsSynchronousCall)
                    {
                        pmi.RaisedException = e;
                    }
                    else
                    {
                        LosgapSystem.ExitWithError("Exception raised in asynchronous pipeline master invocation.", e);
                    }
                }
                finally {
                    if (pmi.IsSynchronousCall)
                    {
                        Monitor.Pulse(pmi.InvocationCompleteMonitor);
                        Monitor.Exit(pmi.InvocationCompleteMonitor);
                    }
                }
            }
            if (barrierOpen)
            {
                Monitor.Wait(barrierOpenLock);
                goto hydrateInvocationQueue;
            }
            Monitor.Exit(barrierOpenLock);
        }
示例#9
0
        /// <summary>
        /// Copies data from the <paramref name="source"/> pointer to the <paramref name="destination"/> array.
        /// </summary>
        /// <typeparam name="T">The array element type. Must be a <see cref="Extensions.IsBlittable">blittable</see> struct.</typeparam>
        /// <param name="source">The pointer to the source data. Must not be <see cref="IntPtr.Zero"/>.</param>
        /// <param name="destination">The destination array to which the data will be copied. This method will copy
        /// <see cref="ArraySlice{T}.Length"/> elements' worth of data, starting at the <see cref="ArraySlice{T}.Offset"/>.</param>
        /// <param name="arrayElementSizeBytes">The size of <typeparamref name="T"/>. Use either sizeof() (preferred), or
        /// <see cref="SizeOf{T}"/> if the type is not known at compile-time.</param>
        public static unsafe void CopyGenericArray <T>(IntPtr source, ArraySlice <T> destination, uint arrayElementSizeBytes) where T : struct
        {
            Assure.False(source == IntPtr.Zero);
            Assure.True(typeof(T).IsBlittable());
            Assure.Equal((int)arrayElementSizeBytes, SizeOf <T>());
            GCHandle pinnedArrayHandle = GCHandle.Alloc(destination.ContainingArray, GCHandleType.Pinned);

            try {
                MemCopy(source,
                        pinnedArrayHandle.AddrOfPinnedObject() + (int)(arrayElementSizeBytes * destination.Offset), destination.Length * arrayElementSizeBytes);
            }
            finally {
                pinnedArrayHandle.Free();
            }
        }
示例#10
0
        public static T ReadGenericFromPtr <T>(IntPtr source, int sizeOfT) where T : struct
        {
            Assure.False(source == IntPtr.Zero);
            Assure.True(typeof(T).IsBlittable());
            Assure.Equal(sizeOfT, (uint)SizeOf <T>());
            byte *bytePtr = (byte *)source;
            T     result  = default(T);

            TypedReference resultRef = __makeref(result);
            byte *         resultPtr = (byte *)*((IntPtr *)&resultRef);

            for (uint i = 0U; i < sizeOfT; ++i)
            {
                resultPtr[i] = bytePtr[i];
            }

            return(result);
        }
示例#11
0
        public void Execute(int numAtomics, int blockSize, Action <int> atomicAction)
        {
            Assure.Equal(Thread.CurrentThread, LosgapSystem.MasterThread, "Execution of parallel processor should be from master thread.");
            Assure.NotNull(atomicAction);

            currentAction    = atomicAction;
            currentBlockSize = blockSize;
            int numFullBlocks = numAtomics / blockSize;

            numReservableBlocks          = numFullBlocks;
            currentWorkIsInvokeAllAction = false;

            bool singleThreadedMode = ForceSingleThreadedMode;

            if (!singleThreadedMode)
            {
                WorkBarrier.MasterOpenBarrier();
            }

            // Do the 'odd-sized' ending block
            for (int i = blockSize * numFullBlocks; i < numAtomics; ++i)
            {
                atomicAction(i);
            }

            for (int blockIndex = Interlocked.Decrement(ref numReservableBlocks);
                 blockIndex >= 0;
                 blockIndex = Interlocked.Decrement(ref numReservableBlocks))
            {
                int blockStartInc = currentBlockSize * blockIndex;
                int blockEndEx    = currentBlockSize * (blockIndex + 1);

                for (int i = blockStartInc; i < blockEndEx; ++i)
                {
                    currentAction(i);
                }
            }

            if (!singleThreadedMode)
            {
                WorkBarrier.MasterWaitForClose();
            }
        }
示例#12
0
        /// <summary>
        /// Invokes the given <paramref name="action"/> on all slave threads, and also the master thread (invoking thread) if
        /// <paramref name="includeMaster"/> is <c>true</c>.
        /// </summary>
        /// <remarks>This method can only be invoked from the <see cref="LosgapSystem.MasterThread"/>.</remarks>
        /// <param name="action">The action to invoke on all threads. Must not be null.</param>
        /// <param name="includeMaster">True if this action should be executed by the calling (master) thread as well.</param>
        public void InvokeOnAll(Action action, bool includeMaster)
        {
            Assure.Equal(Thread.CurrentThread, LosgapSystem.MasterThread, "Invocation of parallel processor should be from master thread.");
            Assure.NotNull(action);

            currentInvokeAllAction       = action;
            currentWorkIsInvokeAllAction = true;

            bool singleThreadedMode = ForceSingleThreadedMode;

            if (!singleThreadedMode)
            {
                WorkBarrier.MasterOpenBarrier();
            }
            if (includeMaster)
            {
                currentInvokeAllAction();
            }
            if (!singleThreadedMode)
            {
                WorkBarrier.MasterWaitForClose();
            }
        }
示例#13
0
 private bool FreezeMasterBlockPredicate()
 {
     Assure.True(Monitor.IsEntered(freezeLock));
     Assure.Equal(Thread.CurrentThread, LosgapSystem.MasterThread);
     return(activeMutatorsCounter == 0);
 }
示例#14
0
        /// <summary>
        /// Determines the first point on the cuboid that is touched by this ray.
        /// </summary>
        /// <param name="other">The cuboid to test for intersection with this ray.</param>
        /// <returns>A <see cref="Vector3"/> indicating the first point on the cuboid edge touched by this ray,
        /// or <c>null</c> if no intersection occurs.</returns>
        // Based on "Fast Ray-Box Intersection" algorithm by Andrew Woo, "Graphics Gems", Academic Press, 1990
        public unsafe Vector3?IntersectionWith(Cuboid other)
        {
            const int NUM_DIMENSIONS = 3;

            Assure.Equal(NUM_DIMENSIONS, 3);             // If that value is ever changed, this algorithm will need some maintenance

            const byte QUADRANT_MIN     = 0;
            const byte QUADRANT_MAX     = 1;
            const byte QUADRANT_BETWEEN = 2;

            // Step 1: Work out which direction from the start point to test for intersection for all 3 dimensions, and the distance
            byte * quadrants                = stackalloc byte[NUM_DIMENSIONS];
            float *candidatePlanes          = stackalloc float[NUM_DIMENSIONS];
            float *cuboidMinPoints          = stackalloc float[NUM_DIMENSIONS];
            float *cuboidMaxPoints          = stackalloc float[NUM_DIMENSIONS];
            bool   startPointIsInsideCuboid = true;

            cuboidMinPoints[0] = other.FrontBottomLeft.X;
            cuboidMinPoints[1] = other.FrontBottomLeft.Y;
            cuboidMinPoints[2] = other.FrontBottomLeft.Z;
            cuboidMaxPoints[0] = other.FrontBottomLeft.X + other.Width;
            cuboidMaxPoints[1] = other.FrontBottomLeft.Y + other.Height;
            cuboidMaxPoints[2] = other.FrontBottomLeft.Z + other.Depth;

            for (byte i = 0; i < NUM_DIMENSIONS; ++i)
            {
                if (StartPoint[i] < cuboidMinPoints[i])
                {
                    quadrants[i]             = QUADRANT_MIN;
                    candidatePlanes[i]       = cuboidMinPoints[i];
                    startPointIsInsideCuboid = false;
                }
                else if (StartPoint[i] > cuboidMaxPoints[i])
                {
                    quadrants[i]             = QUADRANT_MAX;
                    candidatePlanes[i]       = cuboidMaxPoints[i];
                    startPointIsInsideCuboid = false;
                }
                else
                {
                    quadrants[i] = QUADRANT_BETWEEN;
                }
            }

            if (startPointIsInsideCuboid)
            {
                return(StartPoint);
            }

            // Step 2: Find farthest dimension from cuboid
            float maxDistance          = Single.NegativeInfinity;
            byte  maxDistanceDimension = 0;

            for (byte i = 0; i < NUM_DIMENSIONS; ++i)
            {
                // ReSharper disable once CompareOfFloatsByEqualityOperator Exact check is desired here: Anything other than 0f is usable
                if (quadrants[i] != QUADRANT_BETWEEN && Orientation[i] != 0f)
                {
                    float thisDimensionDist = (candidatePlanes[i] - StartPoint[i]) / Orientation[i];
                    if (thisDimensionDist > maxDistance)
                    {
                        maxDistance          = thisDimensionDist;
                        maxDistanceDimension = i;
                    }
                }
            }

            float errorMargin = MathUtils.FlopsErrorMargin;

            if (maxDistance < 0f || maxDistance - Length > errorMargin)
            {
                return(null);
            }

            // Step 3: Find potential intersection point
            float *intersectionPoint = stackalloc float[NUM_DIMENSIONS];

            for (byte i = 0; i < NUM_DIMENSIONS; ++i)
            {
                if (maxDistanceDimension == i)
                {
                    intersectionPoint[i] = StartPoint[i] + maxDistance * Orientation[i];
                    if (cuboidMinPoints[i] - intersectionPoint[i] > errorMargin || intersectionPoint[i] - cuboidMaxPoints[i] > errorMargin)
                    {
                        return(null);
                    }
                }
                else
                {
                    intersectionPoint[i] = candidatePlanes[i];
                }
            }

            Vector3 result = new Vector3(intersectionPoint[0], intersectionPoint[1], intersectionPoint[2]);

            if (!IsInfiniteLength && Vector3.DistanceSquared(StartPoint, result) > Length * Length + errorMargin * errorMargin)
            {
                return(null);
            }
            else if (!Contains(result))
            {
                return(null);
            }
            else
            {
                return(result);
            }
        }