How to protect dynamic lookup content when it is changing?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

How to protect dynamic lookup content when it is changing?

rsobies
i would like to block accesing lookup content when another thread is puting into lookup.
here is an example


Code:

public class MyNode extends AbstractNode {

    private InstanceContent instanceContent = new InstanceContent();

    public MyNode(SomeKey key) {
        this(key, new InstanceContent());
    }

    private CarNode(SomeKey key, InstanceContent ic) {
        super(Children.LEAF, new AbstractLookup(ic));

        this.instanceContent = ic;
        instanceContent.add(key);
    }
   
    public void setNewKey(SomeKey key) {
        Collection<? extends SomeKey> lookupAll = getLookup().lookupAll(SomeKey.class);
        for (Object item : lookupAll) {
            remove(item);
        }

 //at this time lookup is empty, if another thread tries to get content, it gets null
       
        instanceContent.add(key);
    }
}
}




is there an elegant way to block getLookup().lookup(SomeKey.class) during execution of setNewKey()?




Reply | Threaded
Open this post in threaded view
|

Re: How to protect dynamic lookup content when it is changing?

Steven Yi
Not knowing the complete context, I'm wondering if you could change
the architecture such that rather than have another thread that might
poll the lookup data, you could modify the code to use a
LookupListener and react when modifications have occurred.

On Tue, Oct 11, 2016 at 7:33 AM, rsobies <[hidden email]> wrote:

> i would like to block accesing lookup content when another thread is puting into lookup.
> here is an example
>
>
> Code:
>
> public class MyNode extends AbstractNode {
>
>     private InstanceContent instanceContent = new InstanceContent();
>
>     public MyNode(SomeKey key) {
>         this(key, new InstanceContent());
>     }
>
>     private CarNode(SomeKey key, InstanceContent ic) {
>         super(Children.LEAF, new AbstractLookup(ic));
>
>         this.instanceContent = ic;
>         instanceContent.add(key);
>     }
>
>     public void setNewKey(SomeKey key) {
>         Collection<? extends SomeKey> lookupAll = getLookup().lookupAll(SomeKey.class);
>         for (Object item : lookupAll) {
>             remove(item);
>         }
>
>  //at this time lookup is empty, if another thread tries to get content, it gets null
>
>         instanceContent.add(key);
>     }
> }
> }
>
>
>
>
> is there an elegant way to block getLookup().lookup(SomeKey.class) during execution of setNewKey()?
>
>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: How to protect dynamic lookup content when it is changing?

Dmitry Avtonomov

I guess you could synchronize all access methods on a common lock, but don't use the lookup itself for sync, as the actual underlying object might change.

Or use a ReadWriteLock as usual.

But Steven's suggestion is probably the right way to go. Don't forget to use weak listeners or unsubscribe listeners manually.


On Oct 11, 2016 09:27, "Steven Yi" <[hidden email]> wrote:
Not knowing the complete context, I'm wondering if you could change
the architecture such that rather than have another thread that might
poll the lookup data, you could modify the code to use a
LookupListener and react when modifications have occurred.

On Tue, Oct 11, 2016 at 7:33 AM, rsobies <[hidden email]> wrote:
> i would like to block accesing lookup content when another thread is puting into lookup.
> here is an example
>
>
> Code:
>
> public class MyNode extends AbstractNode {
>
>     private InstanceContent instanceContent = new InstanceContent();
>
>     public MyNode(SomeKey key) {
>         this(key, new InstanceContent());
>     }
>
>     private CarNode(SomeKey key, InstanceContent ic) {
>         super(Children.LEAF, new AbstractLookup(ic));
>
>         this.instanceContent = ic;
>         instanceContent.add(key);
>     }
>
>     public void setNewKey(SomeKey key) {
>         Collection<? extends SomeKey> lookupAll = getLookup().lookupAll(SomeKey.class);
>         for (Object item : lookupAll) {
>             remove(item);
>         }
>
>  //at this time lookup is empty, if another thread tries to get content, it gets null
>
>         instanceContent.add(key);
>     }
> }
> }
>
>
>
>
> is there an elegant way to block getLookup().lookup(SomeKey.class) during execution of setNewKey()?
>
>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: How to protect dynamic lookup content when it is changing?

Boris Heithecker-2
In reply to this post by rsobies

Keep a reference to the InstanceContent and synchronize on it. It should work as a common lock.


Am 11.10.2016 13:33 schrieb "rsobies" <[hidden email]>:
i would like to block accesing lookup content when another thread is puting into lookup.
here is an example


Code:

public class MyNode extends AbstractNode {

    private InstanceContent instanceContent = new InstanceContent();

    public MyNode(SomeKey key) {
        this(key, new InstanceContent());
    }

    private CarNode(SomeKey key, InstanceContent ic) {
        super(Children.LEAF, new AbstractLookup(ic));

        this.instanceContent = ic;
        instanceContent.add(key);
    }

    public void setNewKey(SomeKey key) {
        Collection<? extends SomeKey> lookupAll = getLookup().lookupAll(SomeKey.class);
        for (Object item : lookupAll) {
            remove(item);
        }

 //at this time lookup is empty, if another thread tries to get content, it gets null

        instanceContent.add(key);
    }
}
}




is there an elegant way to block getLookup().lookup(SomeKey.class) during execution of setNewKey()?




Reply | Threaded
Open this post in threaded view
|

Re: How to protect dynamic lookup content when it is changing?

Boris Heithecker
In reply to this post by rsobies

Keep a reference to the InstanceContent and synchronize on it. It should work as a common lock.

Boris


Am 11.10.2016 13:33 schrieb "rsobies" <[hidden email]>:
i would like to block accesing lookup content when another thread is puting into lookup.
here is an example


Code:

public class MyNode extends AbstractNode {

    private InstanceContent instanceContent = new InstanceContent();

    public MyNode(SomeKey key) {
        this(key, new InstanceContent());
    }

    private CarNode(SomeKey key, InstanceContent ic) {
        super(Children.LEAF, new AbstractLookup(ic));

        this.instanceContent = ic;
        instanceContent.add(key);
    }

    public void setNewKey(SomeKey key) {
        Collection<? extends SomeKey> lookupAll = getLookup().lookupAll(SomeKey.class);
        for (Object item : lookupAll) {
            remove(item);
        }

 //at this time lookup is empty, if another thread tries to get content, it gets null

        instanceContent.add(key);
    }
}
}




is there an elegant way to block getLookup().lookup(SomeKey.class) during execution of setNewKey()?




Reply | Threaded
Open this post in threaded view
|

How to protect dynamic lookup content when it is changing?

rsobies
In reply to this post by rsobies

Boris Heithecker wrote:
> Keep a reference to the InstanceContent and synchronize on it. It should work as a common lock.
>


synchronization should be done inside setNewKey() and in getLookup()
i cannot override getLookup, it is final




Reply | Threaded
Open this post in threaded view
|

How to protect dynamic lookup content when it is changing?

rsobies
In reply to this post by rsobies
or if getLookup.lookup(SomeKey.class) is invoked, instancontent is locked?
then i only  have to make synchronization in setNewKey
am i right?




Reply | Threaded
Open this post in threaded view
|

Re: How to protect dynamic lookup content when it is changing?

Tim Boudreau-3
In reply to this post by Boris Heithecker-2
Lookup is designed to be thread-safe.  So this should be a non-issue - calling code will either see the object or not.

If you think this is the source of your problem, it is probably something else.  So... what problem are you trying to solve?  What is the sequence of events, and what about it suggests that synchronizing lookup access would help?

If the problem is that some code expects an object to be in a Lookup, and it isn't necessarily there, the usual answer is to key enablement of whatever action results in that code off of the presence or absence of that object.

If the problem is that loading / constructing the object can take a long time, Lookup may not be the right tool for the job (since it can be called from any thread and should not trigger long-running work), and you may want some asynchronous call that completes once loading is complete.  That is not the same problem as synchronizing access, and you probably don't want to block the UI while it happens.

-Tim

On Tue, Oct 11, 2016 at 11:19 AM, Boris Heithecker <[hidden email]> wrote:

Keep a reference to the InstanceContent and synchronize on it. It should work as a common lock.


Am 11.10.2016 13:33 schrieb "rsobies" <[hidden email]>:
i would like to block accesing lookup content when another thread is puting into lookup.
here is an example


Code:

public class MyNode extends AbstractNode {

    private InstanceContent instanceContent = new InstanceContent();

    public MyNode(SomeKey key) {
        this(key, new InstanceContent());
    }

    private CarNode(SomeKey key, InstanceContent ic) {
        super(Children.LEAF, new AbstractLookup(ic));

        this.instanceContent = ic;
        instanceContent.add(key);
    }

    public void setNewKey(SomeKey key) {
        Collection<? extends SomeKey> lookupAll = getLookup().lookupAll(SomeKey.class);
        for (Object item : lookupAll) {
            remove(item);
        }

 //at this time lookup is empty, if another thread tries to get content, it gets null

        instanceContent.add(key);
    }
}
}




is there an elegant way to block getLookup().lookup(SomeKey.class) during execution of setNewKey()?







--
Reply | Threaded
Open this post in threaded view
|

Re: How to protect dynamic lookup content when it is changing?

Boris Heithecker
In reply to this post by rsobies
I think I didn't understand all of your problem. 
Is it 

A: that instanceContent.remove(item) triggers a LookupEvent while the lookup is empty -> in this case the listener could simply ignore the event because a second one will be dispatched subsequently while processing instanceContent.add(key) 

B: no listeners, you just want the lookup to never be empty -> you could reverse the order of invocation (instanceContent.add(newKey) before instanceContent.remove(oldKey))

C: ? 

In principal, you can keep a reference also to the AbstractLookup which is created in your constructor (you need a third constructor), but I think that synchronizing on either instanceContent or the abstractLookup is no good design, because it is deadlock prone. 

Another option is passing an instanceof RequestProcessor to the instanceContent (call "new InstanceContent(new RequestProcessor(...))") to dispatch lookup events in a different thread. 

A third option could be: instead of putting SomeKey itself in the lookup, use a wrapper class and put a singleton instance of it - which is never to be removed - in your lookup. E.g.: 

public class CarReference extends AtomicReference<Car> {

    private final ChangeSupport cSupport = new ChangeSupport(this);

    void setAndNotify(Car newCar) {
        Car before = super.getAndSet(newCar);
        if (!Objects.equals(before, newCar)) {
            cSupport.fireChange();
        }
    }

    public void addChangeListener(ChangeListener listener) {
        cSupport.addChangeListener(listener);
    }

    public void removeChangeListener(ChangeListener listener) {
        cSupport.removeChangeListener(listener);
    }
    
    
}

Boris

2016-10-12 15:34 GMT+02:00 rsobies <[hidden email]>:
or if getLookup.lookup(SomeKey.class) is invoked, instancontent is locked?
then i only  have to make synchronization in setNewKey
am i right?







--
Boris Heithecker


Dr. Boris Heithecker
Lüneburger Str. 30
28870 Ottersberg
Tel.: 0 42 05/ 31 58 34
Reply | Threaded
Open this post in threaded view
|

How to protect dynamic lookup content when it is changing?

rsobies
In reply to this post by rsobies

Boris Heithecker wrote:
>
> B: no listeners, you just want the lookup to never be empty -> you could reverse the order of invocation (instanceContent.add(newKey) before instanceContent.remove(oldKey))
>


yes. that should do the work. so simple. thanks :)


you said that getLookup is thread safe so i wonder if i lock instancontent in setNewKey() like this:



Code:

public void setNewKey(SomeKey key) {

        Collection<? extends SomeKey> lookupAll = getLookup().lookupAll(SomeKey.class);

        synchronized(instanceContent)
            for (SomeKey item : lookupAll) {
                 instanceContent.remove(item);
            }

//if getLookup.lookup(SomeKey.class) is invoked by another thread at this point, will it be blocked untill end of this synchronized block?
         }
 

        instanceContent.add(key);
    }