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();
        }
示例#2
0
 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;
 }