I'm submitting this with mixed feelings since the recent discussion has
shown strong opinions about the utility of the SingleThreadModel.

I was already in the middle of doing the work when all that came about so I
went ahead and finished it.  After reaping the benefits of Tomcat for a
couple of years I've been wanting to give something back.  So after a recent
post about how to help, I went into bugzilla and found this issue.  I don't
even use STM, but was somewhat familiar with the ServletHandler and figured
I could contribute here.

At a minimum, I had fun doing the work and was able to learn a bit more
about the code base.

Maybe it will be of some use to others.

Looking forward to more good stuff from this project!!

-David

--- ServletHandler.java.orig    Thu Oct  4 15:57:50 2001
+++ ServletHandler.java Thu Oct  4 16:06:28 2001
@@ -59,7 +59,7 @@
 package org.apache.tomcat.facade;
 
 import org.apache.tomcat.core.*;
-import org.apache.tomcat.util.*;
+import org.apache.tomcat.util.collections.*;
 import java.io.*;
 import java.net.*;
 import java.util.*;
@@ -106,11 +106,18 @@
     public static final int STATE_READY=3;
 
     // -------------------- Properties --------------------
+
+    public static final String STM_POOL_SIZE = "tomcat.stmpoolsize";
     
     // extra informations - if the servlet is declared in web.xml
     private ServletInfo sw;
 
     private String servletClassName;
+
+    private SimplePool stmPool; // pool of SingleThreadModel instances
+    private int stmPoolSize;
+    private int stmInstances;   // number of servlet instances already being pooled 
+(we create them as needed)
+
     protected Class servletClass;
     protected Servlet servlet;
     protected Context context;
@@ -153,7 +160,6 @@
        return context;
     }
 
-
     public void setServletClassName( String servletClassName) {
        servlet=null; // reset the servlet, if it was set
        servletClass=null;
@@ -192,7 +198,6 @@
        } catch( Exception ex ) {
            log(context,  "Error during destroy ", ex );
        }
-       
 
        errorException=null;
     }
@@ -330,6 +335,14 @@
        }
        
        servlet = (Servlet)servletClass.newInstance();
+
+        if (servlet instanceof SingleThreadModel) {
+           stmPoolSize = Integer.getInteger(STM_POOL_SIZE, 
+SimplePool.DEFAULT_SIZE).intValue();
+           stmPool = new SimplePool(stmPoolSize);
+           stmPool.set(servlet);
+           stmInstances++;
+       }
+
        return servlet;
     }
 
@@ -348,7 +361,15 @@
                            log(context, "preServletDestroy", ex);
                        }
                    }
-                   servlet.destroy();
+
+                   if (!(servlet instanceof SingleThreadModel)) {
+                       servlet.destroy();
+                   } else {
+                       Servlet sl = null;
+                       while ((sl = (Servlet)stmPool.get()) != null) {
+                           sl.destroy();
+                       }
+                   }
 
                    for( int i=0; i< cI.length; i++ ) {
                        try {
@@ -432,6 +453,40 @@
        super.service( req, res );
     }
 
+    protected void doSTMService(HttpServletRequest reqF, HttpServletResponse resF) 
+throws Exception {
+       Servlet sl = null;
+       try {
+           boolean newInstance = false;
+           if ((sl = (Servlet)stmPool.get()) == null) {
+               synchronized (this) {
+                   if (stmInstances < stmPoolSize) {
+                       stmInstances++;
+                       newInstance = true;
+                   }
+               }
+               if (newInstance) {
+                   sl = (Servlet)servletClass.newInstance();
+                   sl.init(getServletInfo().getServletConfig());
+               }
+
+           }
+           
+           if (sl != null) {
+               sl.service(reqF, resF);
+           } else {
+               // The pool is full, just synchronize on the initial instance.
+               // Ideally, we would the pain across all pooled instances
+               // to avoid a bottleneck on a single instance.
+               synchronized(servlet) {
+                   servlet.service(reqF, resF);
+               }
+           }
+       } finally {
+           if (sl != null) {
+               stmPool.put(sl);
+           }
+       }
+    }
     
     protected void doService(Request req, Response res)
        throws Exception
@@ -476,10 +531,8 @@
 
        try {
            // We are initialized and fine
-           if (servlet instanceof SingleThreadModel) {
-               synchronized(servlet) {
-                   servlet.service(reqF, resF);
-               }
+           if ( servlet instanceof SingleThreadModel ) {
+               doSTMService(reqF, resF);
            } else {
                servlet.service(reqF, resF);
            }

Reply via email to