fix: Replaces PollGroup with nuget (#823)

This commit is contained in:
Kamron Batman 2021-10-09 13:52:53 -07:00 committed by GitHub
parent 81486772f6
commit 507eba34a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 13 additions and 495 deletions

View file

@ -1,197 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EPollGroup.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Server.Network
{
public sealed class EPollGroup : IPollGroup
{
[Flags]
private enum epoll_flags
{
NONE = 0,
CLOEXEC = 0x02000000,
NONBLOCK = 0x04000,
}
[Flags]
private enum epoll_events : uint
{
EPOLLIN = 0x001,
EPOLLPRI = 0x002,
EPOLLOUT = 0x004,
EPOLLRDNORM = 0x040,
EPOLLRDBAND = 0x080,
EPOLLWRNORM = 0x100,
EPOLLWRBAND = 0x200,
EPOLLMSG = 0x400,
EPOLLERR = 0x008,
EPOLLHUP = 0x010,
EPOLLRDHUP = 0x2000,
EPOLLONESHOT = 1 << 30,
EPOLLET = unchecked((uint)(1 << 31))
}
private enum epoll_op
{
EPOLL_CTL_ADD = 1,
EPOLL_CTL_DEL = 2,
EPOLL_CTL_MOD = 3,
}
[StructLayout(LayoutKind.Explicit, Size = 8)]
private struct epoll_data
{
[FieldOffset(0)]
public int fd;
[FieldOffset(0)]
public IntPtr ptr;
[FieldOffset(0)]
public uint u32;
[FieldOffset(0)]
public ulong u64;
}
[StructLayout(LayoutKind.Explicit, Pack = 4)]
private struct epoll_event
{
[FieldOffset(0)]
public epoll_events events;
[FieldOffset(4)]
public epoll_data data;
}
private static class Windows
{
[DllImport("wepoll.dll", SetLastError = true)]
public static extern int epoll_create1(epoll_flags flags);
[DllImport("wepoll.dll", SetLastError = true)]
public static extern int epoll_close(int epfd);
[DllImport("wepoll.dll", SetLastError = true)]
public static extern int epoll_ctl(int epfd, epoll_op op, int fd, ref epoll_event ee);
[DllImport("wepoll.dll", SetLastError = true)]
public static extern int epoll_wait(int epfd, [In, Out] epoll_event[] ee, int maxevents, int timeout);
}
private static class Linux
{
[DllImport("libc", SetLastError = true)]
public static extern int epoll_create1(epoll_flags flags);
[DllImport("libc", SetLastError = true)]
public static extern int epoll_close(int epfd);
[DllImport("libc", SetLastError = true)]
public static extern int epoll_ctl(int epfd, epoll_op op, int fd, ref epoll_event ee);
[DllImport("libc", SetLastError = true)]
public static extern int epoll_wait(int epfd, [In, Out] epoll_event[] ee, int maxevents, int timeout);
}
private readonly int _epHndle;
private readonly bool _isWindows;
public EPollGroup()
{
_isWindows = Core.IsWindows;
_epHndle = _isWindows ? Windows.epoll_create1(epoll_flags.NONE) : Linux.epoll_create1(epoll_flags.NONE);
if (_epHndle == 0)
{
throw new Exception("Unable to initialize poll group");
}
}
public void Dispose()
{
if (_isWindows)
{
Windows.epoll_close(_epHndle);
}
else
{
Linux.epoll_close(_epHndle);
}
}
public void Add(Socket socket, GCHandle handle)
{
var ev = new epoll_event
{
events = epoll_events.EPOLLIN | epoll_events.EPOLLERR
};
ev.data.ptr = (IntPtr)handle;
var rc = _isWindows ?
Windows.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_ADD, (int)socket.Handle, ref ev) :
Linux.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_ADD, (int)socket.Handle, ref ev);
if (rc != 0)
{
throw new Exception($"epoll_ctl failed with error code {Marshal.GetLastWin32Error()}");
}
}
public void Remove(Socket socket)
{
var ev = new epoll_event { events = epoll_events.EPOLLIN | epoll_events.EPOLLERR };
var rc = _isWindows ?
Windows.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_DEL, (int)socket.Handle, ref ev) :
Linux.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_DEL, (int)socket.Handle, ref ev);
if (rc != 0)
{
throw new Exception($"epoll_ctl failed with error code {Marshal.GetLastWin32Error()}");
}
}
private epoll_event[] _events = new epoll_event[2048];
public int Poll(ref GCHandle[] handles)
{
if (handles.Length > _events.Length)
{
var newLength = Math.Max(handles.Length, _events.Length + (_events.Length >> 2));
_events = new epoll_event[newLength];
}
var rc = _isWindows ?
Windows.epoll_wait(_epHndle, _events, handles.Length, 0) :
Linux.epoll_wait(_epHndle, _events, handles.Length, 0);
if (rc <= 0)
{
return rc;
}
for (int i = 0; i < rc; i++)
{
handles[i] = (GCHandle)_events[i].data.ptr;
}
return rc;
}
}
}

View file

@ -1,241 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: KQueuePollGroup.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.IO;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Server.Network
{
public class KQueuePollGroup : IPollGroup
{
[StructLayout(LayoutKind.Sequential)]
private struct kevent
{
public IntPtr ident;
public kqueue_filter filter;
public kqueue_flags flags;
public kqueue_fflags fflags;
public IntPtr data;
public IntPtr udata;
}
[Flags]
private enum kqueue_filter : short
{
READ = -1,
WRITE = -2,
AIO = -3,
VNODE = -4,
PROC = -5,
SIGNAL = -6,
TIMER = -7,
MACHPORT = -8,
FS = -9,
USER = -10,
UNUSED = -11,
VM = -12,
EXCEPT = -15
}
[Flags]
private enum kqueue_flags : ushort
{
ADD = 0x0001,
DELETE = 0x0002,
ENABLE = 0x0004,
DISABLE = 0x0008,
ONESHOT = 0x0010,
CLEAR = 0x0020,
RECEIPT = 0x0040,
DISPATCH = 0x0080,
UDATA_SPECIFIC = 0x0100,
DISPATCH2 = (DISPATCH | UDATA_SPECIFIC),
VANISHED = 0x0200,
SYSFLAGS = 0xF000,
FLAG0 = 0x1000,
FLAG1 = 0x2000,
EOF = 0x8000,
ERROR = 0x4000
}
[Flags]
private enum kqueue_fflags : uint
{
TRIGGER = 0x01000000,
FFNOP = 0x00000000,
FFAND = 0x40000000,
FFOR = 0x80000000,
FFCOPY = 0xc0000000,
FFCTRLMASK = 0xc0000000,
FFFLAGSMASK = 0x00ffffff,
LOWAT = 0x00000001,
DELETE = 0x00000001,
WRITE = 0x00000002,
EXTEND = 0x00000004,
ATTRIB = 0x00000008,
LINK = 0x00000010,
RENAME = 0x00000020,
REVOKE = 0x00000040,
NONE = 0x00000080,
}
[StructLayout(LayoutKind.Sequential)]
struct timespec
{
public long tv_sec;
public long tv_nsec;
public timespec(long sec, long nsec)
{
tv_sec = sec;
tv_nsec = nsec;
}
}
private static readonly kevent[] _singleEvent = new kevent[1];
private static readonly IntPtr _zeroTimeoutPtr;
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
private static readonly timespec _zeroTimeout;
static KQueuePollGroup()
{
_zeroTimeout = new timespec(0, 0);
_zeroTimeoutPtr = Marshal.AllocHGlobal(Marshal.SizeOf<timespec>());
Marshal.StructureToPtr(_zeroTimeout, _zeroTimeoutPtr, false);
}
private static class BSD
{
[DllImport ("libc", SetLastError = true)]
public static extern int close (int fd);
[DllImport("libc", SetLastError = true)]
public static extern int kqueue();
[DllImport("libc", SetLastError = true)]
public static extern int kevent(int kq, kevent[] changelist, int nchanges, [In, Out] kevent[] eventlist, int nevents, IntPtr timeout);
public static int kevent(
int kq,
IntPtr ident,
kqueue_filter filter,
kqueue_flags flags,
kqueue_fflags fflags = 0,
IntPtr data = default,
IntPtr udata = default
)
{
_singleEvent[0] = new kevent
{
ident = ident,
filter = filter,
flags = flags,
fflags = fflags,
data = data,
udata = udata
};
var rc = kevent(kq, _singleEvent, 1, null, 0, _zeroTimeoutPtr);
if (rc != 0)
{
throw new Exception($"kqueue failed to {flags} with error code {Marshal.GetLastWin32Error()}");
}
if (_singleEvent[0].flags.HasFlag(kqueue_flags.ERROR))
{
throw new IOException($"kqueue failed to {flags} with error {_singleEvent[0].data}");
}
return rc;
}
}
private readonly int _kqueueHndle;
public KQueuePollGroup()
{
_kqueueHndle = BSD.kqueue();
if (_kqueueHndle == 0)
{
throw new Exception("Unable to initialize poll group");
}
}
public void Dispose()
{
BSD.close(_kqueueHndle);
Marshal.FreeHGlobal(_zeroTimeoutPtr);
}
public void Add(Socket socket, GCHandle handle)
{
var rc = BSD.kevent(
_kqueueHndle,
socket.Handle,
kqueue_filter.READ | kqueue_filter.WRITE,
kqueue_flags.ADD | kqueue_flags.CLEAR,
udata: (IntPtr)handle
);
if (rc != 0)
{
throw new Exception($"kevent failed with error code {Marshal.GetLastWin32Error()}");
}
}
public void Remove(Socket socket)
{
var rc = BSD.kevent(
_kqueueHndle,
socket.Handle,
kqueue_filter.READ | kqueue_filter.WRITE,
kqueue_flags.DELETE
);
if (rc != 0)
{
throw new Exception($"kevent failed with error code {Marshal.GetLastWin32Error()}");
}
}
private kevent[] _events = new kevent[2048];
public int Poll(ref GCHandle[] handles)
{
if (handles.Length > _events.Length)
{
var newLength = Math.Max(handles.Length, _events.Length + (_events.Length >> 2));
_events = new kevent[newLength];
}
var rc = BSD.kevent(_kqueueHndle, null, 0, _events, _events.Length, _zeroTimeoutPtr);
if (rc <= 0)
{
return rc;
}
for (int i = 0; i < rc; i++)
{
handles[i] = (GCHandle)_events[i].udata;
}
return rc;
}
}
}

View file

@ -1,41 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: PollGroup.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Server.Network
{
public interface IPollGroup : IDisposable
{
void Add(Socket sock, GCHandle handle);
void Remove(Socket sock);
int Poll(ref GCHandle[] handles);
}
public static class PollGroup
{
public static IPollGroup Create()
{
if (Core.IsBSD)
{
return new KQueuePollGroup();
}
return new EPollGroup();
}
}
}

View file

@ -13,32 +13,29 @@
</PropertyGroup>
<Target Name="CleanPub" AfterTargets="Clean">
<Message Text="Removing distribution files..." />
<Delete Files="..\..\Distribution\zlib.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\libz.dylib" ContinueOnError="true" />
<Delete Files="..\..\Distribution\libz.so" ContinueOnError="true" />
<Delete Files="..\..\Distribution\ZLib.Bindings.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Microsoft.Toolkit.HighPerformance.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Serilog.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Serilog.Sinks.Async.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Serilog.Sinks.Console.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName)" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).deps.json" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\ref\$(AssemblyName).dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).dll.config" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).exe" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).deps.json" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).pdb" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).runtimeconfig.dev.json" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).runtimeconfig.json" ContinueOnError="true" />
<Delete Files="..\..\Distribution\libz.dylib" ContinueOnError="true" />
<Delete Files="..\..\Distribution\libz.so" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Microsoft.Toolkit.HighPerformance.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\PollGroup.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\ref\$(AssemblyName).dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Serilog.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Serilog.Sinks.Async.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Serilog.Sinks.Console.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\wepoll.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\ZLib.Bindings.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\zlib.dll" ContinueOnError="true" />
</Target>
<ItemGroup Condition="'$(IsWindows)'=='true' OR '$(IsWindows)'==''">
<Content Include="wepoll.dll">
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.0.2" />
<PackageReference Include="PollGroup" Version="1.0.0" />
<PackageReference Include="Zlib.Bindings" Version="1.5.0" />
</ItemGroup>
<ItemGroup>

Binary file not shown.