[concurrency-interest] RE: Concurrency-interest digest, Vol 1 #299 - 1 msg

Unmesh joshi unmesh_joshi@hotmail.com
Tue, 05 Oct 2004 12:14:20 +0000


The ForwardingQueue looks similar to this pattern that I found,
http://www.cs.luc.edu/laufer/teaching/473/handouts/AbstractSubclasses.html/view 
which simulates Mixin functionality with composition.

The stuff being discussed here sounds similar to "Negative Variability" 
discussed by Jim Coplien.
We can achieve it with interface segregation (making separate interfaces 
like Putable, Takable etc) or using Inheritance with cancellation.

Just my $0.01





>From: concurrency-interest-request@cs.oswego.edu
>Reply-To: concurrency-interest@cs.oswego.edu
>To: concurrency-interest@altair.cs.oswego.edu
>Subject: Concurrency-interest digest, Vol 1 #299 - 1 msg
>Date: Mon, 04 Oct 2004 12:00:01 -0400
>
>Send Concurrency-interest mailing list submissions to
>	concurrency-interest@altair.cs.oswego.edu
>
>To subscribe or unsubscribe via the World Wide Web, visit
>	http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
>or, via email, send a message with subject or body 'help' to
>	concurrency-interest-request@altair.cs.oswego.edu
>
>You can reach the person managing the list at
>	concurrency-interest-admin@altair.cs.oswego.edu
>
>When replying, please edit your Subject line so it is more specific
>than "Re: Contents of Concurrency-interest digest..."
>
>
>Today's Topics:
>
>    1. Re: Adding interfaces Sink and Source? (Joshua Bloch)
>
>--__--__--
>
>Message: 1
>Date: Sun, 3 Oct 2004 10:18:13 -0700
>From: Joshua Bloch <jbloch@gmail.com>
>Reply-To: josh@bloch.us
>To: concurrency-interest@altair.cs.oswego.edu
>Subject: Re: [concurrency-interest] Adding interfaces Sink and Source?
>
>Folks,
>
>Vaguely related to this, here's a cool pattern for use when you want
>to do several forwarding wrappers of the same interface.  I learned
>about this pattern from Neal, after I wrote my book.  Had I known
>about it earlier, it would probably be in the book.  The basic idea is
>to make a helper wrapper class that does nothing but forwarding:
>
>public class ForwardingQueue<E> extends Queue<E> {
>     private final Queue<E> queue;
>
>     ForwardingQueue(Queue<E> queue) { this.queue = queue; }
>
>     boolean offer(E o) { return queue.offer(o);  }
>     E poll()           { return queue.poll();    }
>     E remove();        { return queue.remove();  }
>     E peek();          { return queue.peek();    }
>     E element();       { return queue.element(); }
>
>     ... // add Collections methods or (much better) extend 
>forwardingCollection
>}
>
>Then you can make specialized wrappers by overriding only the methods
>where you want to do something other than vanilla forwarding, e.g.:
>
>public class Collections {
>     public static <E> Queue<E> putOnlyQueue(Queue<? super E> queue) {
>         return new ForwardingQueue<E>() {
>             E poll();    { throw new UnsupportedOperation(); }
>             E remove();  { throw new UnsupportedOperation(); }
>             E peek();    { throw new UnsupportedOperation(); }
>             E element(); { throw new UnsupportedOperation(); }
>             ... // Eliminate some collections ops also
>         };
>     }
>
>     pubic static <E> Queue<E> takeOnlyQueue(Queue<? extends E> queue) {
>         return new ForwardingQueue<E>() {
>             boolean offer(E o) { throw new UnsupportedOperation(); }
>             ... // Eliminate some collections ops also
>         };
>     }
>
>     ...
>}
>
>You get the idea.  I have never actually used this pattern in
>practice, but that's only because I learned about it too late.  I
>think it's a good idea.
>
>             Josh
>
>On Sat, 02 Oct 2004 21:38:10 -0400, Tim Peierls <tim@peierls.net> wrote:
> > Doug Lea wrote:
> > > The way we left it, it is still possible for individual developers
> > > to unify usages themselves by adding a bit of glue. For example:
> > >
> > > interface Puttable<E> { void put(E x) throws Exception; }
> > > class MyLinkedQueue<E> extends LinkedQueue<E> implements Puttable<E> {
> > >   ...
> > > }
> >
> > Expanding on this a bit, it might be convenient to use wrapper factories
> > that convert BlockingQueues to custom Puttable and Takable interfaces.
> >
> > class QUtil {
> >   static Puttable<E> asPuttable(final BlockingQueue<E> q) {
> >     return new Puttable<E>() {
> >       public void put(E e) throws InterruptedException { q.put(e); }
> >     }
> >   }
> >   static Takable<E> asTakable(final BlockingQueue<E> q) {
> >     return new Takable<E>() {
> >       public E take() throws InterruptedException { return q.take(); }
> >     }
> >   }
> >
> > But if the only reason you miss Puttable and Takable is the way that 
>they
> > prevented consumers from accidentally or maliciously accessing producer
> > methods and vice versa, then a simple way to achieve the same effect 
>without
> > introducing new interfaces is via a factory that creates wrapped 
>blocking
> > queues that throw UOE on all but a subset of the queue methods:
> >
> > class QUtil {
> >   static BlockingQueue<E> putOnlyBlockingQueue(final BlockingQueue<E> q) 
>{
> >     return new BlockingQueue<E>() {
> >       public void put(E e) throws InterruptedException { q.put(e); }
> >       // similarly for all "put"-like methods that you want to support
> >
> >       public E take() { throw new UnsupportedOperationException(); }
> >       // similarly for all "take"-like methods and anything else you
> >       // don't want to support
> >     };
> >   }
> >
> >   static BlockingQueue<E> takeOnlyBlockingQueue(final BlockingQueue<E> 
>q) {
> >     return new BlockingQueue<E>() {
> >       public E take() throws InterruptedException { return q.take(); }
> >       // similarly for all "take"-like methods that you want to support
> >
> >       public void put(E e) { throw new UnsupportedOperationException(); 
>}
> >       // similarly for all "put"-like methods and anything else you
> >       // don't want to support
> >     };
> >   }
> > }
> >
> > Use this utility to wrap a queue before handing it over to producers and
> > consumers. For example,
> >
> >   interface Producer {
> >     public void produceTo(BlockingQueue<Foo> putOnlyQueue);
> >   }
> >
> >   interface Consumer {
> >     public void consumeFrom(BlockingQueue<Foo> takeOnlyQueue);
> >   }
> >
> >   void start(Collection<Producer> producers,
> >              Collection<Consumer> consumers,
> >              BlockingQueue<Foo> fooq) {
> >
> >     for (Producer producer : producers)
> >       producer.produceTo(QUtil.putOnlyBlockingQueue(fooq));
> >
> >     for (Consumer consumer : consumers)
> >       consumer.consumeFrom(QUtil.takeOnlyBlockingQueue(fooq));
> >   }
> >
> > Now malicious or broken producers and consumers can't touch the "wrong"
> > end of the queue. This approach trades away compile time type 
>information
> > in favor of a smaller set of interfaces and run time checking, roughly
> > analogous to the design tradeoff whose resolution in the Collections
> > framework resulted in the Collections.unmodifiableXXX static methods.
> >
> > --tim
> >
> >
> >
> > _______________________________________________
> > Concurrency-interest mailing list
> > Concurrency-interest@altair.cs.oswego.edu
> > http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
> >
>
>
>--__--__--
>
>_______________________________________________
>Concurrency-interest mailing list
>Concurrency-interest@altair.cs.oswego.edu
>http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
>End of Concurrency-interest Digest

_________________________________________________________________
1 Paisa Auction with no reserve price. 
http://ads2.baazee.com/cgi-bin/banners/redirect.pl?id=2563 Steal a Deal - 
Nokia phones.