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); } }
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; }
/// <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); }
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); } }
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); } }
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); } }
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(); } }
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); } }
/// <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); } }