001: /*
002:
003: Copyright 2004, Martian Software, Inc.
004:
005: Licensed under the Apache License, Version 2.0 (the "License");
006: you may not use this file except in compliance with the License.
007: You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016:
017: */
018:
019: package com.martiansoftware.nailgun;
020:
021: /**
022: * Provides NGSession pooling functionality. One parameter, "maxIdle",
023: * governs its behavior by setting the maximum number of idle NGSession
024: * threads it will allow. It creates a pool of size maxIdle - 1, because
025: * one NGSession is kept "on deck" by the NGServer in order to eke out
026: * a little extra responsiveness.
027: *
028: * @author <a href="http://www.martiansoftware.com/contact.html">Marty Lamb</a>
029: */
030: class NGSessionPool {
031:
032: /**
033: * number of sessions to store in the pool
034: */
035: int poolSize = 0;
036:
037: /**
038: * the pool itself
039: */
040: NGSession[] pool = null;
041:
042: /**
043: * The number of sessions currently in the pool
044: */
045: int poolEntries = 0;
046:
047: /**
048: * reference to server we're working for
049: */
050: NGServer server = null;
051:
052: /**
053: * have we been shut down?
054: */
055: boolean done = false;
056:
057: /**
058: * synchronization object
059: */
060: private Object lock = new Object();
061:
062: /**
063: * Creates a new NGSessionRunner operating for the specified server, with
064: * the specified number of threads
065: * @param server the server to work for
066: * @param poolSize the maximum number of idle threads to allow
067: */
068: NGSessionPool(NGServer server, int maxIdle) {
069: this .server = server;
070: this .poolSize = maxIdle - 1;
071:
072: pool = new NGSession[poolSize];
073: poolEntries = 0;
074: }
075:
076: /**
077: * Returns an NGSession from the pool, or creates one if necessary
078: * @return an NGSession ready to work
079: */
080: NGSession take() {
081: NGSession result;
082: synchronized (lock) {
083: if (poolEntries == 0) {
084: result = new NGSession(this , server);
085: result.start();
086: } else {
087: --poolEntries;
088: result = pool[poolEntries];
089: }
090: }
091: return (result);
092: }
093:
094: /**
095: * Returns an NGSession to the pool. The pool may choose to shutdown
096: * the thread if the pool is full
097: * @param session the NGSession to return to the pool
098: */
099: void give(NGSession session) {
100: if (done || poolEntries == poolSize) {
101: session.shutdown();
102: } else {
103: synchronized (lock) {
104: pool[poolEntries] = session;
105: ++poolEntries;
106: }
107: }
108: }
109:
110: /**
111: * Shuts down the pool. Running nails are allowed to finish.
112: */
113: void shutdown() {
114: done = true;
115: synchronized (lock) {
116: while (poolEntries > 0) {
117: take().shutdown();
118: }
119: }
120: }
121:
122: }
|