master
Harald Wolff 2019-03-13 14:17:46 +01:00
parent 3cc4f92e40
commit c4f456f8c5
3 changed files with 58 additions and 96 deletions

View File

@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using ln.http.threads;
using System.IO;
using System.Text;
using ln.http.resources.session;
using ln.logging;
using ln.types.threads;
namespace ln.http
@ -19,17 +20,21 @@ namespace ln.http
public HttpApplication DefaultApplication { get; set; }
public SessionCache SessionCache { get; set; }
public bool IsRunning => (currentListenerThreads.Count > 0) || (threadPool.NumThreads > 0);
bool shutdown = false;
Dictionary<IPEndPoint, TcpListener> tcpListeners = new Dictionary<IPEndPoint, TcpListener>();
Dictionary<Uri, HttpApplication> applications = new Dictionary<Uri, HttpApplication>();
Dictionary<TcpListener, Thread> currentListenerThreads = new Dictionary<TcpListener, Thread>();
Pool threadPool = new Pool();
public SessionCache SessionCache { get; set; }
public HTTPServer()
{
SessionCache = new SessionCache();
@ -64,7 +69,9 @@ namespace ln.http
foreach (TcpListener tcpListener in this.tcpListeners.Values)
{
tcpListener.Start(backlog);
this.threadPool.Enqueue(() => AcceptConnections(tcpListener));
Thread listenerThread = new Thread(() => AcceptConnections(tcpListener));
listenerThread.Start();
}
}
@ -74,20 +81,49 @@ namespace ln.http
lock (this)
{
this.shutdown = true;
foreach (TcpListener tcpListener in tcpListeners.Values)
{
tcpListener.Stop();
}
threadPool.NumThreads = 0;
while (IsRunning)
{
Thread.Sleep(50);
}
}
}
private void AcceptConnections(TcpListener tcpListener)
{
while (true)
lock (this)
{
lock(this)
if (currentListenerThreads.ContainsKey(tcpListener))
{
if (this.shutdown) {
return;
}
throw new Exception("HTTP listener thread already running");
}
AcceptConnection(tcpListener);
currentListenerThreads.Add(tcpListener, Thread.CurrentThread);
}
try
{
while (!this.shutdown)
{
AcceptConnection(tcpListener);
}
} catch (Exception e)
{
Logging.Log(LogLevel.ERROR, "HTTPServer: Listener thread caught exception {0}",e);
Logging.Log(e);
}
lock (this)
{
currentListenerThreads.Remove(tcpListener);
}
}

View File

@ -34,7 +34,6 @@
<Compile Include="exceptions\HttpException.cs" />
<Compile Include="exceptions\IllegalRequestException.cs" />
<Compile Include="exceptions\ResourceNotFoundException.cs" />
<Compile Include="threads\Pool.cs" />
<Compile Include="HTTPServer.cs" />
<Compile Include="HttpReader.cs" />
<Compile Include="HttpRequest.cs" />
@ -50,8 +49,17 @@
</ItemGroup>
<ItemGroup>
<Folder Include="exceptions\" />
<Folder Include="threads\" />
<Folder Include="session\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.logging\ln.logging.csproj">
<Project>{D471A566-9FB6-41B2-A777-3C32874ECD0E}</Project>
<Name>ln.logging</Name>
</ProjectReference>
<ProjectReference Include="..\ln.types\ln.types.csproj">
<Project>{8D9AB9A5-E513-4BA7-A450-534F6456BF28}</Project>
<Name>ln.types</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,82 +0,0 @@
using System;
using System.Threading;
using System.Collections.Generic;
namespace ln.http.threads
{
public delegate void JobDelegate();
public class Pool
{
public int Timeout { get; set; } = 15000;
ISet<Thread> threads = new HashSet<Thread>();
Queue<JobDelegate> queuedJobs = new Queue<JobDelegate>();
HashSet<Thread> idleThreads = new HashSet<Thread>();
public Pool()
{
}
private void AllocateThread()
{
Thread thread = new Thread(pool_thread);
thread.Start();
}
public void Enqueue(JobDelegate job)
{
lock (this)
{
queuedJobs.Enqueue(job);
if (idleThreads.Count == 0)
{
AllocateThread();
}
else
{
Monitor.Pulse(this);
}
}
}
private void pool_thread()
{
Thread me = Thread.CurrentThread;
try
{
JobDelegate job = null;
do
{
lock (this)
{
if (queuedJobs.Count == 0)
{
idleThreads.Add(me);
bool s = Monitor.Wait(this, Timeout);
idleThreads.Remove(me);
if (!s)
break;
}
job = queuedJobs.Dequeue();
}
job();
} while (true);
}
catch (Exception e)
{
Console.WriteLine("Exception in worker thread: {0}", e);
}
lock (this)
{
threads.Remove(me);
}
}
}
}