public DirectBuffer this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if ((uint)index >= BufferCount) { BuffersThrowHelper.ThrowIndexOutOfRange(); } // ReSharper disable once ImpureMethodCallOnReadonlyValueField return(DirectBuffer.Slice(index * BufferSize, BufferSize)); } }
internal unsafe SharedMemoryPool(string path, uint maxLogSizeMb, LMDBEnvironmentFlags envFlags, Wpid ownerId, int rmMaxBufferLength = RmDefaultMaxBufferLength, int rmMaxBuffersPerBucket = RmDefaultMaxBuffersPerBucket, bool rentAlwaysClean = false) : base( (pool, bucketSize) => { if (bucketSize > pool.MaxBufferSize) { BuffersThrowHelper.ThrowBadLength(); } var smbp = (SharedMemoryPool)pool; #pragma warning disable 618 var sm = smbp.RentNative(bucketSize); Debug.Assert(!sm.IsDisposed); Debug.Assert(sm.ReferenceCount == 0); Debug.Assert(Unsafe.ReadUnaligned <uint>(sm.HeaderPointer) == HeaderFlags.IsOwned); #pragma warning restore 618 // TODO review if Releasing -> IsOwned should keep disposed state? // RMP calls CreateNew outside lock, so if we call RentNative only here // then it could return IsOwned without IsDisposed. But we a technically // inside the pool until this factory returns. Buffers from RentNative // should be unusable without explicit un-dispose action. // Set counter to zero sm.CounterRef &= ~AtomicCounter.CountMask; return(sm); }, RmMinPoolBufferLength, Math.Max(RmDefaultMaxBufferLength, Math.Min(RmMaxPoolBufferLength, BitUtil.FindNextPositivePowerOfTwo(rmMaxBufferLength))), // from ProcCount to DefaultMaxNumberOfBuffersPerBucket x 2 Math.Max(Environment.ProcessorCount, Math.Min(RmDefaultMaxBuffersPerBucket * 2, rmMaxBuffersPerBucket)), MaxBucketsToTry, rentAlwaysClean: rentAlwaysClean) { if (ownerId <= 0) { ThrowHelper.ThrowArgumentOutOfRangeException("ownerId <= 0"); } Directory.CreateDirectory(path); _bra = new BufferRefAllocator(path, envFlags, ownerId, PageSize, maxLogSizeMb * 1024 * 1024L); _buckets = new SharedMemoryBuckets(Path.Combine(path, "buckets"), pageSize: PageSize, maxBucketIndex: BufferRef.MaxBucketIdx); StartMonitoringTask(); }
public T Rent() { if (_disposed) { BuffersThrowHelper.ThrowDisposed <LockedObjectPool <T> >(); } var objects = _objects; T obj = null; var allocate = false; #if !NETCOREAPP try #endif { var spinner = new SpinWait(); while (0 != Interlocked.CompareExchange(ref _locker, 1, 0)) { spinner.SpinOnce(); } if (_index < objects.Length) { obj = objects[_index]; objects[_index++] = null; allocate = obj == null; } } #if !NETCOREAPP finally #endif { Volatile.Write(ref _locker, 0); } if (allocate || (obj == null && AllocateOnEmpty)) { if (TraceLowCapacityAllocation && !allocate) { DoTrace(); } obj = CreateNewObject(); } return(obj); }
public static int IndexToOffset(int index, int head, int len) { if (AdditionalCorrectnessChecks.Enabled && (head < 0 || len < 0)) { BuffersThrowHelper.ThrowIndexOutOfRange(); } // return (head + index) % len; // len is not guaranteed to be power of 2, cannot use bit mask // but we could avoid branch: we do not need modulo // instead we only need to subtract len if we wrap over it var offset = head + index; var isWrapped = (len - (offset + 1)) >> 31; // 0 or -1 var result = offset + isWrapped * len; if (AdditionalCorrectnessChecks.Enabled) { ThrowHelper.Assert(result >= 0); ThrowHelper.Assert(result < len); } return(result); }
internal T?Rent(int cpuId) { if (_disposed) { BuffersThrowHelper.ThrowDisposed <LockedObjectPool <T> >(); } T?obj; for (int i = 0; i <= Cpu.CoreCount; i++) { if ((obj = _perCorePools[cpuId].Rent()) != null) { return(obj); } if (++cpuId == Cpu.CoreCount) { cpuId = 0; } } return(RentSlow()); }