llqueuedthread.h

Go to the documentation of this file.
00001 
00032 #ifndef LL_LLQUEUEDTHREAD_H
00033 #define LL_LLQUEUEDTHREAD_H
00034 
00035 #include <queue>
00036 #include <string>
00037 #include <map>
00038 #include <set>
00039 
00040 #include "llapr.h"
00041 
00042 #include "llthread.h"
00043 #include "llsimplehash.h"
00044 
00045 //============================================================================
00046 // Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small
00047 //   It is assumed that LLQueuedThreads are rarely created/destroyed.
00048 
00049 class LLQueuedThread : public LLThread
00050 {
00051         //------------------------------------------------------------------------
00052 public:
00053         enum priority_t {
00054                 PRIORITY_IMMEDIATE = 0x7FFFFFFF,
00055                 PRIORITY_URGENT =    0x40000000,
00056                 PRIORITY_HIGH =      0x30000000,
00057                 PRIORITY_NORMAL =    0x20000000,
00058                 PRIORITY_LOW =       0x10000000,
00059                 PRIORITY_LOWBITS =   0x0FFFFFFF,
00060                 PRIORITY_HIGHBITS =  0x70000000
00061         };
00062         enum status_t {
00063                 STATUS_EXPIRED = -1,
00064                 STATUS_UNKNOWN = 0,
00065                 STATUS_QUEUED = 1,
00066                 STATUS_INPROGRESS = 2,
00067                 STATUS_COMPLETE = 3,
00068                 STATUS_ABORTED = 4,
00069                 STATUS_DELETE = 5
00070         };
00071         enum flags_t {
00072                 FLAG_AUTO_COMPLETE = 1,
00073                 FLAG_AUTO_DELETE = 2, // child-class dependent
00074                 FLAG_ABORT = 4
00075         };
00076 
00077         typedef U32 handle_t;
00078         
00079         //------------------------------------------------------------------------
00080 public:
00081 
00082         class QueuedRequest : public LLSimpleHashEntry<handle_t>
00083         {
00084                 friend class LLQueuedThread;
00085                 
00086         protected:
00087                 virtual ~QueuedRequest(); // use deleteRequest()
00088                 
00089         public:
00090                 QueuedRequest(handle_t handle, U32 priority, U32 flags = 0);
00091 
00092                 status_t getStatus()
00093                 {
00094                         return mStatus;
00095                 }
00096                 U32 getPriority() const
00097                 {
00098                         return mPriority;
00099                 }
00100                 U32 getFlags() const
00101                 {
00102                         return mFlags;
00103                 }
00104                 bool higherPriority(const QueuedRequest& second) const
00105                 {
00106                         if ( mPriority == second.mPriority)
00107                                 return mHashKey < second.mHashKey;
00108                         else
00109                                 return mPriority > second.mPriority;
00110                 }
00111 
00112         protected:
00113                 status_t setStatus(status_t newstatus)
00114                 {
00115                         status_t oldstatus = mStatus;
00116                         mStatus = newstatus;
00117                         return oldstatus;
00118                 }
00119                 void setFlags(U32 flags)
00120                 {
00121                         // NOTE: flags are |'d
00122                         mFlags |= flags;
00123                 }
00124                 
00125                 virtual bool processRequest() = 0; // Return true when request has completed
00126                 virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
00127                 virtual void deleteRequest(); // Only method to delete a request
00128 
00129                 void setPriority(U32 pri)
00130                 {
00131                         // Only do this on a request that is not in a queued list!
00132                         mPriority = pri;
00133                 };
00134                 
00135         protected:
00136                 LLAtomic32<status_t> mStatus;
00137                 U32 mPriority;
00138                 U32 mFlags;
00139         };
00140 
00141 protected:
00142         struct queued_request_less
00143         {
00144                 bool operator()(const QueuedRequest* lhs, const QueuedRequest* rhs) const
00145                 {
00146                         return lhs->higherPriority(*rhs); // higher priority in front of queue (set)
00147                 }
00148         };
00149 
00150         //------------------------------------------------------------------------
00151         
00152 public:
00153         static handle_t nullHandle() { return handle_t(0); }
00154         
00155 public:
00156         LLQueuedThread(const std::string& name, bool threaded = true);
00157         virtual ~LLQueuedThread();      
00158         virtual void shutdown();
00159         
00160 private:
00161         // No copy constructor or copy assignment
00162         LLQueuedThread(const LLQueuedThread&);
00163         LLQueuedThread& operator=(const LLQueuedThread&);
00164 
00165         virtual bool runCondition(void);
00166         virtual void run(void);
00167 
00168 protected:
00169         handle_t generateHandle();
00170         bool addRequest(QueuedRequest* req);
00171         S32  processNextRequest(void);
00172         void incQueue();
00173 
00174 public:
00175         bool waitForResult(handle_t handle, bool auto_complete = true);
00176 
00177         virtual S32 update(U32 max_time_ms);
00178         S32 updateQueue(U32 max_time_ms);
00179         
00180         void waitOnPending();
00181         void printQueueStats();
00182 
00183         S32 getPending();
00184         bool getThreaded() { return mThreaded ? true : false; }
00185 
00186         // Request accessors
00187         status_t getRequestStatus(handle_t handle);
00188         void abortRequest(handle_t handle, bool autocomplete);
00189         void setFlags(handle_t handle, U32 flags);
00190         void setPriority(handle_t handle, U32 priority);
00191         bool completeRequest(handle_t handle);
00192         // This is public for support classes like LLWorkerThread,
00193         // but generally the methods above should be used.
00194         QueuedRequest* getRequest(handle_t handle);
00195 
00196         // debug (see source)
00197         bool check();
00198         
00199 protected:
00200         BOOL mThreaded;  // if false, run on main thread and do updates during update()
00201         LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
00202         
00203         typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
00204         request_queue_t mRequestQueue;
00205 
00206         enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2
00207         typedef LLSimpleHash<handle_t, REQUEST_HASH_SIZE> request_hash_t;
00208         request_hash_t mRequestHash;
00209 
00210         handle_t mNextHandle;
00211 };
00212 
00213 #endif // LL_LLQUEUEDTHREAD_H

Generated on Thu Jul 1 06:09:04 2010 for Second Life Viewer by  doxygen 1.4.7