         break
 
       default:
-        let selectput = Unmanaged<dispatch_semaphore_t>.fromOpaque(COpaquePointer(context)).takeRetainedValue()
+        let ws = Unmanaged<dispatch_semaphore_t>.fromOpaque(COpaquePointer(context)).takeRetainedValue()
         if let s = semaphore.get()
         {
-          let context = dispatch_get_context(selectput)
-          let element: T = UnsafePointer(context).memory
-          let selection = Selection(selectionID: selectionID, selectionData: element)
-          dispatch_semaphore_signal(selectput)
-
-          let selectptr = UnsafeMutablePointer<Void>(Unmanaged.passRetained(selection).toOpaque())
-          dispatch_set_context(s, selectptr)
-          dispatch_semaphore_signal(s)
+          let context = dispatch_get_context(ws)
+          if context == waitSelect
+          { // we're talking to a selectPut(); it needs a semaphore
+            let buffer = UnsafeMutablePointer<T>.alloc(1)
+            dispatch_set_context(threadLock, buffer)
+            let contextptr = UnsafeMutablePointer<Void>(Unmanaged.passRetained(threadLock).toOpaque())
+            dispatch_set_context(ws, contextptr)
+            dispatch_semaphore_signal(ws)
+            dispatch_semaphore_wait(threadLock, DISPATCH_TIME_FOREVER)
+
+            // thread awoken by insert()
+            assert(dispatch_get_context(threadLock) == buffer)
+            let element = buffer.move()
+            buffer.dealloc(1)
+
+            let selection = Selection(selectionID: selectionID, selectionData: element)
+            let selectptr = UnsafeMutablePointer<Void>(Unmanaged.passRetained(selection).toOpaque())
+            dispatch_set_context(s, selectptr)
+            dispatch_semaphore_signal(s)
+          }
+          else
+          { // the data is attached from a put()
+            let element: T = UnsafePointer(context).memory
+            dispatch_semaphore_signal(ws)
+
+            let selection = Selection(selectionID: selectionID, selectionData: element)
+            let selectptr = UnsafeMutablePointer<Void>(Unmanaged.passRetained(selection).toOpaque())
+            dispatch_set_context(s, selectptr)
+            dispatch_semaphore_signal(s)
+          }
         }
         else
         { // signal failure to the writer
-          dispatch_set_context(selectput, nil)
-          dispatch_semaphore_signal(selectput)
+          dispatch_set_context(ws, nil)
+          dispatch_semaphore_signal(ws)
         }
       }
     }

            let selectptr = UnsafeMutablePointer<Void>(Unmanaged.passRetained(selection).toOpaque())
            dispatch_set_context(s, selectptr)
            dispatch_semaphore_signal(s)
            return
          }
        }
        else
        {
          self.writerQueue.undequeue(ws)
          // The spinlock stayed locked between dequeue() and undequeue(),
          // so it was transparent to other threads.
          OSSpinLockUnlock(&self.lock)
          return
        }
      }

      if self.closed

        preconditionFailure("Context is invalid in \(__FUNCTION__)")

      case waitSelect:
        // waitSelect has a significant chance of failure, but the selectPutNow() path should work "all" the time.
        readerQueue.undequeue(rs)

      default:
