private static void InvokeOnMaster(Action action, bool synchronous)
        {
            Assure.NotNull(action);
            PipelineProcessor processorLocal;

            lock (staticMutationLock) {
                if (!IsRunning)
                {
                    try {
                        ThrowIfCurrentThreadIsNotMaster();
                    }
                    catch (InvalidOperationException e) {
                        throw new InvalidOperationException("Can not execute given operation from any thread but the master when the " +
                                                            "pipeline is not running. Either start the system or move the operation to the master thread.", e);
                    }
                    action();
                    return;
                }
                processorLocal = processor;
            }
            PipelineMasterInvocation pmi = PipelineMasterInvocation.Create(action, synchronous);

            processorLocal.InvokeOnMaster(pmi);
            if (pmi.IsSynchronousCall)
            {
                if (pmi.RaisedException != null)
                {
                    ExceptionDispatchInfo.Capture(pmi.RaisedException).Throw();
                }
                PipelineMasterInvocation.Free(pmi);
            }
        }
示例#2
0
        public void TestNotNull()
        {
            // ReSharper disable ExpressionIsAlwaysNull
            // Define variables and constants
            object nonNullObj = new object();
            object nullObj    = null;
            int?   nonNullInt = 3;
            int?   nullInt    = null;

            // Set up context


            // Execute
            Assure.NotNull(nonNullObj);
            try {
                Assure.NotNull(nullObj);
                Assert.Fail();                 // Should throw the exception
            }
            catch (AssuranceFailedException) { }

            Assure.NotNull(nonNullInt);
            try {
                Assure.NotNull(nullInt);
                Assert.Fail();                 // Should throw the exception
            }
            catch (AssuranceFailedException) { }

            // Assert outcome

            // ReSharper restore ExpressionIsAlwaysNull
        }
        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);
            }
        }
        /// <summary>
        /// Invokes the given <paramref name="func"/> on the <see cref="MasterThread"/> (that is the thread that <see cref="Start"/> was called from).
        /// This function can create a heavy performance hit for the current frame, so it should only be used when necessary.
        /// </summary>
        /// <remarks>
        /// Call this method when you must ensure that all accesses to a particular resource must occur from the same thread (for example,
        /// when working with the Windows API GDI+ message pump).
        /// <para>
        /// This method will block until the <paramref name="func"/> has been completed. Any exceptions that occur when invoking
        /// <paramref name="func"/> will be thrown back to the caller.
        /// </para>
        /// </remarks>
        /// <typeparam name="TResult">The return type of the <paramref name="func"/>.</typeparam>
        /// <param name="func">The function to invoke on the <see cref="MasterThread"/>.</param>
        /// <returns>The <typeparamref name="TResult"/> returned from the invocation of <paramref name="func"/>.</returns>
        public static TResult InvokeOnMaster <TResult>(Func <TResult> func)
        {
            Assure.NotNull(func);
            TResult result = default(TResult);

            InvokeOnMaster(() => {
                result = func();
            });
            return(result);
        }
 /// <summary>
 /// Creates a new array slice that refers to <paramref name="count"/> elements in the given <paramref name="containingArray"/>,
 /// starting from the element at index <paramref name="offset"/>.
 /// </summary>
 /// <param name="containingArray">The array to represent. Must not be null.</param>
 /// <param name="offset">The index of the first element in <paramref name="containingArray"/> to include in this slice.</param>
 /// <param name="count">The number of elements in <paramref name="containingArray"/> to include in this slice.</param>
 public ArraySlice(T[] containingArray, uint offset, uint count)
 {
     Assure.NotNull(containingArray);
     Assure.LessThanOrEqualTo(
         offset + count,
         containingArray.Length,
         "offset + count must be less than or equal to the containing array's length."
         );
     this.ContainingArray = containingArray;
     this.Offset          = offset;
     this.Length          = count;
 }
示例#6
0
 /// <summary>
 /// Get all types that inherit from / implement the given <paramref name="parent"/>.
 /// </summary>
 /// <param name="parent">The parent to find implementers/inheritors of. Must not be null.</param>
 /// <param name="includeParent">If <c>true</c>, the parent type will be included in the returned <see cref="IEnumerable{T}"/>. Set to
 /// <c>false</c> to only include child types.</param>
 /// <returns>An enumeration of types that inherit from or implement the given <paramref name="parent"/>.</returns>
 public static IEnumerable <Type> GetChildTypes(Type parent, bool includeParent = true)
 {
     Assure.NotNull(parent);
     if (includeParent)
     {
         return(allReferencedTypes.Where(parent.IsAssignableFrom));
     }
     else
     {
         return(allReferencedTypes.Where(parent.IsAssignableFrom).Except(new[] { parent }));
     }
 }
        public static Quaternion CombineRotations(params Quaternion[] rotations)
        {
            Assure.NotNull(rotations);
            Assure.GreaterThan(rotations.Length, 0, "Can not supply an empty array to combine rotations.");
            Quaternion result = rotations[0];

            for (int i = 1; i < rotations.Length; i++)
            {
                result *= rotations[i];
            }
            return(result);
        }
示例#8
0
        public static Vector2 Parse(string vectorString)
        {
            Assure.NotNull(vectorString);
            try {
                string[] numericComponents = vectorString.Trim('[', ']').Split(',');
                float    x = float.Parse(numericComponents[0].Trim(), CultureInfo.InvariantCulture);
                float    y = float.Parse(numericComponents[1].Trim(), CultureInfo.InvariantCulture);

                return(new Vector2(x, y));
            }
            catch (Exception e) {
                throw new FormatException("Could not parse vector string.", e);
            }
        }
示例#9
0
        public static Quaternion Parse(string quaternionString)
        {
            Assure.NotNull(quaternionString);
            try {
                string[] components = quaternionString.Trim('<', '>').Split('~');
                Vector3  xyz        = Vector3.Parse(components[0].Trim());
                float    w          = float.Parse(components[1].Trim(), CultureInfo.InvariantCulture);

                return(new Quaternion(new Vector4(xyz, w: w)));
            }
            catch (Exception e) {
                throw new FormatException("Could not parse transform string.", e);
            }
        }
示例#10
0
        public static Transform Parse(string transformString)
        {
            Assure.NotNull(transformString);
            try {
                string[]   components  = transformString.Trim('(', ')').Split('|');
                Vector3    scale       = Vector3.Parse(components[0].Split(':')[1].Trim());
                Quaternion rotation    = Quaternion.Parse(components[1].Split(':')[1].Trim());
                Vector3    translation = Vector3.Parse(components[2].Split(':')[1].Trim());

                return(new Transform(scale, rotation, translation));
            }
            catch (Exception e) {
                throw new FormatException("Could not parse transform string.", e);
            }
        }
示例#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
            internal MutationPermit(StateMutationBarrier barrier, object additionalLockObject)
            {
                Assure.NotNull(barrier);
                if (Monitor.IsEntered(barrier.freezeLock))
                {
                    throw new ApplicationException("Can not acquire permit: Mutations are locked from current thread.");
                }
#if DEBUG
                isDisposed = false;
#endif
                this.barrier = barrier;
                this.additionalLockObject = additionalLockObject;
                lock (barrier.freezeLock) {
                    ++barrier.activeMutatorsCounter;
                }
                if (additionalLockObject != null)
                {
                    Monitor.Enter(additionalLockObject);
                }
            }
        public void SlaveQueueOnMaster(PipelineMasterInvocation pmi)
        {
            Assure.NotNull(pmi);
            Assure.NotEqual(Thread.CurrentThread, LosgapSystem.MasterThread);
            Monitor.Enter(barrierOpenLock);
            masterInvocationQueue.Enqueue(pmi);
            Monitor.Pulse(barrierOpenLock);
            object externalLockObjLocal;

            lock (externalLockObjLock) {
                externalLockObjLocal = externalLockObj;
            }
            Monitor.Exit(barrierOpenLock);
            if (externalLockObjLocal != null)
            {
                Monitor.Enter(externalLockObjLocal);
                Monitor.PulseAll(externalLockObjLocal);
                Monitor.Exit(externalLockObjLocal);
            }
        }
示例#14
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();
            }
        }
        public virtual void WriteMessage(LogMessageSeverity messageSeverity, string message, Exception associatedException, string callerMemberName, string callerFilePath, int callerLineNumber)
        {
            Assure.NotNull(message);
            Assure.NotNull(callerMemberName);
            Assure.NotNull(callerFilePath);
            message = message.Replace(Environment.NewLine, Environment.NewLine + STACK_TRACE_LINE_PREFIX);

            lock (InstanceMutationLock) {
                if (IsDisposed)
                {
                    return;                             // Safest option: No point throwing exceptions if some random component elicits a warning on shutdown
                }
                if (currentFileStreamWriter == null)
                {
                    throw new InvalidOperationException("Can not write log line: No log file location has successfully been set on this logging provider!");
                }

                logLineBuilder.Clear();

                if (AddTimestamps)
                {
                    logLineBuilder.Append(DateTime.Now.ToString(TIMESTAMP_FORMAT));
                    logLineBuilder.Append("\t");
                }

                switch (messageSeverity)
                {
                case LogMessageSeverity.Standard:
                    logLineBuilder.Append(STANDARD_LOG_PREFIX);
                    break;

                case LogMessageSeverity.Debug:
                    logLineBuilder.Append(DEBUG_LOG_PREFIX);
                    break;

                case LogMessageSeverity.Warning:
                    logLineBuilder.Append(WARNING_LOG_PREFIX);
                    break;

                case LogMessageSeverity.Fatal:
                    logLineBuilder.Append(FATAL_LOG_PREFIX);
                    break;
                }

                logLineBuilder.Append(message);

                if (AppendCaller)
                {
                    logLineBuilder.Append(" <= ");
                    logLineBuilder.Append(callerMemberName);
                    if (IncludeDetailedCallerInfo)
                    {
                        logLineBuilder.Append("() in ");
                        logLineBuilder.Append(Path.GetFileName(callerFilePath));
                        logLineBuilder.Append(":");
                        logLineBuilder.Append(callerLineNumber);
                    }
                    else
                    {
                        logLineBuilder.Append("()");
                    }
                }

                if (associatedException != null)
                {
                    logLineBuilder.AppendLine();

                    associatedException.ForEachException(e => {
                        logLineBuilder.Append(ASSOCIATED_EXCEPTION_PREFIX);
                        logLineBuilder.AppendLine(associatedException.GetAllMessages(true).Replace(Environment.NewLine, " "));

                        if (e is ExternalException)
                        {
                            logLineBuilder.Append(STACK_TRACE_LINE_PREFIX);
                            logLineBuilder.AppendLine("** External exception code: 0x" + (e as ExternalException).ErrorCode.ToString("x").ToUpper());
                        }

                        if (e.StackTrace != null)
                        {
                            foreach (string line in e.StackTrace.Split(Environment.NewLine)
                                     .Select(line => line.Trim())
                                     .Where(line => !line.IsNullOrWhiteSpace()))
                            {
                                logLineBuilder.Append(STACK_TRACE_LINE_PREFIX);
                                logLineBuilder.AppendLine(line);
                            }
                        }
                        else
                        {
                            logLineBuilder.Append(STACK_TRACE_LINE_PREFIX);
                            logLineBuilder.AppendLine("<No stack trace>");
                        }
                    });
                }

                logLineBuilder.AppendLine();

#if !RELEASE && !DEVELOPMENT
                try {
                    currentFileStreamWriter.Write(logLineBuilder);
                    currentFileStreamWriter.Flush();
                }
                catch (Exception e) {
                    Assure.Fail("Could not write message to log file. Exception: " + e.GetAllMessages());
                    throw;
                }
#else
                currentFileStreamWriter.Write(logLineBuilder);
                currentFileStreamWriter.Flush();
#endif

                BroadcastMessage(messageSeverity, message, associatedException);
            }
        }