diff options
Diffstat (limited to 'linden/indra/llcommon/llpriqueuemap.h')
-rw-r--r-- | linden/indra/llcommon/llpriqueuemap.h | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llpriqueuemap.h b/linden/indra/llcommon/llpriqueuemap.h new file mode 100644 index 0000000..20cbc6b --- /dev/null +++ b/linden/indra/llcommon/llpriqueuemap.h | |||
@@ -0,0 +1,146 @@ | |||
1 | /** | ||
2 | * @file llpriqueuemap.h | ||
3 | * @brief Priority queue implementation | ||
4 | * | ||
5 | * Copyright (c) 2003-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | #ifndef LL_LLPRIQUEUEMAP_H | ||
28 | #define LL_LLPRIQUEUEMAP_H | ||
29 | |||
30 | #include <map> | ||
31 | |||
32 | // | ||
33 | // Priority queue, implemented under the hood as a | ||
34 | // map. Needs to be done this way because none of the | ||
35 | // standard STL containers provide a representation | ||
36 | // where it's easy to reprioritize. | ||
37 | // | ||
38 | |||
39 | template <class DATA> | ||
40 | class LLPQMKey | ||
41 | { | ||
42 | public: | ||
43 | LLPQMKey(const F32 priority, DATA data) : mPriority(priority), mData(data) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | bool operator<(const LLPQMKey &b) const | ||
48 | { | ||
49 | if (mPriority > b.mPriority) | ||
50 | { | ||
51 | return TRUE; | ||
52 | } | ||
53 | if (mPriority < b.mPriority) | ||
54 | { | ||
55 | return FALSE; | ||
56 | } | ||
57 | if (mData > b.mData) | ||
58 | { | ||
59 | return TRUE; | ||
60 | } | ||
61 | return FALSE; | ||
62 | } | ||
63 | |||
64 | F32 mPriority; | ||
65 | DATA mData; | ||
66 | }; | ||
67 | |||
68 | template <class DATA_TYPE> | ||
69 | class LLPriQueueMap | ||
70 | { | ||
71 | public: | ||
72 | typedef typename std::map<LLPQMKey<DATA_TYPE>, DATA_TYPE>::iterator pqm_iter; | ||
73 | typedef std::pair<LLPQMKey<DATA_TYPE>, DATA_TYPE> pqm_pair; | ||
74 | typedef void (*set_pri_fn)(DATA_TYPE &data, const F32 priority); | ||
75 | typedef F32 (*get_pri_fn)(DATA_TYPE &data); | ||
76 | |||
77 | |||
78 | LLPriQueueMap(set_pri_fn set_pri, get_pri_fn get_pri) : mSetPriority(set_pri), mGetPriority(get_pri) | ||
79 | { | ||
80 | } | ||
81 | |||
82 | void push(const F32 priority, DATA_TYPE data) | ||
83 | { | ||
84 | #ifdef _DEBUG | ||
85 | pqm_iter iter = mMap.find(LLPQMKey<DATA_TYPE>(priority, data)); | ||
86 | if (iter != mMap.end()) | ||
87 | { | ||
88 | llerrs << "Pushing already existing data onto queue!" << llendl; | ||
89 | } | ||
90 | #endif | ||
91 | mMap.insert(pqm_pair(LLPQMKey<DATA_TYPE>(priority, data), data)); | ||
92 | } | ||
93 | |||
94 | BOOL pop(DATA_TYPE *datap) | ||
95 | { | ||
96 | pqm_iter iter; | ||
97 | iter = mMap.begin(); | ||
98 | if (iter == mMap.end()) | ||
99 | { | ||
100 | return FALSE; | ||
101 | } | ||
102 | *datap = (*(iter)).second; | ||
103 | mMap.erase(iter); | ||
104 | |||
105 | return TRUE; | ||
106 | } | ||
107 | |||
108 | void reprioritize(const F32 new_priority, DATA_TYPE data) | ||
109 | { | ||
110 | pqm_iter iter; | ||
111 | F32 cur_priority = mGetPriority(data); | ||
112 | LLPQMKey<DATA_TYPE> cur_key(cur_priority, data); | ||
113 | iter = mMap.find(cur_key); | ||
114 | if (iter == mMap.end()) | ||
115 | { | ||
116 | llwarns << "Data not on priority queue!" << llendl; | ||
117 | // OK, try iterating through all of the data and seeing if we just screwed up the priority | ||
118 | // somehow. | ||
119 | for (iter = mMap.begin(); iter != mMap.end(); iter++) | ||
120 | { | ||
121 | if ((*(iter)).second == data) | ||
122 | { | ||
123 | llerrs << "Data on priority queue but priority not matched!" << llendl; | ||
124 | } | ||
125 | } | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | mMap.erase(iter); | ||
130 | mSetPriority(data, new_priority); | ||
131 | push(new_priority, data); | ||
132 | } | ||
133 | |||
134 | S32 getLength() const | ||
135 | { | ||
136 | return (S32)mMap.size(); | ||
137 | } | ||
138 | |||
139 | // Hack: public for use by the transfer manager, ugh. | ||
140 | std::map<LLPQMKey<DATA_TYPE>, DATA_TYPE> mMap; | ||
141 | protected: | ||
142 | void (*mSetPriority)(DATA_TYPE &data, const F32 priority); | ||
143 | F32 (*mGetPriority)(DATA_TYPE &data); | ||
144 | }; | ||
145 | |||
146 | #endif // LL_LLPRIQUEUEMAP_H | ||