/VsIntegration/Nemerle.Compiler.Utils/Async/AsyncWorker.n
http://github.com/xxVisorxx/nemerle · Unknown · 189 lines · 154 code · 35 blank · 0 comment · 0 complexity · f35e5de75a6a01546535c3bafc7773f6 MD5 · raw file
- using Nemerle.Collections;
- using Nemerle.Text;
- using Nemerle.Utility;
-
- using System;
- using System.Linq;
- using System.Collections.Generic;
- using System.Threading;
- using System.Diagnostics;
-
- using SCG = System.Collections.Generic;
- //using System.Runtime.Remoting.Messaging;
-
-
- namespace Nemerle.Compiler.Utils.Async
- {
- /// <summary>
- /// Description of AsyncWorker.
- /// </summary>
- public module AsyncWorker
- {
- /// Set to true for debuding purpose!
- public IsRunSynchronously : bool = false;
-
- _requestsQueue : SCG.Queue[AsyncRequest] = SCG.Queue();
- _responseQueue : SCG.Queue[AsyncResponse] = SCG.Queue();
- _waitWork : AutoResetEvent = AutoResetEvent(false);
- _thread : Thread;
-
- mutable _curentWork : AsyncRequest;
-
- this()
- {
- def maxStackSize = 12 * 1024 * 1024 * if (System.IntPtr.Size == 8) 2 else 1;
- _thread = Thread(ThreadStart(ThreadProc), maxStackSize);
- _thread.Priority = ThreadPriority.BelowNormal;
- _thread.IsBackground = true;
- _thread.Name = "AsyncWorker";
- unless (IsRunSynchronously)
- _thread.Start();
- }
-
- mutable _isStop : bool;
-
- public IsCurrentThreadTheAsyncWorker : bool { get { Thread.CurrentThread.Equals(_thread) } }
-
- public CheckCurrentThreadIsTheAsyncWorker() : void
- {
- unless (IsRunSynchronously)
- assert(IsCurrentThreadTheAsyncWorker);
- }
-
- public Stop() : void
- {
- _isStop = true;
-
- def curentWork = _curentWork;
-
- when (curentWork != null)
- curentWork.Stop = true;
-
- unless (IsRunSynchronously)
- ignore(_waitWork.Set());
- }
-
- /// ?????????? ????????? ?????? ????????? ??????? ???? ??????????? ??????? ????
- /// ????????? ? ??????? ???????.
- private GetNextRequest() : AsyncRequest
- {
- lock (_requestsQueue)
- {
- def loop()
- {
- if (_requestsQueue.IsEmpty())
- null
- else
- {
- def request = _requestsQueue.Dequeue();
-
- if (_requestsQueue.Exists(x => request.IsForceOutBy(x)))
- {
- request.Stop = true;
- request.MarkAsCompleted();
- loop()
- }
- else
- request
- }
- }
-
- loop()
- }
- }
-
- public DoSynchronously() : bool
- {
- if (IsRunSynchronously)
- {
- ThreadProc();
- !_requestsQueue.IsEmpty()
- }
- else
- false
- }
-
- private ThreadProc() : void
- {
- def loop()
- {
- when (_requestsQueue.IsEmpty() && !_isStop && !IsRunSynchronously)
- ignore(_waitWork.WaitOne());
-
- Thread.Sleep(0);
-
- _curentWork = if (_isStop) null else GetNextRequest();
-
- when (!_isStop && _curentWork != null)
- try { _curentWork.DoWork(); }
- catch
- { | e =>
- Debug.WriteLine($"AsyncWorker thread exception($(e.GetType().Name)):");
- Debug.WriteLine($" $(e.Message)");
- //_ = e.StackTrace;
- _curentWork.MarkAsCompleted();
- }
-
- Thread.Sleep(10);
-
- unless (IsRunSynchronously)
- unless (_isStop)
- loop();
- }
-
- loop();
- }
-
- public GetResponse() : AsyncResponse
- {
- lock (_responseQueue)
- _responseQueue.Dequeue();
- }
-
- public GetResponses() : array[AsyncResponse]
- {
- lock (_responseQueue)
- {
- def result = _responseQueue.ToArray();
- _responseQueue.Clear();
- result
- }
- }
-
- public DispatchResponses() : void
- {
- foreach (response in GetResponses())
- response();
- }
-
-
- public AddResponse(response : AsyncResponse) : void
- {
- lock (_responseQueue)
- _responseQueue.Enqueue(response);
- }
-
- public AddWork(request : AsyncRequest) : void
- {
- when (_isStop)
- throw InvalidOperationException("The AsyncWorker is in stoped state");
-
- lock (_requestsQueue)
- _requestsQueue.Enqueue(request);
-
- //VladD2: ???? ? ???? ?????? ??????????? ?????? (_curentWork != null) ??????? ??????
- // ????? ??? ?????????? ??????? ?????? (????????, ?????? ?? ?????????? ??????? ?????),
- // ????? ?????????? _curentWork.Stop ? true.
- def curentWork = _curentWork;
-
- when (curentWork != null && curentWork.IsForceOutBy(request))
- {
- curentWork.Stop = true;
- curentWork.MarkAsCompleted();
- }
-
- unless (IsRunSynchronously)
- ignore(_waitWork.Set());
- }
- }
- }