vendredi 25 mars 2016

How this "container Design pattern" called?

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:

  1. 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.
  2. 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