While creating my app. architecture I faced the need of one structure, that will be described below. I'm pretty sure, that there is a well known design pattern with the same functionality, because I think that problem, for which I develop it is really common. I write my own implementation of this, but I always try to use "build in language" implementations of patterns, so - please help me to "named" this construction.
The idea is close to reader-writer pattern. We have a "container" in which we can add Objects by the key (). And also we can get this objects by keys, removing it from container. So, the implemented class should have two methods:
void putObject(Key key, Object object);
Object getObject(Key key); // remove <Key,Object> from container.
The next is most interesting. This container should work in multi-threading environment as follows:
- if there is no object associated with key, while calling get(Key key) method the caller thread should WAIT for the object in this contaier.
- When another thread will call putObject(Key key, Object object) method it should check if there is some thread that wait exactly for this object, and if it is - then signal and wake up the thread that waits.
I think that it is common structure, does it have "official" name? Thank you.
PS my Java implementation of this pattern:
private static interface BlackBox {
public void addObject(IdObject object);
public IdObject getObject(ObjectId id);
}
private static class BlackBoxImpl implements BlackBox {
private final Lock conditionLock = new ReentrantLock();
private final SavedObjects savedObjects;
private final WaitingConditions waitingConditions;
public BlackBoxImpl() {
this.savedObjects = new SavedObjects();
this.waitingConditions = new WaitingConditions();
}
@Override
public void addObject(IdObject object) {
savedObjects.putObject(object);
if (waitingConditions.contains(object.getId())) {
Condition waitCondition = waitingConditions.getCondition(object.getId());
conditionLock.lock();
waitCondition.signal();
conditionLock.unlock();
}
}
@Override
public IdObject getObject(ObjectId id) {
if (savedObjects.containsId(id)) {
return savedObjects.get(id);
} else {
conditionLock.lock();
Condition waitCondition = conditionLock.newCondition();
waitingConditions.putCondition(id, waitCondition);
waitCondition.awaitUninterruptibly();
conditionLock.unlock();
return savedObjects.get(id);
}
}
}
private static class SavedObjects {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Map<ObjectId, IdObject> savedObjects;
public SavedObjects() {
this.savedObjects = new HashMap<ObjectId, IdObject>(20);
}
public boolean containsId(ObjectId id) {
lock.readLock().lock();
try {
return savedObjects.containsKey(id);
} finally {
lock.readLock().unlock();
}
}
public void putObject(IdObject object) {
lock.writeLock().lock();
try {
savedObjects.put(object.getId(), object);
} finally {
lock.writeLock().unlock();
}
}
public IdObject get(ObjectId id) {
lock.writeLock().lock();
try {
return savedObjects.remove(id);
} finally {
lock.writeLock().unlock();
}
}
}
private static class WaitingConditions {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Map<ObjectId, Condition> waitingForSuchObjects;
public WaitingConditions() {
this.waitingForSuchObjects = new HashMap<ObjectId, Condition>(20);
}
public void putCondition(ObjectId id, Condition condition) {
lock.writeLock().lock();
try {
waitingForSuchObjects.put(id, condition);
} finally {
lock.writeLock().unlock();
}
}
public Condition getCondition(ObjectId id) {
lock.writeLock().lock();
try {
return waitingForSuchObjects.remove(id);
} finally {
lock.writeLock().unlock();
}
}
public boolean contains(ObjectId id) {
lock.readLock().lock();
try {
return waitingForSuchObjects.containsKey(id);
} finally {
lock.readLock().unlock();
}
}
}
private static interface IdObject {
public ObjectId getId();
}
private static class IdObjectImpl implements IdObject {
protected final ObjectId id;
public IdObjectImpl(ObjectId id) {
this.id = id;
}
@Override
public ObjectId getId() {
return id;
}
}
private static interface ObjectId {
}
private static class ObjectIdImpl implements ObjectId {
}
Aucun commentaire:
Enregistrer un commentaire