baseline: OpenMU upstream b5a0961 (fresh source)
This commit is contained in:
93
src/Persistence/IdGenerator.cs
Normal file
93
src/Persistence/IdGenerator.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
// <copyright file="IdGenerator.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Persistence;
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// A generator which generates id which should be unique within an instance of a generator.
|
||||
/// Ids which are no longer used can be given back to the generator, e.g. when an object joins a game map,
|
||||
/// it gets an id, later when it leaves the map, it gives the id back, so another player can use it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The namespace for this class is probably not the right one - we're missing something like a "Utility" namespace for things like that.
|
||||
/// </remarks>
|
||||
public class IdGenerator
|
||||
{
|
||||
private readonly int _maxValue;
|
||||
private readonly ConcurrentQueue<int> _givenBack = new();
|
||||
private int _currentValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IdGenerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="firstValue">The first value.</param>
|
||||
/// <param name="maxValue">The maximum value.</param>
|
||||
public IdGenerator(int firstValue, int maxValue)
|
||||
{
|
||||
this._maxValue = maxValue;
|
||||
this._currentValue = firstValue - 1; // will be increased by 1 by GenerateId
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines how ids are reused, which were given back with <see cref="IdGenerator.GiveBack"/>.
|
||||
/// </summary>
|
||||
public enum ReUsePolicy
|
||||
{
|
||||
/// <summary>
|
||||
/// The given back id is reused on the next call of <see cref="IdGenerator.GenerateId"/>.
|
||||
/// </summary>
|
||||
ReUseOnNextRetrieve,
|
||||
|
||||
/// <summary>
|
||||
/// The given back id is reused when all of the available ids were exceeded.
|
||||
/// </summary>
|
||||
ReUseWhenExceeded,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="ReUsePolicy"/> which defines how ids are reused, which were given back with <see cref="IdGenerator.GiveBack"/>.
|
||||
/// </summary>
|
||||
public ReUsePolicy ReUseSetting { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an identifier which is unique within this generator instance.
|
||||
/// </summary>
|
||||
/// <returns>An identifier which is unique within this generator instance.</returns>
|
||||
/// <exception cref="InvalidOperationException">Maximum object id exceeded.</exception>
|
||||
public int GenerateId()
|
||||
{
|
||||
if (this.ReUseSetting == ReUsePolicy.ReUseOnNextRetrieve
|
||||
&& this._givenBack.TryDequeue(out int next))
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
if (this._currentValue == this._maxValue)
|
||||
{
|
||||
if (this._givenBack.TryDequeue(out next))
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Maximum object id exceeded");
|
||||
}
|
||||
|
||||
return Interlocked.Increment(ref this._currentValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gives the id back for further usage by the next object.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
public void GiveBack(int id)
|
||||
{
|
||||
if (id <= this._maxValue)
|
||||
{
|
||||
this._givenBack.Enqueue(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user