threading proposal + remove ctor

This commit is contained in:
Mike Rosseel 2017-04-19 11:04:08 +02:00
parent 9ade57842b
commit c6bb61337f
3 changed files with 77 additions and 42 deletions

View file

@ -0,0 +1,58 @@
package io.bisq.common.util;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;
public class FunctionalReadWriteLock {
private final Lock readLock;
private final Lock writeLock;
public FunctionalReadWriteLock(boolean isFair) {
this(new ReentrantReadWriteLock(isFair));
}
public FunctionalReadWriteLock(ReadWriteLock lock) {
readLock = lock.readLock();
writeLock = lock.writeLock();
}
public <T> T read(Supplier<T> block) {
readLock.lock();
try {
return block.get();
} finally {
readLock.unlock();
}
}
public void read(Runnable block) {
readLock.lock();
try {
block.run();
} finally {
readLock.unlock();
}
}
public <T> T write(Supplier<T> block) {
writeLock.lock();
try {
return block.get();
} finally {
writeLock.unlock();
}
}
public void write(Runnable block) {
writeLock.lock();
try {
block.run();
} finally {
writeLock.unlock();
}
}
}

View file

@ -22,6 +22,7 @@ import io.bisq.common.app.Version;
import io.bisq.common.persistence.Persistable; import io.bisq.common.persistence.Persistable;
import io.bisq.common.proto.PersistenceProtoResolver; import io.bisq.common.proto.PersistenceProtoResolver;
import io.bisq.common.storage.Storage; import io.bisq.common.storage.Storage;
import io.bisq.common.util.FunctionalReadWriteLock;
import io.bisq.common.util.Tuple2; import io.bisq.common.util.Tuple2;
import io.bisq.common.util.Utilities; import io.bisq.common.util.Utilities;
import io.bisq.core.app.BisqEnvironment; import io.bisq.core.app.BisqEnvironment;
@ -67,7 +68,7 @@ public class BsqChainState implements Persistable {
//mainnet //mainnet
// this tx has a lot of outputs // this tx has a lot of outputs
// https://blockchain.info/de/tx/ee921650ab3f978881b8fe291e0c025e0da2b7dc684003d7a03d9649dfee2e15 // https://blockchain.info/de/tx/ee921650ab3f978881b8fe291e0c025e0da2b7dc684003d7a03d9649dfee2e15
// BLOCK_HEIGHT 411779 // BLOCK_HEIGHT 411779
// 411812 has 693 recursions // 411812 has 693 recursions
// MAIN NET // MAIN NET
private static final String GENESIS_TX_ID = "b26371e2145f52c94b3d30713a9e38305bfc665fc27cd554e794b5e369d99ef5"; private static final String GENESIS_TX_ID = "b26371e2145f52c94b3d30713a9e38305bfc665fc27cd554e794b5e369d99ef5";
@ -107,10 +108,11 @@ public class BsqChainState implements Persistable {
private int chainHeadHeight = 0; private int chainHeadHeight = 0;
private Tx genesisTx; private Tx genesisTx;
// transient // transient
transient private final boolean dumpBlockchainData; transient private final boolean dumpBlockchainData;
transient private final Storage<BsqChainState> snapshotBsqChainStateStorage; transient private final Storage<BsqChainState> snapshotBsqChainStateStorage;
transient private BsqChainState snapshotCandidate; transient private BsqChainState snapshotCandidate;
transient private final FunctionalReadWriteLock lock;
transient private final ReentrantReadWriteLock.WriteLock writeLock; transient private final ReentrantReadWriteLock.WriteLock writeLock;
transient private final ReentrantReadWriteLock.ReadLock readLock; transient private final ReentrantReadWriteLock.ReadLock readLock;
@ -140,9 +142,11 @@ public class BsqChainState implements Persistable {
genesisBlockHeight = TEST_NET_GENESIS_BLOCK_HEIGHT; genesisBlockHeight = TEST_NET_GENESIS_BLOCK_HEIGHT;
} }
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); // TODO choose between two styles + consider using fair so that threads don't have to wait too long?
readLock = lock.readLock(); lock = new FunctionalReadWriteLock(true);
writeLock = lock.writeLock(); ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock(true);
readLock = lock2.readLock();
writeLock = lock2.writeLock();
} }
@ -151,9 +155,7 @@ public class BsqChainState implements Persistable {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public void applySnapshot() { public void applySnapshot() {
try { lock.write(() -> {
writeLock.lock();
BsqChainState snapshot = snapshotBsqChainStateStorage.initAndGetPersistedWithFileName("BsqChainState"); BsqChainState snapshot = snapshotBsqChainStateStorage.initAndGetPersistedWithFileName("BsqChainState");
blocks.clear(); blocks.clear();
@ -176,18 +178,13 @@ public class BsqChainState implements Persistable {
} }
printDetails(); printDetails();
} finally { });
writeLock.unlock();
}
} }
public void setCreateCompensationRequestFee(long fee, int blockHeight) { public void setCreateCompensationRequestFee(long fee, int blockHeight) {
try { lock.write(() -> {
writeLock.lock();
compensationRequestFees.add(new Tuple2<>(fee, blockHeight)); compensationRequestFees.add(new Tuple2<>(fee, blockHeight));
} finally { });
writeLock.unlock();
}
} }
public void setVotingFee(long fee, int blockHeight) { public void setVotingFee(long fee, int blockHeight) {
@ -240,7 +237,7 @@ public class BsqChainState implements Persistable {
} }
void addSpentTxWithSpentInfo(TxOutput spentTxOutput, SpentInfo spentInfo) { void addSpentTxWithSpentInfo(TxOutput spentTxOutput, SpentInfo spentInfo) {
// we only use spentInfoByTxOutputMap for json export // we only use spentInfoByTxOutputMap for json export
if (dumpBlockchainData) { if (dumpBlockchainData) {
try { try {
writeLock.lock(); writeLock.lock();
@ -333,6 +330,7 @@ public class BsqChainState implements Persistable {
// Public read access // Public read access
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// TODO doesn't need a lock, it's a final String variable so should be thread safe
public String getGenesisTxId() { public String getGenesisTxId() {
try { try {
readLock.lock(); readLock.lock();
@ -532,12 +530,10 @@ public class BsqChainState implements Persistable {
} }
private Optional<Tx> getTx(String txId) { private Optional<Tx> getTx(String txId) {
try { return lock.read(() -> {
readLock.lock(); readLock.lock();
return txMap.get(txId) != null ? Optional.of(txMap.get(txId)) : Optional.<Tx>empty(); return txMap.get(txId) != null ? Optional.of(txMap.get(txId)) : Optional.<Tx>empty();
} finally { });
readLock.unlock();
}
} }
private int getSnapshotHeight(int height) { private int getSnapshotHeight(int height) {

View file

@ -47,29 +47,10 @@ public class TxOutput implements Persistable {
private final int blockHeight; private final int blockHeight;
private final long time; private final long time;
public TxOutput(int index,
long value,
String txId,
PubKeyScript pubKeyScript,
@Nullable String address,
@Nullable byte[] opReturnData,
int blockHeight,
long time) {
this.index = index;
this.value = value;
this.txId = txId;
this.pubKeyScript = pubKeyScript;
this.address = address;
this.opReturnData = opReturnData;
this.blockHeight = blockHeight;
this.time = time;
}
/* public String getAddress() { /* public String getAddress() {
String address = ""; String address = "";
// Only at raw MS outputs addresses have more then 1 entry // Only at raw MS outputs addresses have more then 1 entry
// We do not support raw MS for BSQ but lets see if is needed anyway, might be removed // We do not support raw MS for BSQ but lets see if is needed anyway, might be removed
final List<String> addresses = pubKeyScript.getAddresses(); final List<String> addresses = pubKeyScript.getAddresses();
if (addresses.size() == 1) { if (addresses.size() == 1) {
address = addresses.get(0); address = addresses.get(0);