mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-4534 Remove memory map address set cache lock contention
This commit is contained in:
parent
a36671d9d3
commit
4494e32596
4 changed files with 154 additions and 137 deletions
|
@ -135,14 +135,21 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildAddressSets() {
|
MemoryAddressSetView buildAddressSets() {
|
||||||
|
if (addrSetView != null) {
|
||||||
|
return addrSetView;
|
||||||
|
}
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
try {
|
try {
|
||||||
// null addrSet signals address sets must be built otherwise return
|
// have to try and get it again, another thread may have already filled it out
|
||||||
if (addrSetView != null) {
|
if (addrSetView != null) {
|
||||||
return;
|
return addrSetView;
|
||||||
}
|
}
|
||||||
addrSetView = new MemoryAddressSetView();
|
|
||||||
|
// set cached addressSet view to null, so other threads will end up here waiting
|
||||||
|
// on the above lock if they try to access the cached address sets
|
||||||
|
addrSetView = null;
|
||||||
|
MemoryAddressSetView newAddrSetView = new MemoryAddressSetView();
|
||||||
|
|
||||||
// The allAddrSet instance is generally maintained with all memory
|
// The allAddrSet instance is generally maintained with all memory
|
||||||
// block addresses and need only be updated if currently empty.
|
// block addresses and need only be updated if currently empty.
|
||||||
|
@ -155,15 +162,18 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
for (MemoryBlockDB block : blocks) {
|
for (MemoryBlockDB block : blocks) {
|
||||||
block.clearMappedBlockList();
|
block.clearMappedBlockList();
|
||||||
if (!block.isMapped()) {
|
if (!block.isMapped()) {
|
||||||
addBlockAddresses(block, addToAll);
|
addBlockAddresses(newAddrSetView, block, addToAll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// process all mapped blocks after non-mapped-blocks above
|
// process all mapped blocks after non-mapped-blocks above
|
||||||
for (MemoryBlockDB block : blocks) {
|
for (MemoryBlockDB block : blocks) {
|
||||||
if (block.isMapped()) {
|
if (block.isMapped()) {
|
||||||
addBlockAddresses(block, addToAll);
|
addBlockAddresses(newAddrSetView, block, addToAll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
addrSetView = newAddrSetView;
|
||||||
|
|
||||||
|
return addrSetView;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
lock.release();
|
lock.release();
|
||||||
|
@ -177,17 +187,17 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
* @param block memory block
|
* @param block memory block
|
||||||
* @param addToAll if true the allAddrSet should be updated with the specified block's address range
|
* @param addToAll if true the allAddrSet should be updated with the specified block's address range
|
||||||
*/
|
*/
|
||||||
private void addBlockAddresses(MemoryBlockDB block, boolean addToAll) {
|
private void addBlockAddresses(MemoryAddressSetView newSet, MemoryBlockDB block, boolean addToAll) {
|
||||||
Address start = block.getStart();
|
Address start = block.getStart();
|
||||||
Address end = block.getEnd();
|
Address end = block.getEnd();
|
||||||
if (addToAll) {
|
if (addToAll) {
|
||||||
allAddrSet.add(start, end);
|
allAddrSet.add(start, end);
|
||||||
}
|
}
|
||||||
if (block.isExternalBlock()) {
|
if (block.isExternalBlock()) {
|
||||||
addrSetView.externalBlock.add(start, end);
|
newSet.externalBlock.add(start, end);
|
||||||
}
|
}
|
||||||
else if (block.isExecute()) {
|
else if (block.isExecute()) {
|
||||||
addrSetView.execute.add(start, end);
|
newSet.execute.add(start, end);
|
||||||
}
|
}
|
||||||
if (block.isMapped()) {
|
if (block.isMapped()) {
|
||||||
// Identify source-blocks which block maps onto and add as a mapped-block to each of these
|
// Identify source-blocks which block maps onto and add as a mapped-block to each of these
|
||||||
|
@ -198,15 +208,15 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
b.addMappedBlock(block);
|
b.addMappedBlock(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddressSet mappedSet = getMappedIntersection(block, addrSetView.initialized);
|
AddressSet mappedSet = getMappedIntersection(block, newSet.initialized);
|
||||||
addrSetView.initialized.add(mappedSet);
|
newSet.initialized.add(mappedSet);
|
||||||
addrSetView.initializedAndLoaded
|
newSet.initializedAndLoaded
|
||||||
.add(getMappedIntersection(block, addrSetView.initializedAndLoaded));
|
.add(getMappedIntersection(block, newSet.initializedAndLoaded));
|
||||||
}
|
}
|
||||||
else if (block.isInitialized()) {
|
else if (block.isInitialized()) {
|
||||||
addrSetView.initialized.add(block.getStart(), block.getEnd());
|
newSet.initialized.add(block.getStart(), block.getEnd());
|
||||||
if (block.isLoaded()) {
|
if (block.isLoaded()) {
|
||||||
addrSetView.initializedAndLoaded.add(block.getStart(), block.getEnd());
|
newSet.initializedAndLoaded.add(block.getStart(), block.getEnd());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,16 +322,8 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AddressSetView getAllInitializedAddressSet() {
|
public AddressSetView getAllInitializedAddressSet() {
|
||||||
lock.acquire();
|
MemoryAddressSetView localAddrSetView = buildAddressSets();
|
||||||
try {
|
return new AddressSetViewAdapter(localAddrSetView.initialized);
|
||||||
if (addrSetView == null) {
|
|
||||||
buildAddressSets();
|
|
||||||
}
|
|
||||||
return new AddressSetViewAdapter(addrSetView.initialized);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
lock.release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -329,16 +331,21 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
if (liveMemory != null) {
|
if (liveMemory != null) {
|
||||||
return this; // all memory is initialized!
|
return this; // all memory is initialized!
|
||||||
}
|
}
|
||||||
lock.acquire();
|
|
||||||
try {
|
MemoryAddressSetView localAddrSetView = buildAddressSets();
|
||||||
if (addrSetView == null) {
|
return new AddressSetViewAdapter(localAddrSetView.initializedAndLoaded);
|
||||||
buildAddressSets();
|
}
|
||||||
}
|
|
||||||
return new AddressSetViewAdapter(addrSetView.initializedAndLoaded);
|
@Override
|
||||||
}
|
public boolean isExternalBlockAddress(Address addr) {
|
||||||
finally {
|
MemoryAddressSetView localAddrSetView = buildAddressSets();
|
||||||
lock.release();
|
return localAddrSetView.externalBlock.contains(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSetView getExecuteSet() {
|
||||||
|
MemoryAddressSetView localAddrSetView = buildAddressSets();
|
||||||
|
return new AddressSetViewAdapter(localAddrSetView.execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkMemoryWrite(MemoryBlockDB block, Address start, long length)
|
void checkMemoryWrite(MemoryBlockDB block, Address start, long length)
|
||||||
|
@ -920,13 +927,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSize() {
|
public long getSize() {
|
||||||
lock.acquire();
|
return allAddrSet.getNumAddresses();
|
||||||
try {
|
|
||||||
return allAddrSet.getNumAddresses();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
lock.release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1404,22 +1405,15 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte getByte(Address addr) throws MemoryAccessException {
|
public byte getByte(Address addr) throws MemoryAccessException {
|
||||||
lock.acquire();
|
if (liveMemory != null) {
|
||||||
try {
|
return liveMemory.getByte(addr);
|
||||||
if (liveMemory != null) {
|
|
||||||
return liveMemory.getByte(addr);
|
|
||||||
}
|
|
||||||
MemoryBlock block = getBlockDB(addr);
|
|
||||||
if (block == null) {
|
|
||||||
throw new MemoryAccessException(
|
|
||||||
"Address " + addr.toString(true) + " does not exist in memory");
|
|
||||||
}
|
|
||||||
return block.getByte(addr);
|
|
||||||
}
|
}
|
||||||
finally {
|
MemoryBlock block = getBlockDB(addr);
|
||||||
lock.release();
|
if (block == null) {
|
||||||
|
throw new MemoryAccessException(
|
||||||
|
"Address " + addr.toString(true) + " does not exist in memory");
|
||||||
}
|
}
|
||||||
|
return block.getByte(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1804,13 +1798,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(Address addr) {
|
public boolean contains(Address addr) {
|
||||||
lock.acquire();
|
return allAddrSet.contains(addr);
|
||||||
try {
|
|
||||||
return allAddrSet.contains(addr);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
lock.release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1828,20 +1816,6 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
return allAddrSet.isEmpty();
|
return allAddrSet.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isExternalBlockAddress(Address addr) {
|
|
||||||
lock.acquire();
|
|
||||||
try {
|
|
||||||
if (addrSetView == null) {
|
|
||||||
buildAddressSets();
|
|
||||||
}
|
|
||||||
return addrSetView.externalBlock.contains(addr);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
lock.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address getMinAddress() {
|
public Address getMinAddress() {
|
||||||
return allAddrSet.getMinAddress();
|
return allAddrSet.getMinAddress();
|
||||||
|
@ -2147,20 +2121,6 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
return super.hashCode();
|
return super.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AddressSetView getExecuteSet() {
|
|
||||||
lock.acquire();
|
|
||||||
try {
|
|
||||||
if (addrSetView == null) {
|
|
||||||
buildAddressSets();
|
|
||||||
}
|
|
||||||
return new AddressSetViewAdapter(addrSetView.execute);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
lock.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void memoryChanged(Address addr, int size) {
|
public void memoryChanged(Address addr, int size) {
|
||||||
fireBytesChanged(addr, size);
|
fireBytesChanged(addr, size);
|
||||||
|
|
|
@ -40,10 +40,12 @@ import ghidra.program.model.address.*;
|
||||||
*/
|
*/
|
||||||
class RecoverableAddressIterator implements AddressIterator {
|
class RecoverableAddressIterator implements AddressIterator {
|
||||||
|
|
||||||
private AddressSetView set;
|
private SynchronizedAddressSet synchSet;
|
||||||
|
private AddressSet internalSet;
|
||||||
private boolean forward;
|
private boolean forward;
|
||||||
private AddressIterator iterator;
|
private AddressIterator iterator;
|
||||||
private Address next;
|
private Address next;
|
||||||
|
private int changeID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct iterator
|
* Construct iterator
|
||||||
|
@ -51,8 +53,10 @@ class RecoverableAddressIterator implements AddressIterator {
|
||||||
* @param start address to start iterating at in the address set or null for all addresses
|
* @param start address to start iterating at in the address set or null for all addresses
|
||||||
* @param forward if true address are return from lowest to highest, else from highest to lowest
|
* @param forward if true address are return from lowest to highest, else from highest to lowest
|
||||||
*/
|
*/
|
||||||
RecoverableAddressIterator(AddressSetView set, Address start, boolean forward) {
|
RecoverableAddressIterator(SynchronizedAddressSet set, Address start, boolean forward) {
|
||||||
this.set = set;
|
this.synchSet = set;
|
||||||
|
this.internalSet = set.getInternalSet();
|
||||||
|
changeID = set.getModificationID();
|
||||||
this.forward = forward;
|
this.forward = forward;
|
||||||
initIterator(start);
|
initIterator(start);
|
||||||
this.next = iterator.next();
|
this.next = iterator.next();
|
||||||
|
@ -60,10 +64,10 @@ class RecoverableAddressIterator implements AddressIterator {
|
||||||
|
|
||||||
private void initIterator(Address start) {
|
private void initIterator(Address start) {
|
||||||
if (start == null) {
|
if (start == null) {
|
||||||
iterator = set.getAddresses(forward);
|
iterator = internalSet.getAddresses(forward);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
iterator = set.getAddresses(start, forward);
|
iterator = internalSet.getAddresses(start, forward);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,9 +81,14 @@ class RecoverableAddressIterator implements AddressIterator {
|
||||||
Address addr = next;
|
Address addr = next;
|
||||||
if (addr != null) {
|
if (addr != null) {
|
||||||
try {
|
try {
|
||||||
next = iterator.next();
|
if (synchSet.hasChanged(changeID)) {
|
||||||
|
next = recoverNext(addr);
|
||||||
|
} else {
|
||||||
|
next = iterator.next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ConcurrentModificationException e) {
|
catch (ConcurrentModificationException e) {
|
||||||
|
// will never happen, set in hand is never changed
|
||||||
next = recoverNext(addr);
|
next = recoverNext(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,6 +96,8 @@ class RecoverableAddressIterator implements AddressIterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address recoverNext(Address lastAddr) {
|
private Address recoverNext(Address lastAddr) {
|
||||||
|
changeID = synchSet.getModificationID();
|
||||||
|
internalSet = synchSet.getInternalSet();
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
initIterator(lastAddr);
|
initIterator(lastAddr);
|
||||||
|
@ -97,6 +108,7 @@ class RecoverableAddressIterator implements AddressIterator {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
catch (ConcurrentModificationException e) {
|
catch (ConcurrentModificationException e) {
|
||||||
|
// will never happen, set in hand is never changed
|
||||||
// set must have changed - try re-initializing again
|
// set must have changed - try re-initializing again
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,12 @@ import ghidra.program.model.address.*;
|
||||||
*/
|
*/
|
||||||
class RecoverableAddressRangeIterator implements AddressRangeIterator {
|
class RecoverableAddressRangeIterator implements AddressRangeIterator {
|
||||||
|
|
||||||
private AddressSetView set;
|
private SynchronizedAddressSet synchSet;
|
||||||
|
private AddressSet internalSet;
|
||||||
private boolean forward;
|
private boolean forward;
|
||||||
private AddressRangeIterator iterator;
|
private AddressRangeIterator iterator;
|
||||||
private AddressRange next;
|
private AddressRange next;
|
||||||
|
private int changeID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct iterator
|
* Construct iterator
|
||||||
|
@ -50,8 +52,10 @@ class RecoverableAddressRangeIterator implements AddressRangeIterator {
|
||||||
* @param start the address the the first range should contain.
|
* @param start the address the the first range should contain.
|
||||||
* @param forward true iterators forward, false backwards
|
* @param forward true iterators forward, false backwards
|
||||||
*/
|
*/
|
||||||
RecoverableAddressRangeIterator(AddressSetView set, Address start, boolean forward) {
|
RecoverableAddressRangeIterator(SynchronizedAddressSet set, Address start, boolean forward) {
|
||||||
this.set = set;
|
this.synchSet = set;
|
||||||
|
this.internalSet = set.getInternalSet();
|
||||||
|
changeID = set.getModificationID();
|
||||||
this.forward = forward;
|
this.forward = forward;
|
||||||
initIterator(start);
|
initIterator(start);
|
||||||
try {
|
try {
|
||||||
|
@ -64,10 +68,10 @@ class RecoverableAddressRangeIterator implements AddressRangeIterator {
|
||||||
|
|
||||||
private void initIterator(Address start) {
|
private void initIterator(Address start) {
|
||||||
if (start == null) {
|
if (start == null) {
|
||||||
iterator = set.getAddressRanges(forward);
|
iterator = internalSet.getAddressRanges(forward);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
iterator = set.getAddressRanges(start, forward);
|
iterator = internalSet.getAddressRanges(start, forward);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,9 +87,14 @@ class RecoverableAddressRangeIterator implements AddressRangeIterator {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
next = iterator.next();
|
if (synchSet.hasChanged(changeID)) {
|
||||||
|
next = recoverNext(range);
|
||||||
|
} else {
|
||||||
|
next = iterator.next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ConcurrentModificationException e) {
|
catch (ConcurrentModificationException e) {
|
||||||
|
// will never happen, set in hand is never changed
|
||||||
next = recoverNext(range);
|
next = recoverNext(range);
|
||||||
}
|
}
|
||||||
catch (NoSuchElementException e) {
|
catch (NoSuchElementException e) {
|
||||||
|
@ -95,6 +104,8 @@ class RecoverableAddressRangeIterator implements AddressRangeIterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private AddressRange recoverNext(AddressRange lastRange) {
|
private AddressRange recoverNext(AddressRange lastRange) {
|
||||||
|
changeID = synchSet.getModificationID();
|
||||||
|
internalSet = synchSet.getInternalSet();
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
Address lastAddr = forward ? lastRange.getMaxAddress() : lastRange.getMinAddress();
|
Address lastAddr = forward ? lastRange.getMaxAddress() : lastRange.getMinAddress();
|
||||||
|
@ -114,6 +125,7 @@ class RecoverableAddressRangeIterator implements AddressRangeIterator {
|
||||||
return iterator.next(); // skip range and return next
|
return iterator.next(); // skip range and return next
|
||||||
}
|
}
|
||||||
catch (ConcurrentModificationException e) {
|
catch (ConcurrentModificationException e) {
|
||||||
|
// will never happen, set in hand is never changed
|
||||||
// set must have changed - try re-initializing again
|
// set must have changed - try re-initializing again
|
||||||
}
|
}
|
||||||
catch (NoSuchElementException e) {
|
catch (NoSuchElementException e) {
|
||||||
|
|
|
@ -28,18 +28,31 @@ import ghidra.program.model.address.*;
|
||||||
class SynchronizedAddressSet implements AddressSetView {
|
class SynchronizedAddressSet implements AddressSetView {
|
||||||
|
|
||||||
private AddressSet set;
|
private AddressSet set;
|
||||||
|
private int modificationID = 1; // updated if set above ever replaced
|
||||||
|
|
||||||
SynchronizedAddressSet() {
|
SynchronizedAddressSet() {
|
||||||
set = new AddressSet();
|
set = new AddressSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the modification number of the internal address set
|
||||||
|
* If the underlying set if ever replaced, modification id is changed
|
||||||
|
* @return current modification id
|
||||||
|
*/
|
||||||
|
int getModificationID() {
|
||||||
|
return modificationID;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add all addresses of the given AddressSet to this set.
|
* Add all addresses of the given AddressSet to this set.
|
||||||
* @param addrSet set of addresses to add.
|
* @param addrSet set of addresses to add.
|
||||||
* @see AddressSet#add(AddressSetView)
|
* @see AddressSet#add(AddressSetView)
|
||||||
*/
|
*/
|
||||||
synchronized void add(AddressSet addrSet) {
|
synchronized void add(AddressSet addrSet) {
|
||||||
set.add(addrSet);
|
AddressSet newSet = new AddressSet(set);
|
||||||
|
newSet.add(addrSet);
|
||||||
|
set = newSet;
|
||||||
|
modificationID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,7 +62,10 @@ class SynchronizedAddressSet implements AddressSetView {
|
||||||
* @see AddressSet#add(Address, Address)
|
* @see AddressSet#add(Address, Address)
|
||||||
*/
|
*/
|
||||||
synchronized void add(Address start, Address end) {
|
synchronized void add(Address start, Address end) {
|
||||||
set.add(start, end);
|
AddressSet newSet = new AddressSet(set);
|
||||||
|
newSet.add(start, end);
|
||||||
|
set = newSet;
|
||||||
|
modificationID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,57 +75,75 @@ class SynchronizedAddressSet implements AddressSetView {
|
||||||
* @see AddressSet#delete(Address, Address)
|
* @see AddressSet#delete(Address, Address)
|
||||||
*/
|
*/
|
||||||
synchronized void delete(Address start, Address end) {
|
synchronized void delete(Address start, Address end) {
|
||||||
set.delete(start, end);
|
AddressSet newSet = new AddressSet(set);
|
||||||
|
newSet.delete(start, end);
|
||||||
|
set = newSet;
|
||||||
|
modificationID++;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized AddressSet getInternalSet() {
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the internal set has been modified
|
||||||
|
* If the mod id is different, then the set has changed.
|
||||||
|
*
|
||||||
|
* @param modID modification id to check
|
||||||
|
* @return true if internal mod id is different
|
||||||
|
*/
|
||||||
|
public boolean hasChanged(int modID) {
|
||||||
|
return modID != modificationID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean contains(Address addr) {
|
public boolean contains(Address addr) {
|
||||||
return set.contains(addr);
|
return set.contains(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean contains(Address start, Address end) {
|
public boolean contains(Address start, Address end) {
|
||||||
return set.contains(start, end);
|
return set.contains(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean contains(AddressSetView addrSet) {
|
public boolean contains(AddressSetView addrSet) {
|
||||||
return set.contains(addrSet);
|
return set.contains(addrSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return set.isEmpty();
|
return set.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Address getMinAddress() {
|
public Address getMinAddress() {
|
||||||
return set.getMinAddress();
|
return set.getMinAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Address getMaxAddress() {
|
public Address getMaxAddress() {
|
||||||
return set.getMaxAddress();
|
return set.getMaxAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int getNumAddressRanges() {
|
public int getNumAddressRanges() {
|
||||||
return set.getNumAddressRanges();
|
return set.getNumAddressRanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressRangeIterator getAddressRanges() {
|
public AddressRangeIterator getAddressRanges() {
|
||||||
return set.getAddressRanges();
|
return set.getAddressRanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressRangeIterator getAddressRanges(boolean forward) {
|
public AddressRangeIterator getAddressRanges(boolean forward) {
|
||||||
return set.getAddressRanges(forward);
|
return set.getAddressRanges(forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressRangeIterator getAddressRanges(Address start, boolean forward) {
|
public synchronized AddressRangeIterator getAddressRanges(Address start, boolean forward) {
|
||||||
return new RecoverableAddressRangeIterator(set, start, forward);
|
return new RecoverableAddressRangeIterator(this, start, forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -118,103 +152,102 @@ class SynchronizedAddressSet implements AddressSetView {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Iterator<AddressRange> iterator(boolean forward) {
|
public Iterator<AddressRange> iterator(boolean forward) {
|
||||||
return set.getAddressRanges(forward);
|
return set.getAddressRanges(forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Iterator<AddressRange> iterator(Address start, boolean forward) {
|
public Iterator<AddressRange> iterator(Address start, boolean forward) {
|
||||||
return set.getAddressRanges(start, forward);
|
return set.getAddressRanges(start, forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized long getNumAddresses() {
|
public long getNumAddresses() {
|
||||||
return set.getNumAddresses();
|
return set.getNumAddresses();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressIterator getAddresses(boolean forward) {
|
public synchronized AddressIterator getAddresses(boolean forward) {
|
||||||
return new RecoverableAddressIterator(set, null, forward);
|
return new RecoverableAddressIterator(this, null, forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressIterator getAddresses(Address start, boolean forward) {
|
public synchronized AddressIterator getAddresses(Address start, boolean forward) {
|
||||||
return new RecoverableAddressIterator(set, start, forward);
|
return new RecoverableAddressIterator(this, start, forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean intersects(AddressSetView addrSet) {
|
public boolean intersects(AddressSetView addrSet) {
|
||||||
return set.intersects(addrSet);
|
return set.intersects(addrSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean intersects(Address start, Address end) {
|
public boolean intersects(Address start, Address end) {
|
||||||
return set.intersects(start, end);
|
return set.intersects(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressSet intersect(AddressSetView addrSet) {
|
public AddressSet intersect(AddressSetView addrSet) {
|
||||||
return set.intersect(addrSet);
|
return set.intersect(addrSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressSet intersectRange(Address start, Address end) {
|
public AddressSet intersectRange(Address start, Address end) {
|
||||||
return set.intersectRange(start, end);
|
return set.intersectRange(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressSet union(AddressSetView addrSet) {
|
public AddressSet union(AddressSetView addrSet) {
|
||||||
return set.union(addrSet);
|
return set.union(addrSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressSet subtract(AddressSetView addrSet) {
|
public AddressSet subtract(AddressSetView addrSet) {
|
||||||
return set.subtract(addrSet);
|
return set.subtract(addrSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressSet xor(AddressSetView addrSet) {
|
public AddressSet xor(AddressSetView addrSet) {
|
||||||
return set.xor(addrSet);
|
return set.xor(addrSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean hasSameAddresses(AddressSetView addrSet) {
|
public boolean hasSameAddresses(AddressSetView addrSet) {
|
||||||
return set.hasSameAddresses(addrSet);
|
return set.hasSameAddresses(addrSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressRange getFirstRange() {
|
public AddressRange getFirstRange() {
|
||||||
return set.getFirstRange();
|
return set.getFirstRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressRange getLastRange() {
|
public AddressRange getLastRange() {
|
||||||
return set.getLastRange();
|
return set.getLastRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized AddressRange getRangeContaining(Address address) {
|
public AddressRange getRangeContaining(Address address) {
|
||||||
return set.getRangeContaining(address);
|
return set.getRangeContaining(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Address findFirstAddressInCommon(AddressSetView addrSet) {
|
public Address findFirstAddressInCommon(AddressSetView addrSet) {
|
||||||
return set.findFirstAddressInCommon(addrSet);
|
return set.findFirstAddressInCommon(addrSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int hashCode() {
|
public int hashCode() {
|
||||||
return set.hashCode();
|
return set.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
return set.equals(obj);
|
return set.equals(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized String toString() {
|
public String toString() {
|
||||||
return set.toString();
|
return set.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue