public void Consume(Job job) { Debug.Assert(HasAvailableWorkers, "Doesn't have available workers!"); if (!HasAvailableWorkers) throw new InvalidOperationException("Hey! Check HasAvailableWorkers value first!"); Thread sendJobThread = new Thread(new ThreadStart(() => { ConnectionInfo selectedConnection = null; // TODO: Is there a better way to do this without locking? lock(mListLocker) { foreach (ConnectionInfo connection in mConnectionList.Values) { // Check if it's connected and set as in use if (connection.Smasher.Connected && Interlocked.CompareExchange(ref connection.mUseCount, 1, 0) == 0) { selectedConnection = connection; break; } } } // We do this outside the foreach so that the lock takes as less time as possible if (selectedConnection != null) { Console.WriteLine("REMCONS - Sending job {0} to remote Smasher", job.Id); // We create the formatter and stream here because they might not be thread safe BinaryFormatter formatter = new BinaryFormatter(); NetworkStream stream = new NetworkStream(selectedConnection.Smasher); formatter.Serialize(stream, job); // Start reading after this (block while reading), if it fails, add job back to queue // TODO: Add timeout Job result = (Job)formatter.Deserialize(stream); if (result != null) { if (JobFinished != null) JobFinished(this, result); } // Go back to unused Interlocked.Exchange(ref selectedConnection.mUseCount, 0); } else { // We could use the HasAvailableWorkers to only let it Consume if there were AVAILABLE workers // but we'd have to iterate through each connection everytime we call HasAvailableWorkers... // not ideal. It's much simpler to simply add the job back to the queue // TODO: Obviously this needs more work and thought! We don't want a job to keep coming back and // forward because we only have a connection and is being used! if (JobFailed != null) JobFailed(this, job); } })); sendJobThread.Start(); }
public void EnqueueJob(Job job) { lock (mQueueLocker) { mJobQueue.Enqueue(job); Monitor.Pulse(mQueueLocker); } }
public void Consume(Job job) { Debug.Assert(HasAvailableWorkers, "Doesn't have available workers!"); if (!HasAvailableWorkers) throw new InvalidOperationException("Hey! We're busy! Check HasAvailableWorkers value first!"); Interlocked.Increment(ref mNumOfActiveWorkers); if (JobStarted != null) JobStarted(this, job); // Invoke job in a different thread // TODO: Cache threads and pass the job in the parameters Thread jobThread = new Thread(new ThreadStart(() => { job.Invoke(); if (JobFinished != null) JobFinished(this, job); Interlocked.Decrement(ref mNumOfActiveWorkers); })); jobThread.Start(); }
public RemoteJob(Job original, Socket parent, Action<RemoteJob> finishAction) : base(original.Id) { mOriginalJob = original; mParentSmasher = parent; mFinishAction = finishAction; }