loop: change buffer to queue (remove lock)
diff --git a/serial/urlhandler/protocol_loop.py b/serial/urlhandler/protocol_loop.py
index 756704b..02f30df 100644
--- a/serial/urlhandler/protocol_loop.py
+++ b/serial/urlhandler/protocol_loop.py
@@ -23,6 +23,10 @@
     import urlparse
 except ImportError:
     import urllib.parse as urlparse
+try:
+    import queue
+except ImportError:
+    import Queue as queue
 
 from serial.serialutil import *
 
@@ -41,6 +45,10 @@
     BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
                  9600, 19200, 38400, 57600, 115200)
 
+    def __init__(self, *args, **kwargs):
+        super(Serial, self).__init__(*args, **kwargs)
+        self.buffer_size = 4096
+
     def open(self):
         """\
         Open port with current settings. This may throw a SerialException
@@ -49,8 +57,7 @@
         if self._isOpen:
             raise SerialException("Port is already open.")
         self.logger = None
-        self.buffer_lock = threading.Lock()
-        self.loop_buffer = bytearray()
+        self.queue = queue.Queue(self.buffer_size)
         self.cts = False
         self.dsr = False
 
@@ -70,6 +77,10 @@
         self.flushInput()
         self.flushOutput()
 
+    def close(self):
+        self.queue.put(None)
+        super(Serial, self).close()
+
     def _reconfigurePort(self):
         """\
         Set communication parameters on opened port. For the loop://
@@ -88,9 +99,6 @@
             # in case of quick reconnects, give the server some time
             time.sleep(0.3)
 
-    def makeDeviceName(self, port):
-        raise SerialException("there is no sensible way to turn numbers into URLs")
-
     def fromURL(self, url):
         """extract host and port from an URL string"""
         parts = urlparse.urlsplit(url)
@@ -123,8 +131,8 @@
         if self.logger:
             # attention the logged value can differ from return value in
             # threaded environments...
-            self.logger.debug('inWaiting() -> %d' % (len(self.loop_buffer),))
-        return len(self.loop_buffer)
+            self.logger.debug('inWaiting() -> %d' % (self.queue.qsize(),))
+        return self.queue.qsize()
 
     def read(self, size=1):
         """\
@@ -138,12 +146,13 @@
         else:
             timeout = None
         data = bytearray()
-        while size > 0:
-            with self.buffer_lock:
-                block = to_bytes(self.loop_buffer[:size])
-                del self.loop_buffer[:size]
-            data += block
-            size -= len(block)
+        while size > 0 and self._isOpen:
+            try:
+                data += self.queue.get(timeout=self._timeout) # XXX inter char timeout
+            except queue.Empty:
+                break
+            else:
+                size -= 1
             # check for timeout now, after data has been read.
             # useful for timeout = 0 (non blocking) read
             if timeout and time.time() > timeout:
@@ -157,7 +166,6 @@
         closed.
         """
         if not self._isOpen: raise portNotOpenError
-        # ensure we're working with bytes
         data = to_bytes(data)
         # calculate aprox time that would be used to send the data
         time_used_to_send = 10.0*len(data) / self._baudrate
@@ -166,8 +174,10 @@
         if self._writeTimeout is not None and time_used_to_send > self._writeTimeout:
             time.sleep(self._writeTimeout) # must wait so that unit test succeeds
             raise writeTimeoutError
-        with self.buffer_lock:
-            self.loop_buffer += data
+        #~ for byte in data:    # fails for python3 as it returns ints instead of b''
+        for x in range(len(data)):
+            byte = data[x:x+1]
+            self.queue.put(byte, timeout=self._writeTimeout)
         return len(data)
 
     def flushInput(self):
@@ -175,8 +185,11 @@
         if not self._isOpen: raise portNotOpenError
         if self.logger:
             self.logger.info('flushInput()')
-        with self.buffer_lock:
-            del self.loop_buffer[:]
+        try:
+            while self.queue.qsize():
+                self.queue.get_nowait()
+        except queue.Empty:
+            pass
 
     def flushOutput(self):
         """\
@@ -186,6 +199,11 @@
         if not self._isOpen: raise portNotOpenError
         if self.logger:
             self.logger.info('flushOutput()')
+        try:
+            while self.queue.qsize():
+                self.queue.get_nowait()
+        except queue.Empty:
+            pass
 
     def sendBreak(self, duration=0.25):
         """\
@@ -193,6 +211,7 @@
         duration.
         """
         if not self._isOpen: raise portNotOpenError
+        time.sleep(duration)
 
     def setBreak(self, level=True):
         """\