Skip to content

Commit

Permalink
Change: Attempt to tune threading a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
leezer3 committed Jul 22, 2024
1 parent 2539167 commit 71689f6
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 50 deletions.
43 changes: 17 additions & 26 deletions source/OpenBVE/System/GameWindow.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
Expand Down Expand Up @@ -394,8 +395,7 @@ protected override void OnLoad(EventArgs e)
}
Program.FileSystem.AppendToLogFile("Game window initialised successfully.");
//Initialise the loader thread queues
jobs = new Queue<ThreadStart>(10);
locks = new Queue<object>(10);
jobs = new ConcurrentQueue<ThreadStart>();
Program.Renderer.Initialize();
Program.Renderer.DetermineMaxAFLevel();
Interface.CurrentOptions.Save(OpenBveApi.Path.CombineFile(Program.FileSystem.SettingsFolder, "1.5.0/options.cfg"));
Expand Down Expand Up @@ -1126,18 +1126,15 @@ public void LoadingScreenLoop()

if (Loading.JobAvailable)
{
while (jobs.Count > 0)
while (!jobs.IsEmpty)
{
lock (jobLock)
jobs.TryDequeue(out ThreadStart currentJob);
currentJob();
lock (currentJob)
{
var currentJob = jobs.Dequeue();
var locker = locks.Dequeue();
currentJob();
lock (locker)
{
Monitor.Pulse(locker);
}
Monitor.Pulse(currentJob);
}

}
Loading.JobAvailable = false;
}
Expand All @@ -1156,28 +1153,22 @@ public void LoadingScreenLoop()
}
}

private static readonly object jobLock = new object();
private static Queue<ThreadStart> jobs;
private static Queue<object> locks;
private static ConcurrentQueue<ThreadStart> jobs;

/// <summary>This method is used during loading to run commands requiring an OpenGL context in the main render loop</summary>
/// <param name="job">The OpenGL command</param>
/// <param name="timeout">The timeout</param>
internal static void RunInRenderThread(ThreadStart job, int timeout)
{
object locker = new object();
lock (jobLock)
{
jobs.Enqueue(job);
locks.Enqueue(locker);
//Don't set the job to available until after it's been loaded into the queue
Loading.JobAvailable = true;
}
lock (locker)
{
//Failsafe: If our job has taken more than the timeout, stop waiting for it
//A missing texture is probably better than an infinite loadscreen
Monitor.Wait(locker, timeout);
jobs.Enqueue(job);
//Don't set the job to available until after it's been loaded into the queue
Loading.JobAvailable = true;
//Failsafe: If our job has taken more than the timeout, stop waiting for it
//A missing texture is probably better than an infinite loadscreen
lock (job)
{
Monitor.Wait(job, timeout);
}
}
}
Expand Down
41 changes: 17 additions & 24 deletions source/RouteViewer/System/Gamewindow.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
Expand Down Expand Up @@ -152,15 +153,11 @@ public static void LoadingScreenLoop()
{
while (jobs.Count > 0)
{
lock (jobLock)
jobs.TryDequeue(out ThreadStart currentJob);
currentJob();
lock (currentJob)
{
var currentJob = jobs.Dequeue();
var locker = locks.Dequeue();
currentJob();
lock (locker)
{
Monitor.Pulse(locker);
}
Monitor.Pulse(currentJob);
}
}
Loading.JobAvailable = false;
Expand All @@ -184,29 +181,25 @@ public static void LoadingScreenLoop()
}
}

internal static readonly object LoadingLock = new object();

private static readonly object jobLock = new object();
#pragma warning disable 0649
private static Queue<ThreadStart> jobs;
private static Queue<object> locks;
#pragma warning restore 0649
private static ConcurrentQueue<ThreadStart> jobs;
#pragma warning enable 0649

/// <summary>This method is used during loading to run commands requiring an OpenGL context in the main render loop</summary>
/// <param name="job">The OpenGL command</param>
internal static void RunInRenderThread(ThreadStart job)
/// <param name="timeout">The timeout</param>
internal static void RunInRenderThread(ThreadStart job, int timeout)
{
object locker = new object();
lock (jobLock)
{
Loading.JobAvailable = true;
jobs.Enqueue(job);
locks.Enqueue(locker);
}
lock (locker)
jobs.Enqueue(job);
//Don't set the job to available until after it's been loaded into the queue
Loading.JobAvailable = true;
//Failsafe: If our job has taken more than the timeout, stop waiting for it
//A missing texture is probably better than an infinite loadscreen
lock (job)
{
Monitor.Wait(locker);
Monitor.Wait(job, timeout);
}
}
}
}
}

0 comments on commit 71689f6

Please sign in to comment.