public void AppendFormat(ReadOnlySpan <char> format, double value, IFormatProvider provider) { bool ok = value.TryFormat(m_remaining, out int written, format: format, provider: provider); CoreException.Assert(ok); m_remaining = m_remaining.Slice(written); }
public void AppendFormat(ReadOnlySpan <char> format, byte value) { bool ok = value.TryFormat(m_remaining, out int written, format: format); CoreException.Assert(ok); m_remaining = m_remaining.Slice(written); }
/// <summary> /// Enqueue a list of actions to be performed concurrently; calls continuation(continuationArgument) when all completed /// </summary> public static void ForEachAction(string name, ReadOnlySpan <Action <object> > works, object argument, Action <object> continuation, object continuationArgument) { CoreException.Assert(s_workers != null, "JobService not initialized"); int numJobs = works.Length; if (numJobs == 0) { return; } if (numJobs == 1) { lock (s_instances) EnqueueInternal(name, works[0], argument); return; } var completion = JobCompletion.Acquire(); completion.ContinuationAtCount = numJobs; completion.Continuation = continuation; completion.ContinuationArgument = continuationArgument; #if DEBUG completion.ContinuationName = name + "Contd"; #endif lock (s_instances) { foreach (var work in works) { EnqueueInternal(name, work, argument, completion); } } }
public void Append(int value) { bool ok = value.TryFormat(m_remaining, out int written); CoreException.Assert(ok); m_remaining = m_remaining.Slice(written); }
public static void ToHex(ReadOnlySpan <byte> data, Span <char> into) { CoreException.Assert(into.Length >= data.Length * 2); for (int i = 0; i < data.Length; i++) { into[i * 2] = s_valueToHex[data[i] >> 4]; into[i * 2 + 1] = s_valueToHex[data[i] & 0b1111];
private void RunItem(object ob) { // yay; perform work var item = (IScheduleItem <TItem, TArg>)ob; item.Execute(m_runArgument); var completed = Interlocked.Increment(ref m_completedItemsCount); var idx = Array.IndexOf(m_items, item); lock (m_itemStatus) { // work completed might mean some other can now run CoreException.Assert(m_itemStatus[idx] == ItemStatus.Running); m_itemStatus[idx] = ItemStatus.Done; } if (completed == m_items.Length) { // ALL DONE! m_onCompleted(m_onCompletedArgument); return; } FireReadyJobs(); }
public static float NextFloat(ref ulong state) { uint v = (NextUInt32(ref state) & 0b01111111_11111111_11111111u) | 0x3F800000u; float zeroToOne = SingleUIntUnion.ReinterpretCast(v) - 1.0f; CoreException.Assert(zeroToOne >= 0.0f && zeroToOne < 1.0); return(zeroToOne); }
internal static void EnqueueInternal(string name, Action <object> work, object argument, JobCompletion completion = null) { #if DEBUG CoreException.Assert(Monitor.IsEntered(s_instances)); #endif int idx = (s_nextInstance + s_instancesCount) & k_instancesMask; ref var job = ref s_instances[idx];
public static double NextDouble(ref ulong state) { // generate 52 random mantissa bits and an unbiased exponent of 0 ulong dval = (NextUInt64(ref state) & 0xFFFFFFFFFFFFFUL) | 0x3FF0000000000000UL; double zeroToOne = DoubleULongUnion.ReinterpretCast(dval) - 1.0; CoreException.Assert(zeroToOne >= 0.0f && zeroToOne < 1.0); return(zeroToOne); }
public static void CheckNaN(Vector2 vector) { CoreException.Assert( float.IsNaN(vector.X) == false && float.IsNaN(vector.Y) == false && float.IsInfinity(vector.X) == false && float.IsInfinity(vector.Y) == false ); }
public void AddEntry(string name, long started, int duration) { if (duration < 0) { CoreException.Assert(duration >= 0, "AddEntry negative duration"); return; } // no need for interlocked; this is a thread local object ref var complete = ref m_completed[m_completedCount++];
public static double NextDouble(ref ulong state, double minValue, double maxValue) { CoreException.Assert(maxValue > minValue); var dval = (NextUInt64(ref state) & 0xFFFFFFFFFFFFFUL) | 0x3FF0000000000000UL; double zeroToOne = DoubleULongUnion.ReinterpretCast(dval) - 1.0; double retval = minValue + ((maxValue - minValue) * zeroToOne); CoreException.Assert(retval >= minValue && retval < maxValue); return(retval); }
public static double NextDouble(ref ulong state) { DoubleULongUnion union; union.DoubleValue = 0; union.ULongValue = (NextUInt64(ref state) & 0xFFFFFFFFFFFFFUL) | 0x3FF0000000000000UL; double zeroToOne = union.DoubleValue - 1.0; CoreException.Assert(zeroToOne >= 0.0f && zeroToOne < 1.0); return(zeroToOne); }
public void Dispose() { long now = Stopwatch.GetTimestamp(); CoreException.Assert(now >= Started); long duration = now - Started; if (duration > 0 && duration < int.MaxValue) { TimingThread.Instance.AddEntry(Name, Started, (int)duration); } }
public static byte[] FromHexArray(ReadOnlySpan <char> hexString) { if (hexString.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { hexString = hexString.Slice(2); } var bytes = new byte[hexString.Length / 2]; int len = FromHexArray(hexString, bytes); CoreException.Assert(len == bytes.Length); return(bytes); }
public static float FasterSin(float radians) { CoreException.Assert(radians >= -MathUtils.Pi && radians <= MathUtils.Pi); if (radians < 0) { return(radians * (1.27323954f + 0.405284735f * radians)); } else { return(radians * (1.27323954f - 0.405284735f * radians)); } }
public void Remove(int index, int count) { int curLen = this.Length; int tail = curLen - (index + count); CoreException.Assert(tail >= 0); m_remaining = m_buffer.Slice(curLen - count); if (tail == 0) { return; } m_buffer.Slice(index + count, tail).CopyTo(m_buffer.Slice(index, tail)); }
private void Compact() { CoreException.Assert(m_offset > 0, "Unnecessary compact!"); var buffer = m_buffer; var off = m_offset; var cnt = m_count; // TODO: compare to aliased Span.CopyTo for (int i = 0; i < cnt; i++) { buffer[i] = buffer[off + i]; } m_offset = 0; }
public static double NextDouble(ref ulong state, double minValue, double maxValue) { CoreException.Assert(maxValue > minValue); DoubleULongUnion union; union.DoubleValue = 0; union.ULongValue = (NextUInt64(ref state) & 0xFFFFFFFFFFFFFUL) | 0x3FF0000000000000UL; double zeroToOne = union.DoubleValue - 1.0; double retval = minValue + ((maxValue - minValue) * zeroToOne); CoreException.Assert(retval >= minValue && retval < maxValue); return(retval); }
public void WaitAndRelease(int completionCount) { CoreException.Assert(Continuation == null, "Can't use WaitAndRelease while also using a continuation"); for (; ;) { var comp = Volatile.Read(ref m_numCompleted); if (comp >= completionCount) { break; } Thread.Sleep(0); } JobCompletion.Release(this); }
public bool Equals(ReadOnlySpan <char> text) { CoreException.Assert(text.Length == 4); if (text.Length < 4) { return(false); } Span <char> arr = stackalloc char[4]; ToString(arr); return(arr.SequenceEqual(text)); }
public static JobCompletion Acquire() { lock (s_free) { if (s_free.TryPop(out var retval)) { retval.ResetForReuse(); return(retval); } #if DEBUG s_totalNumCreated++; CoreException.Assert(s_totalNumCreated < 64, "Unlikely high number of in-flight completions; leaking Completion objects?"); #endif return(new JobCompletion()); } }
public void AddEntry(string name, long started, int duration) { if (duration < 0) { CoreException.Assert(duration >= 0, "AddEntry negative duration"); return; } int ccnt = m_completedCount; if (ccnt > 0 && m_completed[ccnt - 1].Start == started) { started++; // push one tick to make better hierarchies } // no need for interlocked; this is a thread local object ref var complete = ref m_completed[ccnt];
public static int FromHexArray(ReadOnlySpan <char> hexString, Span <byte> into) { if (hexString.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { hexString = hexString.Slice(2); } CoreException.Assert(into.Length >= hexString.Length / 2); int len = 0; for (int i = 0; i < hexString.Length; i += 2) { var value = HexCharToInteger(hexString[i]) << 4 | (HexCharToInteger(hexString[i + 1])); into[len] = (byte)value; len++; } return(len); }
public override JsonConverter CreateConverter( Type typeToConvert, JsonSerializerOptions options) { CoreException.Assert(typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(FastList <>)); Type elementType = typeToConvert.GetGenericArguments()[0]; JsonConverter converter = (JsonConverter)Activator.CreateInstance( typeof(JsonConverterForFastListOfT <>) .MakeGenericType(new Type[] { elementType }), BindingFlags.Instance | BindingFlags.Public, binder: null, args: null, culture: null) !; return(converter); }
public LockTiming(string name, object lockObject) { CoreException.Assert(string.IsNullOrWhiteSpace(name) == false); Name = name; LockObject = lockObject; Started = Stopwatch.GetTimestamp(); var ok = Monitor.TryEnter(lockObject); if (!ok) { Monitor.Enter(lockObject); WaitEnd = Stopwatch.GetTimestamp(); } else { WaitEnd = Started; } }
public void Dispose() { Monitor.Exit(LockObject); long now = Stopwatch.GetTimestamp(); CoreException.Assert(now >= Started); long duration = now - Started; var waited = WaitEnd - Started; if (duration > 0 && duration < int.MaxValue) { TimingThread.Instance.AddEntry(Name, Started, (int)duration); if (waited > 0) { TimingThread.Instance.AddEntry("lockWait", Started, (int)waited); } } }
/// <summary> /// Enqueue work to be called once per argument in list; blocks until all completed /// </summary> public static void ForEachArgumentBlock <TArg>(string name, Action <object> work, ReadOnlySpan <TArg> arguments) { CoreException.Assert(s_workers != null, "JobService not initialized"); if (arguments.Length == 0) { return; } if (arguments.Length == 1) { work(arguments[0]); return; } int numJobs = arguments.Length - 1; var completion = JobCompletion.Acquire(); lock (s_instances) { foreach (var argument in arguments.Slice(1)) { EnqueueInternal(name, work, argument, completion); } } // run one time on this thread using (new Timing(name)) work(arguments[0]); // then, try to steal relevant jobs if possible // am I running within a job? try fetching the JobWorker for this thread var localWorker = JobWorker.WorkerForThread; while (JobService.ExecuteAnyJob(localWorker, completion)) { ; } completion.WaitAndRelease(numJobs); }
/// <summary> /// Compare content of two streams; buffers must be equal length and multiple of 8 /// </summary> public static Result AreEqual(Stream fs1, Stream fs2, Span <byte> buf1, Span <byte> buf2) { CoreException.Assert(buf1.Length == buf2.Length); CoreException.Assert((buf1.Length & 7) == 0); ReadOnlySpan <ulong> ulBuf1 = MemoryMarshal.Cast <byte, ulong>(buf1); ReadOnlySpan <ulong> ulBuf2 = MemoryMarshal.Cast <byte, ulong>(buf2); for (; ;) { int len = fs1.Read(buf1); if (len < 1) { return(Result.Identical); } int len2 = fs2.Read(buf2.Slice(0, len)); if (len != len2) { CoreException.Throw("Failed to read part of file"); } if (len == buf1.Length) { // compare ulongs if (ulBuf1.SequenceEqual(ulBuf2) == false) { return(Result.Different); } } else { // compare bytes if (buf1.Slice(0, len).SequenceEqual(buf2.Slice(0, len)) == false) { return(Result.Different); } } } }
public static int Next(ref ulong state, int minValue, int maxValue) { CoreException.Assert(maxValue > minValue); unchecked { var x = state; x ^= x >> 12; x ^= x << 25; x ^= x >> 27; state = x; // lemire fastrange ulong rnd = (x * 0x2545F4914F6CDD1D) >> 32; // use upper bits ulong span = (ulong)((long)maxValue - (long)minValue); uint offset = (uint)((rnd * span) >> 32); var retval = (int)(minValue + offset); CoreException.Assert(retval >= minValue && retval < maxValue); return(retval); } }