comparison Framework/Toolbox/DownloadStack.cpp @ 0:351ab0da0150

initial commit
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 14 Oct 2016 15:34:11 +0200
parents
children ff1e935768e7
comparison
equal deleted inserted replaced
-1:000000000000 0:351ab0da0150
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 *
6 * This program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * In addition, as a special exception, the copyright holders of this
12 * program give permission to link the code of its release with the
13 * OpenSSL project's "OpenSSL" library (or with modified versions of it
14 * that use the same license as the "OpenSSL" library), and distribute
15 * the linked executables. You must obey the GNU General Public License
16 * in all respects for all of the code used other than "OpenSSL". If you
17 * modify file(s) with this exception, you may extend this exception to
18 * your version of the file(s), but you are not obligated to do so. If
19 * you do not wish to do so, delete this exception statement from your
20 * version. If you delete this exception statement from all source files
21 * in the program, then also delete it here.
22 *
23 * This program is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 **/
31
32
33 #include "DownloadStack.h"
34
35 #include "../Orthanc/Core/OrthancException.h"
36
37 #include <cassert>
38
39 namespace OrthancStone
40 {
41 bool DownloadStack::CheckInvariants() const
42 {
43 std::vector<bool> dequeued(nodes_.size(), true);
44
45 int i = firstNode_;
46 while (i != NIL)
47 {
48 const Node& node = nodes_[i];
49
50 dequeued[i] = false;
51
52 if (node.next_ != NIL &&
53 nodes_[node.next_].prev_ != i)
54 {
55 return false;
56 }
57
58 if (node.prev_ != NIL &&
59 nodes_[node.prev_].next_ != i)
60 {
61 return false;
62 }
63
64 i = nodes_[i].next_;
65 }
66
67 for (size_t i = 0; i < nodes_.size(); i++)
68 {
69 if (nodes_[i].dequeued_ != dequeued[i])
70 {
71 return false;
72 }
73 }
74
75 return true;
76 }
77
78
79 DownloadStack::DownloadStack(unsigned int size)
80 {
81 nodes_.resize(size);
82
83 if (size == 0)
84 {
85 firstNode_ = NIL;
86 }
87 else
88 {
89 for (size_t i = 0; i < size; i++)
90 {
91 nodes_[i].prev_ = i - 1;
92 nodes_[i].next_ = i + 1;
93 nodes_[i].dequeued_ = false;
94 }
95
96 nodes_.front().prev_ = NIL;
97 nodes_.back().next_ = NIL;
98 firstNode_ = 0;
99 }
100
101 assert(CheckInvariants());
102 }
103
104
105 DownloadStack::~DownloadStack()
106 {
107 assert(CheckInvariants());
108 }
109
110
111 bool DownloadStack::Pop(unsigned int& value)
112 {
113 boost::mutex::scoped_lock lock(mutex_);
114
115 assert(CheckInvariants());
116
117 if (firstNode_ == NIL)
118 {
119 for (size_t i = 0; i < nodes_.size(); i++)
120 {
121 assert(nodes_[i].dequeued_);
122 }
123
124 return false;
125 }
126 else
127 {
128 assert(firstNode_ >= 0 && firstNode_ < static_cast<int>(nodes_.size()));
129 value = firstNode_;
130
131 Node& node = nodes_[firstNode_];
132 assert(node.prev_ == NIL);
133 assert(!node.dequeued_);
134
135 node.dequeued_ = true;
136 firstNode_ = node.next_;
137
138 if (firstNode_ != NIL)
139 {
140 nodes_[firstNode_].prev_ = NIL;
141 }
142
143 return true;
144 }
145 }
146
147
148 void DownloadStack::SetTopNodeInternal(unsigned int value)
149 {
150 assert(CheckInvariants());
151
152 Node& node = nodes_[value];
153
154 if (node.dequeued_)
155 {
156 // This node has already been processed by the download thread, nothing to do
157 return;
158 }
159
160 // Remove the node from the list
161 if (node.prev_ == NIL)
162 {
163 assert(firstNode_ == static_cast<int>(value));
164
165 // This is already the top node in the list, nothing to do
166 return;
167 }
168
169 nodes_[node.prev_].next_ = node.next_;
170
171 if (node.next_ != NIL)
172 {
173 nodes_[node.next_].prev_ = node.prev_;
174 }
175
176 // Add back the node at the top of the list
177 assert(firstNode_ != NIL);
178
179 Node& old = nodes_[firstNode_];
180 assert(old.prev_ == NIL);
181 assert(!old.dequeued_);
182 node.prev_ = NIL;
183 node.next_ = firstNode_;
184 old.prev_ = value;
185
186 firstNode_ = value;
187 }
188
189
190 void DownloadStack::Writer::SetTopNode(unsigned int value)
191 {
192 if (value >= that_.nodes_.size())
193 {
194 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
195 }
196
197 that_.SetTopNodeInternal(value);
198 }
199
200
201 void DownloadStack::Writer::SetTopNodePermissive(int value)
202 {
203 if (value >= 0 &&
204 value < static_cast<int>(that_.nodes_.size()))
205 {
206 that_.SetTopNodeInternal(value);
207 }
208 }
209 }