/** * A request from a Brewer to the warehouse. *
* CS 537, Spring 2007, Project 3. *
* A Request keeps track of the amounts requested and allocated thus far, and * serves as a waiting place for the ordering thread to wait for completion. */ public class Request { /** Source version number. */ private static final int VERSION = 3; /** Source of sequence numbers. */ private static int nextSeq = 0; /** The original amount requested. */ private Order requested; /** The requesting customer's id (for debugging output). */ private int id; /** The sequence number of this request in the order received. */ public final int seq; /** The amount allocated thus far. */ private Order alloc; /** Flag to indicate this Request is satisfied. */ private boolean completed = false; /** Creates a new Request. * Note: This method is not thread-safe, so it should be only called from * a synchronized method that prevents two concurrent invocations of * "new Request(...)". * @param id the requesting customer's id (for debugging output). * @param request the amount of each commodity needed. */ public Request(int id, Order request) { this.id = id; this.requested = request.copy(); this.seq = ++nextSeq; alloc = new Order(); } // Request(Order) /** Check whether the unfilled portion of this request is less than or * equal to supply (in all grains). * @param supply the amount to compare to. * @return true if the request can be completely satisfied by supply. */ public synchronized boolean lessOrEqual(Order supply) { for (Grain g : Grain.values()) { if (requested.get(g) - alloc.get(g) > supply.get(g)) { return false; } } return true; } // lessOrEqual(Order) /** Allocate some grain to this Request from supply. * The amount of each grain given is the minimum of the amount in supply * and the amount needed to complete the order. However, if limit is * postive, no more than 'limit' bushels of any grain will be given. * @param supply the source of grain. * @param limit if greater than zero, do not give more than this many * bushels of any one grain. * @return the total number of bushels of grain given. */ public synchronized int give(Order supply, int limit) { int result = 0; for (Grain g : Grain.values()) { int amt = requested.get(g) - alloc.get(g); if (amt > supply.get(g)) { amt = supply.get(g); } if (limit > 0 && amt > limit) { amt = limit; } alloc.change(g, amt); supply.change(g, -amt); result += amt; } return result; } // give(Order,int) /** Check whether this order is satified. * @return true if the amount allocated matches the amount requested, for * all resources. */ public synchronized boolean satisfied() { for (Grain g : Grain.values()) { if (alloc.get(g) != requested.get(g)) { return false; } } return true; } // satisfied() /** Return the total amount requested. * @return the sum of the numbers of bushels of all grains. */ public synchronized int size() { int sum = 0; for (Grain g : Grain.values()) { sum += requested.get(g); } return sum; } // size() /** Return the remaining amount requested. * @return the sum of request - alloc over all grains. */ public synchronized int remaining() { int sum = 0; for (Grain g : Grain.values()) { sum += requested.get(g) - alloc.get(g); } return sum; } // remaining() /** Signal completion. * The customer who placed this order is allowed to return. */ public synchronized void complete() { completed = true; notify(); } // complete() /** Await fulfillment of this order. * @throws InterruptedException if the current thread is interrupted while * waiting for the request to be filled. */ public synchronized void await() throws InterruptedException { while (!completed) { wait(); } } // await() /** Gets the current allocation to this request. * * @return the current amount allocated */ public synchronized Order getAlloc() { return alloc; } // getAlloc() /** Turn a Request into a printable string. * @return a printable version of this request. */ public String toString() { StringBuffer sb = new StringBuffer(seq + ":" + id); char sep = '['; for (Grain g : Grain.values()) { sb.append(String.format( "%c%d/%d %s", sep, alloc.get(g), requested.get(g), g)); sep = ','; } sb.append(']'); return sb.toString(); } // toString() } // Request