1 /**************************************************************************/
2 /*  Copyright 2012 Tim Day                                                */
3 /*                                                                        */
4 /*  This file is part of Evolvotron                                       */
5 /*                                                                        */
6 /*  Evolvotron is free software: you can redistribute it and/or modify    */
7 /*  it under the terms of the GNU General Public License as published by  */
8 /*  the Free Software Foundation, either version 3 of the License, or     */
9 /*  (at your option) any later version.                                   */
10 /*                                                                        */
11 /*  Evolvotron is distributed in the hope that it will be useful,         */
12 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
13 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
14 /*  GNU General Public License for more details.                          */
15 /*                                                                        */
16 /*  You should have received a copy of the GNU General Public License     */
17 /*  along with Evolvotron.  If not, see <http://www.gnu.org/licenses/>.   */
18 /**************************************************************************/
19 
20 /*! \file
21   \brief Interface for class MutatableImageComputerFarm.
22 */
23 
24 #ifndef _mutatable_image_computer_farm_h_
25 #define _mutatable_image_computer_farm_h_
26 
27 #include "common.h"
28 #include "useful.h"
29 
30 #include "mutatable_image_computer.h"
31 #include "mutatable_image_computer_task.h"
32 
33 class MutatableImageComputer;
34 class MutatableImageDisplay;
35 
36 //! Class encapsulating some compute threads and queues of tasks to be done and tasks completed.
37 /*! Priority queues are implemented using multiset becase we want to be able to iterate over all members.
38  */
39 class MutatableImageComputerFarm
40 {
41  protected:
42 
43   //! Comparison class for STL template.
44   class CompareTaskPriorityLoResFirst : public std::binary_function<boost::shared_ptr<const MutatableImageComputerTask>,boost::shared_ptr<const MutatableImageComputerTask>,bool>
45     {
46     public:
47       //! Compare task priorities.
operator()48       bool operator()(const boost::shared_ptr<const MutatableImageComputerTask>& t0,const boost::shared_ptr<const MutatableImageComputerTask>& t1)
49 	{
50 	  return (t0->priority() < t1->priority());
51 	}
52     };
53 
54   //! Comparison class for STL template.
55   class CompareTaskPriorityHiResFirst : public std::binary_function<boost::shared_ptr<const MutatableImageComputerTask>,boost::shared_ptr<const MutatableImageComputerTask>,bool>
56     {
57     public:
58       //! Compare task priorities.
operator()59       bool operator()(const boost::shared_ptr<const MutatableImageComputerTask>& t0,const boost::shared_ptr<const MutatableImageComputerTask>& t1)
60 	{
61 	  return (t0->priority() > t1->priority());
62 	}
63     };
64 
65   //! Mutex for locking.  This is the ONLY thing the compute threads should ever block on.
66   mutable QMutex _mutex;
67 
68   //! Wait condition for threads waiting for a new task.
69   QWaitCondition _wait_condition;
70 
71   //! The compute threads
72   boost::ptr_vector<MutatableImageComputer> _computers;
73 
74   //! Convenience typedef.
75   typedef std::multiset<boost::shared_ptr<MutatableImageComputerTask>,CompareTaskPriorityLoResFirst> TodoQueue;
76 
77   //! Queue of tasks to be performed, lowest resolution first
78   TodoQueue _todo;
79 
80   //! Conveniencetypedef.
81   typedef std::multiset<boost::shared_ptr<MutatableImageComputerTask>,CompareTaskPriorityHiResFirst> DoneQueue;
82 
83   //! Convenience typedef.
84   /*! const because never needs to do anything other than compare pointers
85    */
86   typedef std::map<const MutatableImageDisplay*,DoneQueue> DoneQueueByDisplay;
87 
88   //! Queue of tasks completed awaiting display.
89   /*! We reverse the compute priority so that highest resolution images get displayed first.
90       Lower resolution ones arriving later should be discarded by the displays.
91       This mainly makes a difference for animation where enlarging multiple low resolution
92       images to screen res takes a lot of time.  May help low-bandwidth X11 connections
93       by minimising redraws too.
94       We now also sort by display and do round-robin delivery (ithout this one display can run way ahead of the others)
95    */
96   DoneQueueByDisplay _done;
97 
98   //! Points to the next display queue to be returned (could be .end())
99   DoneQueueByDisplay::iterator _done_position;
100 
101  public:
102 
103   //! Constructor.
104   MutatableImageComputerFarm(uint n_threads,int niceness);
105 
106   //! Destructor cleans up threads.
107   ~MutatableImageComputerFarm();
108 
109   //! Accessor.
num_threads()110   uint num_threads() const
111     {
112       return _computers.size();
113     }
114 
115   //! Move aborted tasks from todo queue to done queue.
116   void fasttrack_aborted();
117 
118   //! Enqueue a task for computing.
119   void push_todo(const boost::shared_ptr<MutatableImageComputerTask>&);
120 
121   //! Remove a task from the head of the todo queue (returns null if none).
122   const boost::shared_ptr<MutatableImageComputerTask> pop_todo(MutatableImageComputer& requester);
123 
124   //! Enqueue a task for display.
125   void push_done(const boost::shared_ptr<MutatableImageComputerTask>&);
126 
127   //! Remove a task from the head of the display queue (returns null if none).
128   const boost::shared_ptr<MutatableImageComputerTask> pop_done();
129 
130   //! Flags all tasks in all queues as aborted, and signals the compute threads to abort their current task.
131   void abort_all();
132 
133   //! Flags all tasks for a particular display as aborted (including compute threads)
134   void abort_for(const MutatableImageDisplay* disp);
135 
136   //! Number of tasks in queues
137   uint tasks() const;
138 };
139 
140 #endif
141