v0.2.2: updated Lidgren, railgun shells can be bought, autorestart server, netstats, tutorial moloch spawning in a wall fix, misc error checks
This commit is contained in:
@@ -6,14 +6,18 @@ namespace Lidgren.Network
|
||||
{
|
||||
public partial class NetPeer
|
||||
{
|
||||
private List<byte[]> m_storagePool; // sorted smallest to largest
|
||||
internal List<byte[]> m_storagePool;
|
||||
private NetQueue<NetOutgoingMessage> m_outgoingMessagesPool;
|
||||
private NetQueue<NetIncomingMessage> m_incomingMessagesPool;
|
||||
|
||||
internal int m_storagePoolBytes;
|
||||
internal int m_storageSlotsUsedCount;
|
||||
private int m_maxCacheCount;
|
||||
|
||||
private void InitializePools()
|
||||
{
|
||||
m_storageSlotsUsedCount = 0;
|
||||
|
||||
if (m_configuration.UseMessageRecycling)
|
||||
{
|
||||
m_storagePool = new List<byte[]>(16);
|
||||
@@ -26,6 +30,8 @@ namespace Lidgren.Network
|
||||
m_outgoingMessagesPool = null;
|
||||
m_incomingMessagesPool = null;
|
||||
}
|
||||
|
||||
m_maxCacheCount = m_configuration.RecycledCacheMaxCount;
|
||||
}
|
||||
|
||||
internal byte[] GetStorage(int minimumCapacityInBytes)
|
||||
@@ -41,6 +47,7 @@ namespace Lidgren.Network
|
||||
if (retval != null && retval.Length >= minimumCapacityInBytes)
|
||||
{
|
||||
m_storagePool[i] = null;
|
||||
m_storageSlotsUsedCount--;
|
||||
m_storagePoolBytes -= retval.Length;
|
||||
return retval;
|
||||
}
|
||||
@@ -52,22 +59,39 @@ namespace Lidgren.Network
|
||||
|
||||
internal void Recycle(byte[] storage)
|
||||
{
|
||||
if (m_storagePool == null)
|
||||
if (m_storagePool == null || storage == null)
|
||||
return;
|
||||
|
||||
lock (m_storagePool)
|
||||
{
|
||||
m_storagePoolBytes += storage.Length;
|
||||
int cnt = m_storagePool.Count;
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
if (m_storagePool[i] == null)
|
||||
{
|
||||
m_storageSlotsUsedCount++;
|
||||
m_storagePoolBytes += storage.Length;
|
||||
m_storagePool[i] = storage;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_storagePool.Add(storage);
|
||||
|
||||
if (m_storagePool.Count >= m_maxCacheCount)
|
||||
{
|
||||
// pool is full; replace randomly chosen entry to keep size distribution
|
||||
var idx = NetRandom.Instance.Next(m_storagePool.Count);
|
||||
|
||||
m_storagePoolBytes -= m_storagePool[idx].Length;
|
||||
m_storagePoolBytes += storage.Length;
|
||||
|
||||
m_storagePool[idx] = storage; // replace
|
||||
}
|
||||
else
|
||||
{
|
||||
m_storageSlotsUsedCount++;
|
||||
m_storagePoolBytes += storage.Length;
|
||||
m_storagePool.Add(storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,10 +108,8 @@ namespace Lidgren.Network
|
||||
/// </summary>
|
||||
public NetOutgoingMessage CreateMessage(string content)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(content);
|
||||
NetOutgoingMessage om = CreateMessage(2 + bytes.Length);
|
||||
om.WriteVariableUInt32((uint)bytes.Length);
|
||||
om.Write(bytes);
|
||||
var om = CreateMessage(2 + content.Length); // fair guess
|
||||
om.Write(content);
|
||||
return om;
|
||||
}
|
||||
|
||||
@@ -101,8 +123,10 @@ namespace Lidgren.Network
|
||||
if (m_outgoingMessagesPool == null || !m_outgoingMessagesPool.TryDequeue(out retval))
|
||||
retval = new NetOutgoingMessage();
|
||||
|
||||
byte[] storage = GetStorage(initialCapacity);
|
||||
retval.m_data = storage;
|
||||
NetException.Assert(retval.m_recyclingCount == 0, "Wrong recycling count! Should be zero" + retval.m_recyclingCount);
|
||||
|
||||
if (initialCapacity > 0)
|
||||
retval.m_data = GetStorage(initialCapacity);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -134,17 +158,18 @@ namespace Lidgren.Network
|
||||
/// </summary>
|
||||
public void Recycle(NetIncomingMessage msg)
|
||||
{
|
||||
if (m_incomingMessagesPool == null)
|
||||
if (m_incomingMessagesPool == null || msg == null)
|
||||
return;
|
||||
#if DEBUG
|
||||
if (m_incomingMessagesPool.Contains(msg))
|
||||
throw new NetException("Recyling already recycled message! Thread race?");
|
||||
#endif
|
||||
|
||||
NetException.Assert(m_incomingMessagesPool.Contains(msg) == false, "Recyling already recycled incoming message! Thread race?");
|
||||
|
||||
byte[] storage = msg.m_data;
|
||||
msg.m_data = null;
|
||||
Recycle(storage);
|
||||
msg.Reset();
|
||||
m_incomingMessagesPool.Enqueue(msg);
|
||||
|
||||
if (m_incomingMessagesPool.Count < m_maxCacheCount)
|
||||
m_incomingMessagesPool.Enqueue(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -154,34 +179,8 @@ namespace Lidgren.Network
|
||||
{
|
||||
if (m_incomingMessagesPool == null)
|
||||
return;
|
||||
|
||||
// first recycle the storage of each message
|
||||
if (m_storagePool != null)
|
||||
{
|
||||
lock (m_storagePool)
|
||||
{
|
||||
foreach (var msg in toRecycle)
|
||||
{
|
||||
var storage = msg.m_data;
|
||||
msg.m_data = null;
|
||||
m_storagePoolBytes += storage.Length;
|
||||
int cnt = m_storagePool.Count;
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
if (m_storagePool[i] == null)
|
||||
{
|
||||
m_storagePool[i] = storage;
|
||||
return;
|
||||
}
|
||||
}
|
||||
msg.Reset();
|
||||
m_storagePool.Add(storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// then recycle the message objects
|
||||
m_incomingMessagesPool.Enqueue(toRecycle);
|
||||
foreach (var im in toRecycle)
|
||||
Recycle(im);
|
||||
}
|
||||
|
||||
internal void Recycle(NetOutgoingMessage msg)
|
||||
@@ -189,20 +188,25 @@ namespace Lidgren.Network
|
||||
if (m_outgoingMessagesPool == null)
|
||||
return;
|
||||
#if DEBUG
|
||||
if (m_outgoingMessagesPool.Contains(msg))
|
||||
throw new NetException("Recyling already recycled message! Thread race?");
|
||||
NetException.Assert(m_outgoingMessagesPool.Contains(msg) == false, "Recyling already recycled outgoing message! Thread race?");
|
||||
if (msg.m_recyclingCount != 0)
|
||||
LogWarning("Wrong recycling count! should be zero; found " + msg.m_recyclingCount);
|
||||
#endif
|
||||
// setting m_recyclingCount to zero SHOULD be an unnecessary maneuver, if it's not zero something is wrong
|
||||
// however, in RELEASE, we'll just have to accept this and move on with life
|
||||
msg.m_recyclingCount = 0;
|
||||
|
||||
byte[] storage = msg.m_data;
|
||||
msg.m_data = null;
|
||||
|
||||
|
||||
// message fragments cannot be recycled
|
||||
// TODO: find a way to recycle large message after all fragments has been acknowledged; or? possibly better just to garbage collect them
|
||||
if (msg.m_fragmentGroup == 0)
|
||||
Recycle(storage);
|
||||
|
||||
|
||||
msg.Reset();
|
||||
m_outgoingMessagesPool.Enqueue(msg);
|
||||
if (m_outgoingMessagesPool.Count < m_maxCacheCount)
|
||||
m_outgoingMessagesPool.Enqueue(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user