AsyncCallServer.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #region Copyright notice and license
  2. // Copyright 2015, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #endregion
  31. using System;
  32. using System.Diagnostics;
  33. using System.Runtime.CompilerServices;
  34. using System.Runtime.InteropServices;
  35. using System.Threading;
  36. using System.Threading.Tasks;
  37. using Grpc.Core.Internal;
  38. using Grpc.Core.Utils;
  39. namespace Grpc.Core.Internal
  40. {
  41. /// <summary>
  42. /// Manages server side native call lifecycle.
  43. /// </summary>
  44. internal class AsyncCallServer<TRequest, TResponse> : AsyncCallBase<TResponse, TRequest>
  45. {
  46. readonly TaskCompletionSource<object> finishedServersideTcs = new TaskCompletionSource<object>();
  47. public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer) : base(serializer, deserializer)
  48. {
  49. }
  50. public void Initialize(CallSafeHandle call)
  51. {
  52. DebugStats.ActiveServerCalls.Increment();
  53. InitializeInternal(call);
  54. }
  55. /// <summary>
  56. /// Starts a server side call.
  57. /// </summary>
  58. public Task ServerSideCallAsync()
  59. {
  60. lock (myLock)
  61. {
  62. Preconditions.CheckNotNull(call);
  63. started = true;
  64. call.StartServerSide(HandleFinishedServerside);
  65. return finishedServersideTcs.Task;
  66. }
  67. }
  68. /// <summary>
  69. /// Sends a streaming response. Only one pending send action is allowed at any given time.
  70. /// completionDelegate is called when the operation finishes.
  71. /// </summary>
  72. public void StartSendMessage(TResponse msg, AsyncCompletionDelegate<object> completionDelegate)
  73. {
  74. StartSendMessageInternal(msg, completionDelegate);
  75. }
  76. /// <summary>
  77. /// Receives a streaming request. Only one pending read action is allowed at any given time.
  78. /// completionDelegate is called when the operation finishes.
  79. /// </summary>
  80. public void StartReadMessage(AsyncCompletionDelegate<TRequest> completionDelegate)
  81. {
  82. StartReadMessageInternal(completionDelegate);
  83. }
  84. /// <summary>
  85. /// Sends call result status, also indicating server is done with streaming responses.
  86. /// Only one pending send action is allowed at any given time.
  87. /// completionDelegate is called when the operation finishes.
  88. /// </summary>
  89. public void StartSendStatusFromServer(Status status, AsyncCompletionDelegate<object> completionDelegate)
  90. {
  91. lock (myLock)
  92. {
  93. Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
  94. CheckSendingAllowed();
  95. call.StartSendStatusFromServer(status, HandleHalfclosed);
  96. halfcloseRequested = true;
  97. readingDone = true;
  98. sendCompletionDelegate = completionDelegate;
  99. }
  100. }
  101. protected override void OnReleaseResources()
  102. {
  103. DebugStats.ActiveServerCalls.Decrement();
  104. }
  105. /// <summary>
  106. /// Handles the server side close completion.
  107. /// </summary>
  108. private void HandleFinishedServerside(bool success, BatchContextSafeHandle ctx)
  109. {
  110. bool cancelled = ctx.GetReceivedCloseOnServerCancelled();
  111. lock (myLock)
  112. {
  113. finished = true;
  114. if (cancelled)
  115. {
  116. // Once we cancel, we don't have to care that much
  117. // about reads and writes.
  118. Cancel();
  119. }
  120. ReleaseResourcesIfPossible();
  121. }
  122. // TODO(jtattermusch): handle error
  123. finishedServersideTcs.SetResult(null);
  124. }
  125. }
  126. }