📄 rnglock.cc
字号:
//// rnglock.cc//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Curtis Janssen <cljanss@limitpt.com>// Maintainer: LPS//// This file is part of the SC Toolkit.//// The SC Toolkit is free software; you can redistribute it and/or modify// it under the terms of the GNU Library General Public License as published by// the Free Software Foundation; either version 2, or (at your option)// any later version.//// The SC Toolkit is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU Library General Public License for more details.//// You should have received a copy of the GNU Library General Public License// along with the SC Toolkit; see the file COPYING.LIB. If not, write to// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.//// The U.S. Government is granted a limited license as per AL 91-7.//#ifdef __GNUC__#pragma implementation#endif#include <new>#include <util/misc/formio.h>#include <util/group/rnglock.h>#include <util/group/pool.h>using namespace std;using namespace sc;#define CHECK 0namespace sc {/////////////////////////////////////////////////////////////////////// RangeLockItem membersvoid *RangeLockItem::operator new(size_t size, Pool * pool){ if (pool) return pool->allocate(size); else return ::operator new(size);}voidRangeLockItem::operator delete(void* r, Pool *pool){ if (pool) pool->release(r); else ::operator delete(r);}/////////////////////////////////////////////////////////////////////// Utility classesclass RangeLockValOp { public: virtual ~RangeLockValOp() {}; virtual void op(int&) = 0;};class RangeLockValSum: public RangeLockValOp { private: int delta; public: RangeLockValSum(int d): delta(d) {} void op(int &i) { i += delta; }};class RangeLockValSet: public RangeLockValOp { private: int val; public: RangeLockValSet(int v): val(v) {} void op(int &i) { i = val; }};/////////////////////////////////////////////////////////////////////// Members of RangeLockRangeLock::RangeLock(Pool *pool){ pool_ = pool; root_ = 0;}RangeLock::~RangeLock(){ for (RangeLockItem *i = root_; i;) { RangeLockItem *next = i->next; RangeLockItem::operator delete(i, pool_); i = next; }}intRangeLock::lockvalue(int loc){ for (RangeLockItem *i = root_; i; i = i->next) { if (loc >= i->start && loc < i->fence) { return i->value; } if (loc < i->fence) break; } return 0;}intRangeLock::checkeq(int start, int fence, int value){ split_ranges(start, fence); for (RangeLockItem *i = root_; i; i = i->next) { if (start >= i->start && start < i->fence || fence > i->start && fence <= i->fence || start < i->start && fence > i->fence) { if (value != i->value) return 0; } if (fence < i->fence) break; } return 1;}intRangeLock::checkgr(int start, int fence, int value){ split_ranges(start, fence); for (RangeLockItem *i = root_; i; i = i->next) { if (start >= i->start && start < i->fence || fence > i->start && fence <= i->fence || start < i->start && fence > i->fence) { if (i->value <= value) return 0; } if (fence < i->fence) break; } return 1;}voidRangeLock::check(){ for (RangeLockItem* i = root_; i; i = i->next) { int bad = 0; if (i->next && i->next->prev != i) { ExEnv::errn() << scprintf("i->next->prev bad\n"); bad = 1; } if (i->prev && i->prev->next != i) { ExEnv::errn() << scprintf("i->prev->next bad\n"); bad = 1; } if (i->start >= i->fence) { ExEnv::errn() << scprintf("start >= fence\n"); bad = 1; } if (i->next && i->fence > i->next->start) { ExEnv::errn() << scprintf("fence > next start\n"); bad = 1; }#if VERBOSE ExEnv::outn() << scprintf("i = 0x%08x, n = 0x%08x, p = 0x%08x, [%3d, %3d), %5d\n", i, i->next, i->prev, i->start, i->fence, i->value);#endif if (bad) abort(); }}voidRangeLock::split_ranges(int start, int fence){ if (root_ == 0) { // no blocks are allocted yet, initialize one and return root_ = new(pool_) RangeLockItem(0, 0, start, fence, 0); return; } RangeLockItem *i; for (i = root_; i; i=i->next) { if (start > i->start && start < i->fence) { // start is in the middle of this block, split it RangeLockItem *t = new(pool_) RangeLockItem(i, i->next, start, i->fence, i->value); i->fence = start; i->next = t; if (t->next) t->next->prev = t; i = t; break; } else if (start < i->start && fence <= i->start) { // start and end are before this block, insert it and return RangeLockItem *t = new(pool_) RangeLockItem(i->prev, i, start, fence, 0); i->prev = t; if (t->prev) t->prev->next = t; else root_ = t; return; } else if (start < i->start) { // start is before this block, fill in the gap RangeLockItem *t = new(pool_) RangeLockItem(i->prev, i, start, i->start, 0); i->prev = t; if (t->prev) t->prev->next = t; else root_ = t; break; } else if (start == i->start) { // start coincides with this block's start break; } else if (i->next == 0) { // start is after the last block, make the block and return RangeLockItem *t = new(pool_) RangeLockItem(i, 0, start, fence, 0); i->next = t; return; } // otherwise start is after this block, continue } for (; i; i=i->next) { if (fence > i->start && i->prev && i->prev->fence < i->start) { // fence is after this block and there is a gap before RangeLockItem *t = new(pool_) RangeLockItem(i->prev, i, i->prev->fence, i->start, 0); i->prev = t; if (t->prev) t->prev->next = t; else root_ = t; i = t; } else if (fence > i->start && fence < i->fence) { // fence is in the middle of this block, split it and return RangeLockItem *t = new(pool_) RangeLockItem(i->prev, i, i->start, fence, i->value); i->start = fence; i->prev = t; if (t->prev) t->prev->next = t; else root_ = t; return; } else if (fence > i->fence && !i->next) { // fence is after this block and no blocks follow RangeLockItem *t = new(pool_) RangeLockItem(i, 0, i->fence, fence, 0); i->next = t; return; } else if (fence <= i->start) { // fence is before this block, fill in the gap RangeLockItem *p = i->prev; RangeLockItem *t = new(pool_) RangeLockItem(p, i, p->fence, fence, 0); p->next = t; i->prev = t; return; } else if (fence == i->fence) { // fence coincides with this block's fence return; } // otherwise fence is after this block, continue } ExEnv::errn() << scprintf("RangeLock::split_ranges(): got to end\n"); abort();}voidRangeLock::do_valop(RangeLockValOp& op, int start, int fence){ if (start == fence) return; split_ranges(start, fence);#if CHECK check();#endif for (RangeLockItem *i = root_; i; i = i->next) { if (start == i->start || fence == i->fence || start < i->start && fence > i->fence) { op.op(i->value); } if (fence < i->fence) break; }}voidRangeLock::sum(int start, int fence, int delta){ RangeLockValSum sum(delta); do_valop(sum, start, fence);}voidRangeLock::increment(int start, int fence){ RangeLockValSum sum(1); do_valop(sum, start, fence);}voidRangeLock::decrement(int start, int fence){ RangeLockValSum sum(-1); do_valop(sum, start, fence);}voidRangeLock::set(int start, int fence, int value){ RangeLockValSet set(value); do_valop(set, start, fence);}voidRangeLock::print(ostream &o) const{ for (RangeLockItem *i = root_; i; i = i->next) { o << scprintf(" RangeLockItem: [%5d, %5d): %4d\n", i->start, i->fence, i->value); }}/////////////////////////////////////////////////////////////////////////////}// Local Variables:// mode: c++// c-file-style: "CLJ"// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -