1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
14#ifndef OSG_OPERATIONTHREAD
15#define OSG_OPERATIONTHREAD 1
17#include <osg/observer_ptr>
20#include <OpenThreads/Thread>
21#include <OpenThreads/Barrier>
22#include <OpenThreads/Condition>
23#include <OpenThreads/Block>
30class RefBlock : virtual public osg::Referenced, public OpenThreads::Block
35 osg::Referenced(true) {}
39class RefBlockCount : virtual public osg::Referenced, public OpenThreads::BlockCount
43 RefBlockCount(unsigned blockCount):
44 osg::Referenced(true),
45 OpenThreads::BlockCount(blockCount) {}
49/** Base class for implementing graphics operations.*/
50class Operation : virtual public Referenced
54 Operation(const std::string& name, bool keep):
59 /** Set the human readable name of the operation.*/
60 void setName(const std::string& name) { _name = name; }
62 /** Get the human readable name of the operation.*/
63 const std::string& getName() const { return _name; }
65 /** Set whether the operation should be kept once its been applied.*/
66 void setKeep(bool keep) { _keep = keep; }
68 /** Get whether the operation should be kept once its been applied.*/
69 bool getKeep() const { return _keep; }
71 /** if this operation is a barrier then release it.*/
72 virtual void release() {}
74 /** Do the actual task of this operation.*/
75 virtual void operator () (Object*) = 0;
82 virtual ~Operation() {}
90class OSG_EXPORT OperationQueue : public Referenced
96 /** Get the next operation from the operation queue.
97 * Return null ref_ptr<> if no operations are left in queue. */
98 osg::ref_ptr<Operation> getNextOperation(bool blockIfEmpty = false);
100 /** Return true if the operation queue is empty. */
103 /** Return the num of pending operations that are sitting in the OperationQueue.*/
104 unsigned int getNumOperationsInQueue();
106 /** Add operation to end of OperationQueue, this will be
107 * executed by the operation thread once this operation gets to the head of the queue.*/
108 void add(Operation* operation);
110 /** Remove operation from OperationQueue.*/
111 void remove(Operation* operation);
113 /** Remove named operation from OperationQueue.*/
114 void remove(const std::string& name);
116 /** Remove all operations from OperationQueue.*/
117 void removeAllOperations();
119 /** Run the operations. */
120 void runOperations(Object* callingObject=0);
122 /** Call release on all operations. */
123 void releaseAllOperations();
125 /** Release operations block that is used to block threads that are waiting on an empty operations queue.*/
126 void releaseOperationsBlock();
128 typedef std::set<OperationThread*> OperationThreads;
130 /** Get the set of OperationThreads that are sharing this OperationQueue. */
131 const OperationThreads& getOperationThreads() const { return _operationThreads; }
135 virtual ~OperationQueue();
137 friend class OperationThread;
139 void addOperationThread(OperationThread* thread);
140 void removeOperationThread(OperationThread* thread);
142 typedef std::list< osg::ref_ptr<Operation> > Operations;
144 OpenThreads::Mutex _operationsMutex;
145 osg::ref_ptr<osg::RefBlock> _operationsBlock;
146 Operations _operations;
147 Operations::iterator _currentOperationIterator;
149 OperationThreads _operationThreads;
152/** OperationThread is a helper class for running Operation within a single thread.*/
153class OSG_EXPORT OperationThread : public Referenced, public OpenThreads::Thread
158 void setParent(Object* parent) { _parent = parent; }
160 Object* getParent() { return _parent.get(); }
162 const Object* getParent() const { return _parent.get(); }
165 /** Set the OperationQueue. */
166 void setOperationQueue(OperationQueue* opq);
168 /** Get the OperationQueue. */
169 OperationQueue* getOperationQueue() { return _operationQueue.get(); }
171 /** Get the const OperationQueue. */
172 const OperationQueue* getOperationQueue() const { return _operationQueue.get(); }
175 /** Add operation to end of OperationQueue, this will be
176 * executed by the graphics thread once this operation gets to the head of the queue.*/
177 void add(Operation* operation);
179 /** Remove operation from OperationQueue.*/
180 void remove(Operation* operation);
182 /** Remove named operation from OperationQueue.*/
183 void remove(const std::string& name);
185 /** Remove all operations from OperationQueue.*/
186 void removeAllOperations();
189 /** Get the operation currently being run.*/
190 osg::ref_ptr<Operation> getCurrentOperation() { return _currentOperation; }
192 /** Run does the opertion thread run loop.*/
195 void setDone(bool done);
197 bool getDone() const { return _done!=0; }
199 /** Cancel this graphics thread.*/
200 virtual int cancel();
204 virtual ~OperationThread();
206 observer_ptr<Object> _parent;
208 OpenThreads::Atomic _done;
210 OpenThreads::Mutex _threadMutex;
211 osg::ref_ptr<OperationQueue> _operationQueue;
212 osg::ref_ptr<Operation> _currentOperation;
216typedef OperationThread OperationsThread;