public Subscription Subscribe(
            CancellationToken ct,
            long start,
            int bufferSize,
            int cacheSize
            ) {
	        var sub = new Subscription();

            sub.Task = Task.Factory.StartNew(() => RunSubscription(sub, start, ct, bufferSize, cacheSize),
                TaskCreationOptions.LongRunning);
            return sub;
        }
        void RunSubscription(
            Subscription sub,
            long position,
            CancellationToken ct,
            int bufferSize,
            int cacheSize
            ) {

	        sub.DebugStartPosition = position;
            var buffer = new byte[bufferSize];
            // forever try
            while (!ct.IsCancellationRequested) {
                try {
                    // read current max length
                    var length = _position.Read();
	                sub.DebugKnownMaxOffset = length;
                    using (var prs = new PageReadStream(_messages, position, length, buffer)) {
                        using (var bin = new BinaryReader(prs)) {
                            while (prs.Position < prs.Length) {
                                var message = StorageFormat.Read(bin);
                                sub.Buffer.Enqueue(message);
	                            sub.DebugEnqueuedOffset = prs.Position;
                                position = prs.Position;

                                while (sub.Buffer.Count >= cacheSize) {
                                    ct.WaitHandle.WaitOne(500);
                                }
                            }
                        }
                    }
                    // wait till we get chance to advance
                    while (_position.Read() == position)
                    {
                        if (ct.WaitHandle.WaitOne(1000)) {
                            return;
                        }
                    }
                }
                catch (Exception ex) {
                    Debug.Print("Exception {0}", ex);
                    ct.WaitHandle.WaitOne(1000*5);
                }
            }
        }