• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 
3 // Copyright 2018 The gRPC Authors
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #endregion
18 
19 using Grpc.Core.Utils;
20 using System;
21 using System.Buffers;
22 using System.Threading;
23 
24 namespace Grpc.Core.Internal
25 {
26     internal class DefaultSerializationContext : SerializationContext
27     {
28         static readonly ThreadLocal<DefaultSerializationContext> threadLocalInstance =
29             new ThreadLocal<DefaultSerializationContext>(() => new DefaultSerializationContext(), false);
30 
31         bool isComplete;
32         SliceBufferSafeHandle sliceBuffer = SliceBufferSafeHandle.Create();
33 
DefaultSerializationContext()34         public DefaultSerializationContext()
35         {
36             Reset();
37         }
38 
Complete(byte[] payload)39         public override void Complete(byte[] payload)
40         {
41             GrpcPreconditions.CheckState(!isComplete);
42             this.isComplete = true;
43 
44             var destSpan = sliceBuffer.GetSpan(payload.Length);
45             payload.AsSpan().CopyTo(destSpan);
46             sliceBuffer.Advance(payload.Length);
47             sliceBuffer.Complete();
48         }
49 
50         /// <summary>
51         /// Expose serializer as buffer writer
52         /// </summary>
GetBufferWriter()53         public override IBufferWriter<byte> GetBufferWriter()
54         {
55             GrpcPreconditions.CheckState(!isComplete);
56             return sliceBuffer;
57         }
58 
SetPayloadLength(int payloadLength)59         public override void SetPayloadLength(int payloadLength)
60         {
61             // Length is calculated using the buffer writer
62         }
63 
64         /// <summary>
65         /// Complete the payload written so far.
66         /// </summary>
Complete()67         public override void Complete()
68         {
69             GrpcPreconditions.CheckState(!isComplete);
70             sliceBuffer.Complete();
71             this.isComplete = true;
72         }
73 
GetPayload()74         internal SliceBufferSafeHandle GetPayload()
75         {
76             if (!isComplete)
77             {
78                 // mimic the legacy behavior when byte[] was used to represent the payload.
79                 throw new NullReferenceException("No payload was set. Complete() needs to be called before payload can be used.");
80             }
81             return sliceBuffer;
82         }
83 
Reset()84         public void Reset()
85         {
86             this.isComplete = false;
87             this.sliceBuffer.Reset();
88         }
89 
90         // Get a cached thread local instance of deserialization context
91         // and wrap it in a disposable struct that allows easy resetting
92         // via "using" statement.
GetInitializedThreadLocalScope()93         public static UsageScope GetInitializedThreadLocalScope()
94         {
95             var instance = threadLocalInstance.Value;
96             return new UsageScope(instance);
97         }
98 
99         public struct UsageScope : IDisposable
100         {
101             readonly DefaultSerializationContext context;
102 
UsageScopeGrpc.Core.Internal.DefaultSerializationContext.UsageScope103             public UsageScope(DefaultSerializationContext context)
104             {
105                 this.context = context;
106             }
107 
108             public DefaultSerializationContext Context => context;
DisposeGrpc.Core.Internal.DefaultSerializationContext.UsageScope109             public void Dispose()
110             {
111                 context.Reset();
112             }
113         }
114     }
115 }
116