source: ThirdParty/mpqc_open/src/lib/util/group/rnglock.cc@ 398fcd

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 398fcd was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 9.0 KB
Line 
1//
2// rnglock.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#ifdef __GNUC__
29#pragma implementation
30#endif
31
32#include <new>
33
34#include <util/misc/formio.h>
35#include <util/group/rnglock.h>
36#include <util/group/pool.h>
37
38using namespace std;
39using namespace sc;
40
41#define CHECK 0
42
43namespace sc {
44
45/////////////////////////////////////////////////////////////////////
46// RangeLockItem members
47
48void *
49RangeLockItem::operator new(size_t size, Pool * pool)
50{
51 if (pool) return pool->allocate(size);
52 else return ::operator new(size);
53}
54
55void
56RangeLockItem::operator delete(void* r, Pool *pool)
57{
58 if (pool) pool->release(r);
59 else ::operator delete(r);
60}
61
62/////////////////////////////////////////////////////////////////////
63// Utility classes
64
65class RangeLockValOp {
66 public:
67 virtual ~RangeLockValOp() {};
68 virtual void op(int&) = 0;
69};
70
71class RangeLockValSum: public RangeLockValOp {
72 private:
73 int delta;
74 public:
75 RangeLockValSum(int d): delta(d) {}
76 void op(int &i) { i += delta; }
77};
78
79class RangeLockValSet: public RangeLockValOp {
80 private:
81 int val;
82 public:
83 RangeLockValSet(int v): val(v) {}
84 void op(int &i) { i = val; }
85};
86
87/////////////////////////////////////////////////////////////////////
88// Members of RangeLock
89
90RangeLock::RangeLock(Pool *pool)
91{
92 pool_ = pool;
93 root_ = 0;
94}
95
96RangeLock::~RangeLock()
97{
98 for (RangeLockItem *i = root_; i;) {
99 RangeLockItem *next = i->next;
100 RangeLockItem::operator delete(i, pool_);
101 i = next;
102 }
103}
104
105int
106RangeLock::lockvalue(int loc)
107{
108 for (RangeLockItem *i = root_; i; i = i->next) {
109 if (loc >= i->start && loc < i->fence) {
110 return i->value;
111 }
112 if (loc < i->fence) break;
113 }
114 return 0;
115}
116
117int
118RangeLock::checkeq(int start, int fence, int value)
119{
120 split_ranges(start, fence);
121 for (RangeLockItem *i = root_; i; i = i->next) {
122 if (start >= i->start && start < i->fence
123 || fence > i->start && fence <= i->fence
124 || start < i->start && fence > i->fence) {
125 if (value != i->value) return 0;
126 }
127 if (fence < i->fence) break;
128 }
129 return 1;
130}
131
132int
133RangeLock::checkgr(int start, int fence, int value)
134{
135 split_ranges(start, fence);
136 for (RangeLockItem *i = root_; i; i = i->next) {
137 if (start >= i->start && start < i->fence
138 || fence > i->start && fence <= i->fence
139 || start < i->start && fence > i->fence) {
140 if (i->value <= value) return 0;
141 }
142 if (fence < i->fence) break;
143 }
144 return 1;
145}
146
147void
148RangeLock::check()
149{
150 for (RangeLockItem* i = root_; i; i = i->next) {
151 int bad = 0;
152 if (i->next && i->next->prev != i) {
153 ExEnv::errn() << scprintf("i->next->prev bad\n");
154 bad = 1;
155 }
156 if (i->prev && i->prev->next != i) {
157 ExEnv::errn() << scprintf("i->prev->next bad\n");
158 bad = 1;
159 }
160 if (i->start >= i->fence) {
161 ExEnv::errn() << scprintf("start >= fence\n");
162 bad = 1;
163 }
164 if (i->next && i->fence > i->next->start) {
165 ExEnv::errn() << scprintf("fence > next start\n");
166 bad = 1;
167 }
168#if VERBOSE
169 ExEnv::outn()
170 << scprintf("i = 0x%08x, n = 0x%08x, p = 0x%08x, [%3d, %3d), %5d\n",
171 i, i->next, i->prev, i->start, i->fence, i->value);
172#endif
173 if (bad) abort();
174 }
175}
176
177void
178RangeLock::split_ranges(int start, int fence)
179{
180 if (root_ == 0) {
181 // no blocks are allocted yet, initialize one and return
182 root_ = new(pool_) RangeLockItem(0, 0, start, fence, 0);
183 return;
184 }
185
186 RangeLockItem *i;
187 for (i = root_; i; i=i->next) {
188 if (start > i->start && start < i->fence) {
189 // start is in the middle of this block, split it
190 RangeLockItem *t = new(pool_) RangeLockItem(i, i->next,
191 start, i->fence,
192 i->value);
193 i->fence = start;
194 i->next = t;
195 if (t->next) t->next->prev = t;
196 i = t;
197 break;
198 }
199 else if (start < i->start && fence <= i->start) {
200 // start and end are before this block, insert it and return
201 RangeLockItem *t = new(pool_) RangeLockItem(i->prev, i,
202 start, fence, 0);
203 i->prev = t;
204 if (t->prev) t->prev->next = t;
205 else root_ = t;
206 return;
207 }
208 else if (start < i->start) {
209 // start is before this block, fill in the gap
210 RangeLockItem *t = new(pool_) RangeLockItem(i->prev, i,
211 start, i->start, 0);
212 i->prev = t;
213 if (t->prev) t->prev->next = t;
214 else root_ = t;
215 break;
216 }
217 else if (start == i->start) {
218 // start coincides with this block's start
219 break;
220 }
221 else if (i->next == 0) {
222 // start is after the last block, make the block and return
223 RangeLockItem *t = new(pool_) RangeLockItem(i, 0, start, fence, 0);
224 i->next = t;
225 return;
226 }
227 // otherwise start is after this block, continue
228 }
229
230 for (; i; i=i->next) {
231 if (fence > i->start && i->prev && i->prev->fence < i->start) {
232 // fence is after this block and there is a gap before
233 RangeLockItem *t = new(pool_) RangeLockItem(i->prev, i,
234 i->prev->fence, i->start,
235 0);
236 i->prev = t;
237 if (t->prev) t->prev->next = t;
238 else root_ = t;
239 i = t;
240 }
241 else if (fence > i->start && fence < i->fence) {
242 // fence is in the middle of this block, split it and return
243 RangeLockItem *t = new(pool_) RangeLockItem(i->prev, i,
244 i->start, fence,
245 i->value);
246 i->start = fence;
247 i->prev = t;
248 if (t->prev) t->prev->next = t;
249 else root_ = t;
250 return;
251 }
252 else if (fence > i->fence && !i->next) {
253 // fence is after this block and no blocks follow
254 RangeLockItem *t = new(pool_) RangeLockItem(i, 0,
255 i->fence, fence, 0);
256 i->next = t;
257 return;
258 }
259 else if (fence <= i->start) {
260 // fence is before this block, fill in the gap
261 RangeLockItem *p = i->prev;
262 RangeLockItem *t = new(pool_) RangeLockItem(p, i,
263 p->fence, fence, 0);
264 p->next = t;
265 i->prev = t;
266 return;
267 }
268 else if (fence == i->fence) {
269 // fence coincides with this block's fence
270 return;
271 }
272 // otherwise fence is after this block, continue
273 }
274
275 ExEnv::errn() << scprintf("RangeLock::split_ranges(): got to end\n");
276 abort();
277}
278
279void
280RangeLock::do_valop(RangeLockValOp& op, int start, int fence)
281{
282 if (start == fence) return;
283
284 split_ranges(start, fence);
285
286#if CHECK
287 check();
288#endif
289
290 for (RangeLockItem *i = root_; i; i = i->next) {
291 if (start == i->start
292 || fence == i->fence
293 || start < i->start && fence > i->fence) {
294 op.op(i->value);
295 }
296 if (fence < i->fence) break;
297 }
298}
299
300void
301RangeLock::sum(int start, int fence, int delta)
302{
303 RangeLockValSum sum(delta);
304 do_valop(sum, start, fence);
305}
306
307void
308RangeLock::increment(int start, int fence)
309{
310 RangeLockValSum sum(1);
311 do_valop(sum, start, fence);
312}
313
314void
315RangeLock::decrement(int start, int fence)
316{
317 RangeLockValSum sum(-1);
318 do_valop(sum, start, fence);
319}
320
321void
322RangeLock::set(int start, int fence, int value)
323{
324 RangeLockValSet set(value);
325 do_valop(set, start, fence);
326}
327
328void
329RangeLock::print(ostream &o) const
330{
331 for (RangeLockItem *i = root_; i; i = i->next) {
332 o << scprintf(" RangeLockItem: [%5d, %5d): %4d\n",
333 i->start, i->fence, i->value);
334 }
335}
336
337/////////////////////////////////////////////////////////////////////////////
338
339}
340
341// Local Variables:
342// mode: c++
343// c-file-style: "CLJ"
344// End:
Note: See TracBrowser for help on using the repository browser.