 	var latestValue: T?
 	var completed = false
 }
+
+private class ConcatState<T> {
+	let queue = dispatch_queue_create("org.reactivecocoa.ReactiveCocoa.ColdSignal.concat", DISPATCH_QUEUE_SERIAL)
+	let subscriber: Subscriber<T>
+
+	var inFlight: Int = 1
+	var enqueuedSignals = [ColdSignal<T>]()
+	var currentSignal: ColdSignal<T>?
+
+	init(subscriber: Subscriber<T>) {
+		self.subscriber = subscriber
+	}
+
+	func decrementInFlight() {
+		dispatch_sync(queue) {
+			if --self.inFlight == 0 && self.enqueuedSignals.count == 0 && self.currentSignal == nil {
+				self.subscriber.put(.Completed)
+			}
+		}
+	}
+
+	func dequeueIfReady() {
+		var signal: ColdSignal<T>?
+
+		dispatch_sync(queue) {
+			if self.currentSignal != nil {
+				return
+			} else if self.enqueuedSignals.count == 0 {
+				return
+			}
+
+			signal = self.enqueuedSignals.removeAtIndex(0)
+			self.currentSignal = signal
+			self.inFlight++
+		}
+
+		if let signal = signal {
+			let signalDisposable = SerialDisposable()
+			subscriber.disposable.addDisposable(signalDisposable)
+
+			signalDisposable.innerDisposable = signal.start(next: { value in
+				self.subscriber.put(.Next(Box(value)))
+			}, error: { error in
+				self.subscriber.put(.Error(error))
+
+				// TODO: We should remove our disposable from the
+				// composite disposable here, but that is non-trivial to
+				// do right now. See https://github.com/ReactiveCocoa/ReactiveCocoa/issues/1535.
+			}, completed: {
+				dispatch_sync(self.queue) {
+					self.currentSignal = nil
+				}
+
+				// TODO: Avoid multiple dispatches.
+				self.decrementInFlight()
+				self.dequeueIfReady()
+			})
+		}
+	}
+}


			subscriber.disposable.addDisposable(selfDisposable)
		}
	}

	/// Ignores all values from the receiver, then subscribes to and forwards

		}
	}

	/// Merges a signal of signals down into a single signal, biased toward the
	/// signals added earlier.
	///
