public void Swap(UnmanagedSliceBuilder other) { if (other == null) { throw new ArgumentNullException("other"); } if (m_buffer == null || other.m_buffer == null) { ThrowAlreadyDisposed(); } try { } finally { var handle = other.m_handle; var buffer = other.m_buffer; var data = other.m_data; var sz = other.m_count; other.m_handle = m_handle; other.m_buffer = buffer; other.m_data = m_data; other.m_count = m_count; m_handle = handle; m_buffer = buffer; m_data = data; m_count = sz; } }
/// <summary>Borrow a builder from this pool</summary> /// <returns>Builder subscription that should be disposed as soon as the buffer is not needed anymore</returns> /// <remarks>ALWAYS wrap the subscription in a using(...) statement! Do NOT pass the subscription by value, always pass the Builder by reference ! Do NOT keep a reference on the Builder or reuse it after it has been disposed! Do NOT return or store slices that point to this buffer! </remarks> public Subscription Use() { UnmanagedSliceBuilder builder = null; lock (m_buckets) { if (m_disposed) { ThrowDisposed(); } while (m_buckets.Count > 0) { builder = m_buckets.Pop(); if (builder != null && builder.Buffer != null) { Interlocked.Add(ref m_memoryUsed, -((long)builder.Capacity)); Contract.Assert(m_memoryUsed >= 0, "m_memoryUsed desync"); break; } builder = null; } } if (builder == null) { builder = new UnmanagedSliceBuilder(m_initialCapacity); } Interlocked.Add(ref m_memoryLoaned, builder.Capacity); Contract.Assert(builder != null && builder.Buffer != null); return(new Subscription(this, builder)); }
/// <summary>Return a builder into the pool</summary> /// <param name="builder">Builder that is no longer in use</param> internal void Return(UnmanagedSliceBuilder builder) { if (m_disposed || builder == null) { return; } lock (m_buckets) { if (m_disposed) { return; } var size = builder.Capacity; Contract.Assert(size == UnmanagedHelpers.NextPowerOfTwo(size), "builder size should always be a power of two"); Interlocked.Add(ref m_memoryLoaned, -((long)builder.Capacity)); Contract.Assert(m_memoryUsed >= 0, "m_memoryLoaned desync"); if (m_buckets.Count < m_maxCount) { m_buckets.Push(builder); Interlocked.Add(ref m_memoryUsed, builder.Capacity); } else { builder.Dispose(); } } }
internal Subscription(UnmanagedSliceBuilderPool pool, UnmanagedSliceBuilder builder) { Contract.Requires(pool != null && builder != null); m_pool = pool; m_builder = builder; }
public DebugView(UnmanagedSliceBuilder builder) { m_builder = builder; }
public DebugView(UnmanagedSliceBuilder builder) { m_builder = builder; }
public void Swap(UnmanagedSliceBuilder other) { if (other == null) throw new ArgumentNullException("other"); if (m_buffer == null || other.m_buffer == null) ThrowAlreadyDisposed(); try { } finally { var handle = other.m_handle; var buffer = other.m_buffer; var data = other.m_data; var sz = other.m_count; other.m_handle = m_handle; other.m_buffer = buffer; other.m_data = m_data; other.m_count = m_count; m_handle = handle; m_buffer = buffer; m_data = data; m_count = sz; } }
/// <summary>Checks if a list of reads conflicts with at least one write performed in this transaction window</summary> /// <param name="reads">List of reads to check for conflicts</param> /// <param name="version">Sequence number of the transaction that performed the reads</param> /// <returns>True if at least one read is conflicting with a write with a higher sequence number; otherwise, false.</returns> public bool Conflicts(ColaRangeSet<Slice> reads, ulong version) { Contract.Requires(reads != null); //Debug.WriteLine("* Testing for conflicts for: " + String.Join(", ", reads)); if (version > m_maxVersion) { // all the writes are before the reads, so no possible conflict! //Debug.WriteLine(" > cannot conflict"); return false; } using (var scratch = new UnmanagedSliceBuilder()) { //TODO: do a single-pass version of intersection checking ! foreach (var read in reads) { scratch.Clear(); scratch.Append(read.Begin); var p = scratch.Count; scratch.Append(read.End); var begin = scratch.ToUSlice(p); var end = scratch.ToUSlice(p, scratch.Count - p); if (m_writeConflicts.Intersect(begin, end, version, (v, min) => v > min)) { Debug.WriteLine(" > Conflicting read: " + read); return true; } } } //Debug.WriteLine(" > No conflicts found"); return false; }
/// <summary>Borrow a builder from this pool</summary> /// <returns>Builder subscription that should be disposed as soon as the buffer is not needed anymore</returns> /// <remarks>ALWAYS wrap the subscription in a using(...) statement! Do NOT pass the subscription by value, always pass the Builder by reference ! Do NOT keep a reference on the Builder or reuse it after it has been disposed! Do NOT return or store slices that point to this buffer! </remarks> public Subscription Use() { UnmanagedSliceBuilder builder = null; lock (m_buckets) { if (m_disposed) ThrowDisposed(); while(m_buckets.Count > 0) { builder = m_buckets.Pop(); if (builder != null && builder.Buffer != null) { Interlocked.Add(ref m_memoryUsed, -((long)builder.Capacity)); Contract.Assert(m_memoryUsed >= 0, "m_memoryUsed desync"); break; } builder = null; } } if (builder == null) { builder = new UnmanagedSliceBuilder(m_initialCapacity); } Interlocked.Add(ref m_memoryLoaned, builder.Capacity); Contract.Assert(builder != null && builder.Buffer != null); return new Subscription(this, builder); }
internal Subscription(UnmanagedSliceBuilderPool pool, UnmanagedSliceBuilder builder) { Contract.Requires(pool != null && builder != null); m_pool = pool; m_builder = builder; }
/// <summary>Return a builder into the pool</summary> /// <param name="builder">Builder that is no longer in use</param> internal void Return(UnmanagedSliceBuilder builder) { if (m_disposed || builder == null) return; lock (m_buckets) { if (m_disposed) return; var size = builder.Capacity; Contract.Assert(size == UnmanagedHelpers.NextPowerOfTwo(size), "builder size should always be a power of two"); Interlocked.Add(ref m_memoryLoaned, -((long)builder.Capacity)); Contract.Assert(m_memoryUsed >= 0, "m_memoryLoaned desync"); if (m_buckets.Count < m_maxCount) { m_buckets.Push(builder); Interlocked.Add(ref m_memoryUsed, builder.Capacity); } else { builder.Dispose(); } } }