4 using System.Collections.Concurrent;
5 using System.Collections.Generic;
8 using System.Threading;
9 using SiliconStudio.BuildEngine;
10 using SiliconStudio.Core.Diagnostics;
11 using SiliconStudio.Core.IO;
12 using SiliconStudio.Core.Storage;
14 namespace SiliconStudio.Assets
18 private static readonly
object TrackerLock =
new object();
21 private readonly Thread asyncRunner;
22 private readonly AutoResetEvent asyncRequestAvailable;
23 private readonly ConcurrentQueue<AsyncRequest> asyncRequests;
24 private bool isDisposing;
25 private bool isDisposed;
30 asyncRequestAvailable =
new AutoResetEvent(
false);
31 asyncRequests =
new ConcurrentQueue<AsyncRequest>();
34 tracker = FileVersionTracker.GetDefault();
35 asyncRunner =
new Thread(
SafeAction.
Wrap(ComputeFileHashAsyncRunner)) { IsBackground =
true };
49 AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
68 if (!
File.Exists(path))
71 return tracker.ComputeFileHash(path);
75 public void ComputeFileHashAsync(
UFile path, Action<UFile, ObjectId> fileHashCallback = null, CancellationToken? cancellationToken = null)
77 if (path == null)
throw new ArgumentNullException(
"path");
81 asyncRequests.Enqueue(
new AsyncRequest(path, fileHashCallback, cancellationToken));
83 asyncRequestAvailable.Set();
88 if (paths == null)
throw new ArgumentNullException(
"paths");
92 foreach(var path
in paths)
93 asyncRequests.Enqueue(
new AsyncRequest(path, fileHashCallback, cancellationToken));
95 asyncRequestAvailable.Set();
98 private readonly HashSet<AsyncRequest> requestsToProcess =
new HashSet<AsyncRequest>();
100 private void ComputeFileHashAsyncRunner()
104 if (asyncRequestAvailable.WaitOne())
111 AsyncRequest asyncRequest;
112 if (asyncRequests.TryDequeue(out asyncRequest))
114 requestsToProcess.Add(asyncRequest);
130 foreach (var request
in requestsToProcess)
137 if (request.CancellationToken.HasValue && request.CancellationToken.Value.IsCancellationRequested)
142 var hash = ComputeFileHash(request.File);
144 if (request.CancellationToken.HasValue && request.CancellationToken.Value.IsCancellationRequested)
154 if (request.FileHashCallback != null)
160 requestsToProcess.Clear();
164 private static void CurrentDomain_ProcessExit(
object sender,
EventArgs e)
169 private void Dispose()
176 asyncRequestAvailable.Set();
183 private struct AsyncRequest : IEquatable<AsyncRequest>
185 public AsyncRequest(
UFile file, Action<UFile, ObjectId> fileHashCallback, CancellationToken? cancellationToken)
188 FileHashCallback = fileHashCallback;
189 CancellationToken = cancellationToken;
194 public readonly Action<UFile, ObjectId> FileHashCallback;
196 public readonly CancellationToken? CancellationToken;
198 public bool Equals(AsyncRequest other)
200 return Equals(
File, other.File) && Equals(FileHashCallback, other.FileHashCallback) && CancellationToken.Equals(other.CancellationToken);
203 public override bool Equals(
object obj)
205 if (ReferenceEquals(null, obj))
return false;
206 return obj is AsyncRequest && Equals((AsyncRequest)obj);
209 public override int GetHashCode()
213 int hashCode = (
File != null ? File.GetHashCode() : 0);
214 hashCode = (hashCode*397) ^ (FileHashCallback != null ? FileHashCallback.GetHashCode() : 0);
215 hashCode = (hashCode*397) ^ CancellationToken.GetHashCode();
220 public static bool operator ==(AsyncRequest left, AsyncRequest right)
222 return left.Equals(right);
225 public static bool operator !=(AsyncRequest left, AsyncRequest right)
227 return !left.Equals(right);
ObjectId ComputeFileHash(UFile path)
static ThreadStart Wrap(ThreadStart action, [CallerFilePath] string sourceFilePath="", [CallerMemberName] string memberName="", [CallerLineNumber] int sourceLineNumber=0)
void ComputeFileHashAsync(IEnumerable< UFile > paths, Action< UFile, ObjectId > fileHashCallback=null, CancellationToken?cancellationToken=null)
void ComputeFileHashAsync(UFile path, Action< UFile, ObjectId > fileHashCallback=null, CancellationToken?cancellationToken=null)
static readonly ObjectId Empty
A hash to uniquely identify data.
Defines a normalized file path. See UPath for details. This class cannot be inherited.