Index: Utilities.java
===================================================================
--- Utilities.java	(revision 11969)
+++ Utilities.java	(working copy)
@@ -50,7 +50,7 @@
             osName.startsWith("NetBSD");
         isPlatformWindows = osName.startsWith("Windows");
     }
-
+    
     public static boolean isFilenameAbsolute(String filename)
     {
         final int length = filename.length();
Index: Gate.java
===================================================================
--- Gate.java	(revision 0)
+++ Gate.java	(revision 0)
@@ -0,0 +1,152 @@
+/*
+ * Gate.java
+ *
+ *   A GATE is an object with two states, open and closed. It is
+ *   created with MAKE-GATE. Its state can be opened (OPEN-GATE) or
+ *   closed (CLOSE-GATE) and can be explicitly tested with
+ *   GATE-OPEN-P. Usually though, a thread awaits the opening of a
+ *   gate by WAIT-OPEN-GATE.
+ *   
+ */
+
+package org.armedbear.lisp;
+
+public final class Gate extends LispObject
+{
+    private boolean open;
+
+    private Gate(boolean open) 
+    { 
+        this.open = open; 
+    }
+
+    @Override
+    public LispObject typeOf()    { return Symbol.GATE; }
+
+    @Override
+    public LispObject classOf()   { return BuiltInClass.GATE; }
+
+    @Override
+    public String writeToString() { return unreadableString("GATE"); }
+
+    @Override
+    public LispObject typep(LispObject typeSpecifier) throws ConditionThrowable
+    {
+        if (typeSpecifier == Symbol.GATE)
+            return T;
+        if (typeSpecifier == BuiltInClass.GATE)
+            return T;
+        return super.typep(typeSpecifier);
+    }
+
+    public boolean isOpen() 
+    {
+        return open;
+    }
+
+    public synchronized void close()
+    {
+        open = false;
+    }
+
+    public synchronized void open()  {
+        open = true;
+        notifyAll();
+    }
+
+    public synchronized void wait_for_open(long timeout) throws InterruptedException {
+        if (open)
+            return;
+        wait(timeout);
+    }
+
+
+    private static final void check_for_gate(LispObject arg) throws ConditionThrowable
+    {
+        if (arg instanceof Gate)
+            return;
+        type_error(arg, Symbol.GATE);
+    }
+
+    // ### make-gate => gate
+    private static final Primitive MAKE_GATE =
+        new Primitive("make-gate", PACKAGE_EXT, true, "openp")
+    {
+        @Override
+        public LispObject execute(LispObject arg) throws ConditionThrowable
+        {
+            return new Gate(arg.getBooleanValue());
+        }
+    };
+
+    // ### open-gate-p gate => generalized-boolean
+    private static final Primitive OPEN_GATE_P =
+        new Primitive("open-gate-p", PACKAGE_EXT, true, "gate")
+    {
+        @Override
+        public LispObject execute(LispObject arg) throws ConditionThrowable
+        {
+            check_for_gate(arg);
+            return ((Gate) arg).isOpen() ? T : NIL;
+        }
+    };
+
+
+    // ### open-gate gate => generalized-boolean
+    private static final Primitive OPEN_GATE =
+        new Primitive("open-gate", PACKAGE_EXT, true, "gate")
+    {
+        @Override
+        public LispObject execute(LispObject arg) throws ConditionThrowable
+        {
+            check_for_gate(arg);
+            ((Gate) arg).open();
+            return T;
+        }
+    };
+
+    // ### close-gate gate
+    private static final Primitive CLOSE_GATE =
+        new Primitive("close-gate", PACKAGE_EXT, true, "gate")
+    {
+        @Override
+        public LispObject execute(LispObject arg) throws ConditionThrowable
+        {
+            check_for_gate(arg);
+            ((Gate)arg).close();
+            return T;
+        }
+    };
+
+
+    // ### wait-open-gate gate
+    private static final Primitive WAIT_OPEN_GATE =
+        new Primitive("wait-open-gate", PACKAGE_EXT, true, "gate &optional timeout")
+    {
+
+        @Override
+        public LispObject execute(LispObject gate) throws ConditionThrowable
+        {
+            return execute(gate, Fixnum.ZERO);
+        }
+        
+        @Override
+        public LispObject execute(LispObject gate, LispObject timeout) throws ConditionThrowable
+        {
+            check_for_gate(gate);
+
+            long msecs = LispThread.javaSleepInterval(timeout);
+            try {
+                ((Gate)gate).wait_for_open(msecs);
+                return T;
+            } catch (InterruptedException e) {
+                return error(new LispError("The thread "
+                                           + LispThread.currentThread().writeToString()
+                                           + " was interrupted."));
+            }
+                
+
+        }
+    };
+
+}
Index: BuiltInClass.java
===================================================================
--- BuiltInClass.java	(revision 11969)
+++ BuiltInClass.java	(working copy)
@@ -111,6 +111,7 @@
   public static final BuiltInClass MAILBOX              = addClass(Symbol.MAILBOX);
   public static final BuiltInClass METHOD_COMBINATION   = addClass(Symbol.METHOD_COMBINATION);
   public static final BuiltInClass MUTEX                = addClass(Symbol.MUTEX);
+  public static final BuiltInClass GATE                 = addClass(Symbol.GATE);
   public static final BuiltInClass NIL_VECTOR           = addClass(Symbol.NIL_VECTOR);
   public static final BuiltInClass NULL                 = addClass(Symbol.NULL);
   public static final BuiltInClass NUMBER               = addClass(Symbol.NUMBER);
Index: Symbol.java
===================================================================
--- Symbol.java	(revision 11969)
+++ Symbol.java	(working copy)
@@ -2843,6 +2843,8 @@
     PACKAGE_EXT.addExternalSymbol("COMPILER-UNSUPPORTED-FEATURE-ERROR");
   public static final Symbol MUTEX =
     PACKAGE_EXT.addExternalSymbol("MUTEX");
+  public static final Symbol GATE =
+    PACKAGE_EXT.addExternalSymbol("GATE");
   public static final Symbol THREAD =
     PACKAGE_EXT.addExternalSymbol("THREAD");
   public static final Symbol SUPPRESS_COMPILER_WARNINGS =
Index: Autoload.java
===================================================================
--- Autoload.java	(revision 11969)
+++ Autoload.java	(working copy)
@@ -489,6 +489,7 @@
         autoload(PACKAGE_EXT, "arglist", "arglist", true);
         autoload(PACKAGE_EXT, "assq", "assq", true);
         autoload(PACKAGE_EXT, "assql", "assql", true);
+        autoload(PACKAGE_EXT, "close-gate", "Gate", true);
         autoload(PACKAGE_EXT, "file-directory-p", "probe_file", true);
         autoload(PACKAGE_EXT, "gc", "gc", true);
         autoload(PACKAGE_EXT, "get-floating-point-modes", "FloatFunctions", true);
@@ -497,11 +498,13 @@
         autoload(PACKAGE_EXT, "mailbox-peek", "Mailbox", true);
         autoload(PACKAGE_EXT, "mailbox-read", "Mailbox", true);
         autoload(PACKAGE_EXT, "mailbox-send", "Mailbox", true);
+        autoload(PACKAGE_EXT, "make-gate", "Gate", true);
         autoload(PACKAGE_EXT, "make-mailbox", "Mailbox", true);
         autoload(PACKAGE_EXT, "make-mutex", "Mutex", true);
         autoload(PACKAGE_EXT, "make-slime-input-stream", "SlimeInputStream", true);
         autoload(PACKAGE_EXT, "make-slime-output-stream", "SlimeOutputStream", true);
         autoload(PACKAGE_EXT, "make-thread-lock", "ThreadLock", true);
+        autoload(PACKAGE_EXT, "open-gate", "Gate", true);
         autoload(PACKAGE_EXT, "probe-directory", "probe_file", true);
         autoload(PACKAGE_EXT, "release-mutex", "Mutex", true);
         autoload(PACKAGE_EXT, "set-floating-point-modes", "FloatFunctions", true);
@@ -512,6 +515,7 @@
         autoload(PACKAGE_EXT, "string-position", "StringFunctions");
         autoload(PACKAGE_EXT, "thread-lock", "ThreadLock", true);
         autoload(PACKAGE_EXT, "thread-unlock", "ThreadLock", true);
+        autoload(PACKAGE_EXT, "wait-open-gate", "Gate", true);
         autoload(PACKAGE_JAVA, "%jnew-proxy", "JProxy");
         autoload(PACKAGE_JAVA, "%find-java-class", "JavaClass");
         autoload(PACKAGE_JAVA, "%jmake-invocation-handler", "JProxy");
Index: Mutex.java
===================================================================
--- Mutex.java	(revision 11969)
+++ Mutex.java	(working copy)
@@ -94,7 +94,6 @@
         notify();
     }
 
-
     @Override
     public String writeToString()
     {
@@ -148,4 +147,5 @@
                                             " is not a mutex."));
         }
     };
+
 }
