Add thread validation to the .NET compressor object.
Plus for safeties sake use BeginThreadAffinity()...
This commit is contained in:
parent
89206909a4
commit
20b73458a5
@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace Nvidia.TextureTools
|
||||
{
|
||||
@ -159,7 +161,12 @@ namespace Nvidia.TextureTools
|
||||
get { return errorCode; }
|
||||
}
|
||||
|
||||
public TextureToolsException(Error errorCode) : base(Compressor.ErrorString(errorCode))
|
||||
public TextureToolsException(Error errorCode) : this(errorCode, Compressor.ErrorString(errorCode))
|
||||
{
|
||||
}
|
||||
|
||||
public TextureToolsException(Error errorCode, string msg)
|
||||
: base(msg)
|
||||
{
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
@ -720,14 +727,24 @@ namespace Nvidia.TextureTools
|
||||
#endregion
|
||||
|
||||
internal IntPtr compressor;
|
||||
private Thread creatingThread;
|
||||
|
||||
public Compressor()
|
||||
{
|
||||
/*
|
||||
* Strictly speaking the CLR may decide to move managed threads between OS thread, to prevent this we call BeginThreadAffinity().
|
||||
* In practice this doesnt happen, but it may if the host is using some form of custom thread management.
|
||||
*/
|
||||
creatingThread = Thread.CurrentThread;
|
||||
Thread.BeginThreadAffinity();
|
||||
|
||||
compressor = nvttCreateCompressor();
|
||||
}
|
||||
|
||||
public void Compress(InputOptions input, CompressionOptions compression, OutputOptions output)
|
||||
{
|
||||
ValidateThread();
|
||||
|
||||
if (!nvttCompress(compressor, input.options, compression.options, output.options))
|
||||
{
|
||||
//An error occured, use the last error registered.
|
||||
@ -737,6 +754,8 @@ namespace Nvidia.TextureTools
|
||||
|
||||
public int EstimateSize(InputOptions input, CompressionOptions compression)
|
||||
{
|
||||
ValidateThread();
|
||||
|
||||
return nvttEstimateSize(compressor, input.options, compression.options);
|
||||
}
|
||||
|
||||
@ -752,9 +771,20 @@ namespace Nvidia.TextureTools
|
||||
|
||||
public void SetEnableCuda(bool enableCuda)
|
||||
{
|
||||
ValidateThread();
|
||||
|
||||
nvttEnableCudaCompression(compressor, enableCuda);
|
||||
}
|
||||
|
||||
private void ValidateThread()
|
||||
{
|
||||
if (Thread.CurrentThread != creatingThread)
|
||||
{
|
||||
throw new TextureToolsException(Error.Unknown, "Compressor objects should only be used on the thread which creates them, this is because CUDA stores per thread data.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
@ -766,11 +796,31 @@ namespace Nvidia.TextureTools
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
|
||||
if (compressor != IntPtr.Zero)
|
||||
{
|
||||
if (!disposing)
|
||||
{
|
||||
/*
|
||||
* Throwing exceptions from finalizers is a bad idea, so just let the user know in a debug build.
|
||||
* Otherwise we presumably leak the cuda context data, but still deallocate the memory for the compressor object.
|
||||
*/
|
||||
Debug.Fail("Compressor objects should always be disposed on the thread which creates them, this is because CUDA stores per thread data which should be cleaned up on the calling thread");
|
||||
}
|
||||
else
|
||||
{
|
||||
ValidateThread();
|
||||
}
|
||||
|
||||
nvttDestroyCompressor(compressor);
|
||||
compressor = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (creatingThread != null)
|
||||
{
|
||||
Thread.EndThreadAffinity();
|
||||
creatingThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
~Compressor()
|
||||
|
Loading…
Reference in New Issue
Block a user