Exemple #1
0
        public static Checksum Create(WellKnownSynchronizationKind kind, IObjectWritable @object)
        {
            using var stream       = SerializableBytes.CreateWritableStream();
            using var objectWriter = new ObjectWriter(stream);
            objectWriter.WriteInt32((int)kind);
            @object.WriteTo(objectWriter);

            return(Create(stream));
        }
Exemple #2
0
        private void WriteObject(object instance)
        {
            _cancellationToken.ThrowIfCancellationRequested();

            // write object ref if we already know this instance
            if (_objectReferenceMap.TryGetReferenceId(instance, out int id))
            {
                Debug.Assert(id >= 0);
                if (id <= byte.MaxValue)
                {
                    _writer.Write((byte)EncodingKind.ObjectRef_1Byte);
                    _writer.Write((byte)id);
                }
                else if (id <= ushort.MaxValue)
                {
                    _writer.Write((byte)EncodingKind.ObjectRef_2Bytes);
                    _writer.Write((ushort)id);
                }
                else
                {
                    _writer.Write((byte)EncodingKind.ObjectRef_4Bytes);
                    _writer.Write(id);
                }
            }
            else
            {
                IObjectWritable writable = instance as IObjectWritable;
                if (writable == null)
                {
                    throw NoSerializationWriterException($"{instance.GetType()} must implement {nameof(IObjectWritable)}");
                }

                int oldDepth = _recursionDepth;
                _recursionDepth++;

                if (_recursionDepth % MaxRecursionDepth == 0)
                {
                    // If we're recursing too deep, move the work to another thread to do so we
                    // don't blow the stack.  'LongRunning' ensures that we get a dedicated thread
                    // to do this work.  That way we don't end up blocking the threadpool.
                    Task task = Task.Factory.StartNew(
                        () => WriteObjectWorker(instance, writable),
                        _cancellationToken,
                        TaskCreationOptions.LongRunning,
                        TaskScheduler.Default);
                    task.Wait(_cancellationToken);
                }
                else
                {
                    WriteObjectWorker(instance, writable);
                }

                _recursionDepth--;
                Debug.Assert(_recursionDepth == oldDepth);
            }
        }
Exemple #3
0
        public void WriteValue(IObjectWritable value)
        {
            if (value == null)
            {
                _writer.Write((byte)EncodingKind.Null);
                return;
            }

            WriteObject(instance: value, instanceAsWritableOpt: value);
        }
Exemple #4
0
        public static Checksum Create(IObjectWritable @object, string kind)
        {
            using (var stream = SerializableBytes.CreateWritableStream())
                using (var objectWriter = new StreamObjectWriter(stream))
                {
                    objectWriter.WriteString(kind);
                    @object.WriteTo(objectWriter);

                    return(Create(stream));
                }
        }
Exemple #5
0
        private void WriteObjectWorker(IObjectWritable writable)
        {
            // emit object header up front
            _objectReferenceMap.Add(writable);

            _writer.Write((byte)EncodingKind.Object);

            // Directly write out the type-id for this object.  i.e. no need to write out the 'Type'
            // tag since we just wrote out the 'Object' tag
            this.WriteInt32(_binderSnapshot.GetTypeId(writable.GetType()));
            writable.WriteTo(this);
        }
Exemple #6
0
        private void WriteWritableObject(IObjectWritable instance)
        {
            _writer.Write((byte)DataKind.Object_W);

            Type type = instance.GetType();

            this.WriteType(type);

            _binder?.Record(instance);

            instance.WriteTo(this);
        }
Exemple #7
0
        private void WriteObject(object instance, IObjectWritable instanceAsWritableOpt)
        {
            Debug.Assert(instance != null);
            Debug.Assert(instanceAsWritableOpt == null || instance == instanceAsWritableOpt);

            _cancellationToken.ThrowIfCancellationRequested();

            // write object ref if we already know this instance
            if (_objectReferenceMap.TryGetReferenceId(instance, out var id))
            {
                Debug.Assert(id >= 0);
                if (id <= byte.MaxValue)
                {
                    _writer.Write((byte)EncodingKind.ObjectRef_1Byte);
                    _writer.Write((byte)id);
                }
                else if (id <= ushort.MaxValue)
                {
                    _writer.Write((byte)EncodingKind.ObjectRef_2Bytes);
                    _writer.Write((ushort)id);
                }
                else
                {
                    _writer.Write((byte)EncodingKind.ObjectRef_4Bytes);
                    _writer.Write(id);
                }
            }
            else
            {
                var writable = instanceAsWritableOpt;
                if (writable == null)
                {
                    writable = instance as IObjectWritable;
                    if (writable == null)
                    {
                        throw NoSerializationWriterException($"{instance.GetType()} must implement {nameof(IObjectWritable)}");
                    }
                }

                var oldDepth = _recursionDepth;
                _recursionDepth++;

                if (_recursionDepth % MaxRecursionDepth == 0)
                {
                    // If we're recursing too deep, move the work to another thread to do so we
                    // don't blow the stack.  'LongRunning' ensures that we get a dedicated thread
                    // to do this work.  That way we don't end up blocking the threadpool.
                    var task = Task.Factory.StartNew(
                        obj => WriteObjectWorker((IObjectWritable)obj),
                        writable,
                        _cancellationToken,
                        TaskCreationOptions.LongRunning,
                        TaskScheduler.Default);

                    // We must not proceed until the additional task completes. After returning from a write, the underlying
                    // stream providing access to raw memory will be closed; if this occurs before the separate thread
                    // completes its write then an access violation can occur attempting to write to unmapped memory.
                    //
                    // CANCELLATION: If cancellation is required, DO NOT attempt to cancel the operation by cancelling this
                    // wait. Cancellation must only be implemented by modifying 'task' to cancel itself in a timely manner
                    // so the wait can complete.
                    task.GetAwaiter().GetResult();
                }
                else
                {
                    WriteObjectWorker(writable);
                }

                _recursionDepth--;
                Debug.Assert(_recursionDepth == oldDepth);
            }
        }
Exemple #8
0
        private void WriteWritableObject(IObjectWritable instance)
        {
            writer.Write((byte)DataKind.Object_W);

            Type type = instance.GetType();
            this.WriteType(type);

            if (this.binder != null)
            {
                this.binder.Record(instance);
            }

            instance.WriteTo(this);
        }
Exemple #9
0
 public static void WriteTo(this IObjectWritable @object, ObjectWriter writer)
 => @object.WriteTo(writer);
Exemple #10
0
 private void WriteObjectWorker(object instance, IObjectWritable writable)
 {
     // emit object header up front
     this.WriteObjectHeader(instance, 0);
     writable.WriteTo(this);
 }