Пример #1
0
        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;
 }
Пример #5
0
 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();
				}
			}
		}