[Objectbridge-developers] Re: ObjectBridge
Brought to you by:
thma
From: Thomas M. <tho...@ho...> - 2000-11-05 11:10:57
|
Hi David, thanks for the code ! will have a look at it soon. did you my reply on your remarks the "stupid" code in RsIterator ? please set obj...@li... in cc so that all can participate. best regards, Thomas David Dixon-Peugh wrote: > Thanks for putting me on the ObJectBridge project. > > I went in and put some notes about one of the tasks you had listed. (I can't > remember what exactly the task was, but I do remember my solution for it.) > > I'm including source code for ThreadIterator which basically is an iterator > which contains two additional methods (addObject and finish). > > The way you use this, is you loop through one iterator, and call addObject > on the ThreadIterator. This then queues it up for use by the other thread. > > This will allow you to know exactly when it is okay to get rid of a database > connection. > > There is another variation to this that we may want to try, and that is creating > a PreFetchIterator. PreFetchIterator is a seperate thread which will pull > from the provided Iterator until it is done. > > To solve the problem of reclaiming the resources, it is possible to provide a > "watch" parameter, which will be notified at the end of the PreFetch when > it is possible to clean up the resources. > > Here are some examples of how I think this might work (using fork, because > it is easier to see here.) > > -------------- ThreadIterator ----------------- > > ThreadIterator ti = new ThreadIterator(); > > if (fork()) { > return ti; > } else { > while (RS.next()) { > ti.addObject( makeFromRS( RS ) ); > } > ti.finish(); > // Clean up code. . . > } > > ------------------------------------------- > > Or, with the PreFetch, we could do something like > > Object watch = new Object(); > PreFetchIterator pfi = new PreFetchIterator( rsi, watch ); > pfi.start(); > > if (fork()) { > return pfi; > } else { > try { > watch.wait(); > } catch (InterruptedException e) { } > // Clean up code. . . > } > > -------------------------------------------- > > Obviously, we would need to push and pull a few things here > and there to get something that works. I personally think that > PreFetchIterator may be the way to go. (Origionally, I was thinking > ThreadIterator) > > There are many other things that could be going on that we could do > while some other thread is handling pulling results, and serving them > to the user. Of course, this isn't BeOS, so creating a lot of threads > is not necessarily a good thing. > > Well, enjoy the code. . . I'll try to do more work tommorow. Maybe > I'll check out what other tasks you have, and take a closer look > at ojb.server. > > Thanks, > > David. > > ------------------------------------------------------------------------ > package ojb.broker.accesslayer; > > import java.util.Iterator; > import java.util.NoSuchElementException; > import java.util.LinkedList; > import java.lang.InterruptedException; > > /** > * ThreadIterator contains a thread-safe > * queue which implements the Iterator class. > * > * The idea is, that you execute database > * operations in a different thread, and > * return this Iterator right away. > * > * The database thread adds stuff onto the > * end of the queue, and the calling thread > * pulls stuff off of the begining of the > * queue. > * > * The calling thread will block until data > * is available from the queue. > * > * @author <a href="mailto:dp...@mi...">David Dixon-Peugh</a> > */ > > public class ThreadIterator implements Iterator { > > private boolean isDone = false; > private LinkedList queue = new LinkedList(); > > public ThreadIterator() { } > > public void addObject( Object obj ) { > synchronized (queue) { > queue.addLast( obj ); > } > queue.notifyAll(); > } > > public void finish() { > isDone = true; > queue.notifyAll(); > } > > public boolean hasNext() { > while (true) { > synchronized (queue) { > if ( queue.size() > 0 ) { > // If I have data in the Queue, return True. > return true; > } > if (isDone) { > return false; > } > } > try { > queue.wait(); > } catch (InterruptedException e) { } > > } > } > > public Object next() > throws NoSuchElementException > { > while (true) { > synchronized (queue) { > if (queue.size() > 0 ) { > return queue.removeFirst(); > } > if (isDone) { > throw new NoSuchElementException(); > } > } > try { > queue.wait(); > } catch (InterruptedException e) { } > } > } > > public void remove() > { > while (true) { > synchronized (queue) { > if (queue.size() > 0 ) { > queue.removeFirst(); > return; > } > if (isDone) { > return; > } > } > try { > queue.wait(); > } catch (InterruptedException e) { } > } > } > } > > ------------------------------------------------------------------------ > package ojb.broker.accesslayer; > > import java.util.Iterator; > import java.util.NoSuchElementException; > import java.util.LinkedList; > import java.lang.InterruptedException; > > /** > * PreFetchIterator is an iterator which is based on > * another iterator. However, this one runs in its > * own thread. > * > * You can build it with one of two constructors. > * > * The first constructor takes only the Iterator to > * be prefetched. > * > * The second constructor takes the Iterator and a > * generic object. This Object will have "notify" > * called on it when the PreFetching is done. > * > * This way the builder of the iterator can call > * wait() and wake up when the resources of the > * iterator are used. > * > * @author <a href="mailto:dp...@mi...">David Dixon-Peugh</a> > */ > > public class PreFetchIterator > implements Iterator, Runnable { > > private Object w; > private Iterator src; > boolean isDone = false; > > private LinkedList queue = new LinkedList(); > > public PreFetchIterator(Iterator source) > { > src = source; > w = new Object(); > } > > public PreFetchIterator(Iterator source, Object watch) { > src = source; > w = watch; > } > > /** > * From Runnable Interface > * > * This is basically a loop which pulls things from the > * source, and drops them into the queue. > * > * When the loop is done, it will call notifyAll on the > * watcher. > */ > > public void run() { > while (src.hasNext()) { > synchronized (queue) { > queue.addLast( src.next() ); > queue.notifyAll(); > } > } > isDone = false; > queue.notifyAll(); > w.notifyAll(); > } > > /** > * From Iterator interface > * > * This checks to see if anything is on the queue, > * and if so, it returns true. > * > * If the queue is empty, and isDone is marked, then > * it is completed. > * > * Otherwise, it waits on the queue to be notified. > */ > > public boolean hasNext() { > while (true) { > synchronized (queue) { > if ( queue.size() > 0 ) { > // If I have data in the Queue, return True. > return true; > } > if (isDone) { > return false; > } > } > try { > queue.wait(); > } catch (InterruptedException e) { } > > } > } > > public Object next() > throws NoSuchElementException > { > while (true) { > synchronized (queue) { > if (queue.size() > 0 ) { > return queue.removeFirst(); > } > if (isDone) { > throw new NoSuchElementException(); > } > } > try { > queue.wait(); > } catch (InterruptedException e) { } > } > } > > public void remove() > { > while (true) { > synchronized (queue) { > if (queue.size() > 0 ) { > queue.removeFirst(); > return; > } > if (isDone) { > return; > } > } > try { > queue.wait(); > } catch (InterruptedException e) { } > } > } > } |