mirror of https://github.com/grpc/grpc.git
Merge pull request #968 from jtattermusch/csharp_refactoring
C# refactoring and code cleanuppull/974/head
commit
4947638c62
19 changed files with 1137 additions and 696 deletions
@ -0,0 +1,407 @@ |
||||
#region Copyright notice and license |
||||
|
||||
// Copyright 2015, Google Inc. |
||||
// All rights reserved. |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Runtime.CompilerServices; |
||||
using System.Runtime.InteropServices; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using Grpc.Core.Internal; |
||||
using Grpc.Core.Utils; |
||||
|
||||
namespace Grpc.Core.Internal |
||||
{ |
||||
/// <summary> |
||||
/// Base for handling both client side and server side calls. |
||||
/// Handles native call lifecycle and provides convenience methods. |
||||
/// </summary> |
||||
internal abstract class AsyncCallBase<TWrite, TRead> |
||||
{ |
||||
readonly Func<TWrite, byte[]> serializer; |
||||
readonly Func<byte[], TRead> deserializer; |
||||
|
||||
protected readonly CompletionCallbackDelegate sendFinishedHandler; |
||||
protected readonly CompletionCallbackDelegate readFinishedHandler; |
||||
protected readonly CompletionCallbackDelegate halfclosedHandler; |
||||
|
||||
protected readonly object myLock = new object(); |
||||
|
||||
protected GCHandle gchandle; |
||||
protected CallSafeHandle call; |
||||
protected bool disposed; |
||||
|
||||
protected bool started; |
||||
protected bool errorOccured; |
||||
protected bool cancelRequested; |
||||
|
||||
protected AsyncCompletionDelegate sendCompletionDelegate; // Completion of a pending send or sendclose if not null. |
||||
protected bool readPending; // True if there is a read in progress. |
||||
protected bool readingDone; |
||||
protected bool halfcloseRequested; |
||||
protected bool halfclosed; |
||||
protected bool finished; // True if close has been received from the peer. |
||||
|
||||
// Streaming reads will be delivered to this observer. For a call that only does unary read it may remain null. |
||||
protected IObserver<TRead> readObserver; |
||||
|
||||
public AsyncCallBase(Func<TWrite, byte[]> serializer, Func<byte[], TRead> deserializer) |
||||
{ |
||||
this.serializer = Preconditions.CheckNotNull(serializer); |
||||
this.deserializer = Preconditions.CheckNotNull(deserializer); |
||||
|
||||
this.sendFinishedHandler = CreateBatchCompletionCallback(HandleSendFinished); |
||||
this.readFinishedHandler = CreateBatchCompletionCallback(HandleReadFinished); |
||||
this.halfclosedHandler = CreateBatchCompletionCallback(HandleHalfclosed); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Requests cancelling the call. |
||||
/// </summary> |
||||
public void Cancel() |
||||
{ |
||||
lock (myLock) |
||||
{ |
||||
Preconditions.CheckState(started); |
||||
cancelRequested = true; |
||||
|
||||
if (!disposed) |
||||
{ |
||||
call.Cancel(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Requests cancelling the call with given status. |
||||
/// </summary> |
||||
public void CancelWithStatus(Status status) |
||||
{ |
||||
lock (myLock) |
||||
{ |
||||
Preconditions.CheckState(started); |
||||
cancelRequested = true; |
||||
|
||||
if (!disposed) |
||||
{ |
||||
call.CancelWithStatus(status); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected void InitializeInternal(CallSafeHandle call) |
||||
{ |
||||
lock (myLock) |
||||
{ |
||||
// Make sure this object and the delegated held by it will not be garbage collected |
||||
// before we release this handle. |
||||
gchandle = GCHandle.Alloc(this); |
||||
this.call = call; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Initiates sending a message. Only once send operation can be active at a time. |
||||
/// completionDelegate is invoked upon completion. |
||||
/// </summary> |
||||
protected void StartSendMessageInternal(TWrite msg, AsyncCompletionDelegate completionDelegate) |
||||
{ |
||||
byte[] payload = UnsafeSerialize(msg); |
||||
|
||||
lock (myLock) |
||||
{ |
||||
Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null"); |
||||
CheckSendingAllowed(); |
||||
|
||||
call.StartSendMessage(payload, sendFinishedHandler); |
||||
sendCompletionDelegate = completionDelegate; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Requests receiving a next message. |
||||
/// </summary> |
||||
protected void StartReceiveMessage() |
||||
{ |
||||
lock (myLock) |
||||
{ |
||||
Preconditions.CheckState(started); |
||||
Preconditions.CheckState(!disposed); |
||||
Preconditions.CheckState(!errorOccured); |
||||
|
||||
Preconditions.CheckState(!readingDone); |
||||
Preconditions.CheckState(!readPending); |
||||
|
||||
call.StartReceiveMessage(readFinishedHandler); |
||||
readPending = true; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Default behavior just completes the read observer, but more sofisticated behavior might be required |
||||
/// by subclasses. |
||||
/// </summary> |
||||
protected virtual void CompleteReadObserver() |
||||
{ |
||||
FireReadObserverOnCompleted(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// If there are no more pending actions and no new actions can be started, releases |
||||
/// the underlying native resources. |
||||
/// </summary> |
||||
protected bool ReleaseResourcesIfPossible() |
||||
{ |
||||
if (!disposed && call != null) |
||||
{ |
||||
if (halfclosed && readingDone && finished) |
||||
{ |
||||
ReleaseResources(); |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private void ReleaseResources() |
||||
{ |
||||
if (call != null) |
||||
{ |
||||
call.Dispose(); |
||||
} |
||||
gchandle.Free(); |
||||
disposed = true; |
||||
} |
||||
|
||||
protected void CheckSendingAllowed() |
||||
{ |
||||
Preconditions.CheckState(started); |
||||
Preconditions.CheckState(!disposed); |
||||
Preconditions.CheckState(!errorOccured); |
||||
|
||||
Preconditions.CheckState(!halfcloseRequested, "Already halfclosed."); |
||||
Preconditions.CheckState(sendCompletionDelegate == null, "Only one write can be pending at a time"); |
||||
} |
||||
|
||||
protected byte[] UnsafeSerialize(TWrite msg) |
||||
{ |
||||
return serializer(msg); |
||||
} |
||||
|
||||
protected bool TrySerialize(TWrite msg, out byte[] payload) |
||||
{ |
||||
try |
||||
{ |
||||
payload = serializer(msg); |
||||
return true; |
||||
} |
||||
catch(Exception) |
||||
{ |
||||
Console.WriteLine("Exception occured while trying to serialize message"); |
||||
payload = null; |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
protected bool TryDeserialize(byte[] payload, out TRead msg) |
||||
{ |
||||
try |
||||
{ |
||||
msg = deserializer(payload); |
||||
return true; |
||||
} |
||||
catch(Exception) |
||||
{ |
||||
Console.WriteLine("Exception occured while trying to deserialize message"); |
||||
msg = default(TRead); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
protected void FireReadObserverOnNext(TRead value) |
||||
{ |
||||
try |
||||
{ |
||||
readObserver.OnNext(value); |
||||
} |
||||
catch(Exception e) |
||||
{ |
||||
Console.WriteLine("Exception occured while invoking readObserver.OnNext: " + e); |
||||
} |
||||
} |
||||
|
||||
protected void FireReadObserverOnCompleted() |
||||
{ |
||||
try |
||||
{ |
||||
readObserver.OnCompleted(); |
||||
} |
||||
catch(Exception e) |
||||
{ |
||||
Console.WriteLine("Exception occured while invoking readObserver.OnCompleted: " + e); |
||||
} |
||||
} |
||||
|
||||
protected void FireReadObserverOnError(Exception error) |
||||
{ |
||||
try |
||||
{ |
||||
readObserver.OnError(error); |
||||
} |
||||
catch(Exception e) |
||||
{ |
||||
Console.WriteLine("Exception occured while invoking readObserver.OnError: " + e); |
||||
} |
||||
} |
||||
|
||||
protected void FireCompletion(AsyncCompletionDelegate completionDelegate, Exception error) |
||||
{ |
||||
try |
||||
{ |
||||
completionDelegate(error); |
||||
} |
||||
catch(Exception e) |
||||
{ |
||||
Console.WriteLine("Exception occured while invoking completion delegate: " + e); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Creates completion callback delegate that wraps the batch completion handler in a try catch block to |
||||
/// prevent propagating exceptions accross managed/unmanaged boundary. |
||||
/// </summary> |
||||
protected CompletionCallbackDelegate CreateBatchCompletionCallback(Action<bool, BatchContextSafeHandleNotOwned> handler) |
||||
{ |
||||
return new CompletionCallbackDelegate( (error, batchContextPtr) => { |
||||
try |
||||
{ |
||||
var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr); |
||||
bool wasError = (error != GRPCOpError.GRPC_OP_OK); |
||||
handler(wasError, ctx); |
||||
} |
||||
catch(Exception e) |
||||
{ |
||||
Console.WriteLine("Caught exception in a native handler: " + e); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Handles send completion. |
||||
/// </summary> |
||||
private void HandleSendFinished(bool wasError, BatchContextSafeHandleNotOwned ctx) |
||||
{ |
||||
AsyncCompletionDelegate origCompletionDelegate = null; |
||||
lock (myLock) |
||||
{ |
||||
origCompletionDelegate = sendCompletionDelegate; |
||||
sendCompletionDelegate = null; |
||||
|
||||
ReleaseResourcesIfPossible(); |
||||
} |
||||
|
||||
if (wasError) |
||||
{ |
||||
FireCompletion(origCompletionDelegate, new OperationFailedException("Send failed")); |
||||
} |
||||
else |
||||
{ |
||||
FireCompletion(origCompletionDelegate, null); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Handles halfclose completion. |
||||
/// </summary> |
||||
private void HandleHalfclosed(bool wasError, BatchContextSafeHandleNotOwned ctx) |
||||
{ |
||||
AsyncCompletionDelegate origCompletionDelegate = null; |
||||
lock (myLock) |
||||
{ |
||||
halfclosed = true; |
||||
origCompletionDelegate = sendCompletionDelegate; |
||||
sendCompletionDelegate = null; |
||||
|
||||
ReleaseResourcesIfPossible(); |
||||
} |
||||
|
||||
if (wasError) |
||||
{ |
||||
FireCompletion(origCompletionDelegate, new OperationFailedException("Halfclose failed")); |
||||
} |
||||
else |
||||
{ |
||||
FireCompletion(origCompletionDelegate, null); |
||||
} |
||||
|
||||
} |
||||
|
||||
/// <summary> |
||||
/// Handles streaming read completion. |
||||
/// </summary> |
||||
private void HandleReadFinished(bool wasError, BatchContextSafeHandleNotOwned ctx) |
||||
{ |
||||
var payload = ctx.GetReceivedMessage(); |
||||
|
||||
lock (myLock) |
||||
{ |
||||
readPending = false; |
||||
if (payload == null) |
||||
{ |
||||
readingDone = true; |
||||
} |
||||
|
||||
ReleaseResourcesIfPossible(); |
||||
} |
||||
|
||||
// TODO: handle the case when error occured... |
||||
|
||||
if (payload != null) |
||||
{ |
||||
// TODO: handle deserialization error |
||||
TRead msg; |
||||
TryDeserialize(payload, out msg); |
||||
|
||||
FireReadObserverOnNext(msg); |
||||
|
||||
// Start a new read. The current one has already been delivered, |
||||
// so correct ordering of reads is assured. |
||||
StartReceiveMessage(); |
||||
} |
||||
else |
||||
{ |
||||
CompleteReadObserver(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,125 @@ |
||||
#region Copyright notice and license |
||||
|
||||
// Copyright 2015, Google Inc. |
||||
// All rights reserved. |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Runtime.CompilerServices; |
||||
using System.Runtime.InteropServices; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using Grpc.Core.Internal; |
||||
using Grpc.Core.Utils; |
||||
|
||||
namespace Grpc.Core.Internal |
||||
{ |
||||
/// <summary> |
||||
/// Handles server side native call lifecycle. |
||||
/// </summary> |
||||
internal class AsyncCallServer<TRequest, TResponse> : AsyncCallBase<TResponse, TRequest> |
||||
{ |
||||
readonly CompletionCallbackDelegate finishedServersideHandler; |
||||
readonly TaskCompletionSource<object> finishedServersideTcs = new TaskCompletionSource<object>(); |
||||
|
||||
public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer) : base(serializer, deserializer) |
||||
{ |
||||
this.finishedServersideHandler = CreateBatchCompletionCallback(HandleFinishedServerside); |
||||
} |
||||
|
||||
public void Initialize(CallSafeHandle call) |
||||
{ |
||||
InitializeInternal(call); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Starts a server side call. Currently, all server side calls are implemented as duplex |
||||
/// streaming call and they are adapted to the appropriate streaming arity. |
||||
/// </summary> |
||||
public Task ServerSideCallAsync(IObserver<TRequest> readObserver) |
||||
{ |
||||
lock (myLock) |
||||
{ |
||||
Preconditions.CheckNotNull(call); |
||||
|
||||
started = true; |
||||
this.readObserver = readObserver; |
||||
|
||||
call.StartServerSide(finishedServersideHandler); |
||||
StartReceiveMessage(); |
||||
return finishedServersideTcs.Task; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Sends a streaming response. Only one pending send action is allowed at any given time. |
||||
/// completionDelegate is called when the operation finishes. |
||||
/// </summary> |
||||
public void StartSendMessage(TResponse msg, AsyncCompletionDelegate completionDelegate) |
||||
{ |
||||
StartSendMessageInternal(msg, completionDelegate); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Sends call result status, also indicating server is done with streaming responses. |
||||
/// Only one pending send action is allowed at any given time. |
||||
/// completionDelegate is called when the operation finishes. |
||||
/// </summary> |
||||
public void StartSendStatusFromServer(Status status, AsyncCompletionDelegate completionDelegate) |
||||
{ |
||||
lock (myLock) |
||||
{ |
||||
Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null"); |
||||
CheckSendingAllowed(); |
||||
|
||||
call.StartSendStatusFromServer(status, halfclosedHandler); |
||||
halfcloseRequested = true; |
||||
sendCompletionDelegate = completionDelegate; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Handles the server side close completion. |
||||
/// </summary> |
||||
private void HandleFinishedServerside(bool wasError, BatchContextSafeHandleNotOwned ctx) |
||||
{ |
||||
lock (myLock) |
||||
{ |
||||
finished = true; |
||||
|
||||
ReleaseResourcesIfPossible(); |
||||
} |
||||
// TODO: handle error ... |
||||
|
||||
finishedServersideTcs.SetResult(null); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,95 @@ |
||||
#region Copyright notice and license |
||||
|
||||
// Copyright 2015, Google Inc. |
||||
// All rights reserved. |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Runtime.CompilerServices; |
||||
using System.Runtime.InteropServices; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using Grpc.Core.Internal; |
||||
using Grpc.Core.Utils; |
||||
|
||||
namespace Grpc.Core.Internal |
||||
{ |
||||
/// <summary> |
||||
/// If error != null, there's been an error or operation has been cancelled. |
||||
/// </summary> |
||||
internal delegate void AsyncCompletionDelegate(Exception error); |
||||
|
||||
/// <summary> |
||||
/// Helper for transforming AsyncCompletionDelegate into full-fledged Task. |
||||
/// </summary> |
||||
internal class AsyncCompletionTaskSource |
||||
{ |
||||
readonly TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); |
||||
readonly AsyncCompletionDelegate completionDelegate; |
||||
|
||||
public AsyncCompletionTaskSource() |
||||
{ |
||||
completionDelegate = new AsyncCompletionDelegate(HandleCompletion); |
||||
} |
||||
|
||||
public Task Task |
||||
{ |
||||
get |
||||
{ |
||||
return tcs.Task; |
||||
} |
||||
} |
||||
|
||||
public AsyncCompletionDelegate CompletionDelegate |
||||
{ |
||||
get |
||||
{ |
||||
return completionDelegate; |
||||
} |
||||
} |
||||
|
||||
private void HandleCompletion(Exception error) |
||||
{ |
||||
if (error == null) |
||||
{ |
||||
tcs.SetResult(null); |
||||
return; |
||||
} |
||||
if (error is OperationCanceledException) |
||||
{ |
||||
tcs.SetCanceled(); |
||||
return; |
||||
} |
||||
tcs.SetException(error); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,48 @@ |
||||
#region Copyright notice and license |
||||
|
||||
// Copyright 2015, Google Inc. |
||||
// All rights reserved. |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
#endregion |
||||
|
||||
using System; |
||||
|
||||
namespace Grpc.Core |
||||
{ |
||||
/// <summary> |
||||
/// Thrown when gRPC operation fails. |
||||
/// </summary> |
||||
public class OperationFailedException : Exception |
||||
{ |
||||
public OperationFailedException(string message) : base(message) |
||||
{ |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,113 @@ |
||||
#region Copyright notice and license |
||||
|
||||
// Copyright 2015, Google Inc. |
||||
// All rights reserved. |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Threading.Tasks; |
||||
using System.Collections.Generic; |
||||
using System.Collections.Concurrent; |
||||
using System.Diagnostics; |
||||
|
||||
namespace Grpc.Core.Utils |
||||
{ |
||||
public static class Preconditions |
||||
{ |
||||
/// <summary> |
||||
/// Throws ArgumentException if condition is false. |
||||
/// </summary> |
||||
public static void CheckArgument(bool condition) |
||||
{ |
||||
if (!condition) |
||||
{ |
||||
throw new ArgumentException(); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Throws ArgumentException with given message if condition is false. |
||||
/// </summary> |
||||
public static void CheckArgument(bool condition, string errorMessage) |
||||
{ |
||||
if (!condition) |
||||
{ |
||||
throw new ArgumentException(errorMessage); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Throws NullReferenceException if reference is null. |
||||
/// </summary> |
||||
public static T CheckNotNull<T> (T reference) |
||||
{ |
||||
if (reference == null) |
||||
{ |
||||
throw new NullReferenceException(); |
||||
} |
||||
return reference; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Throws NullReferenceException with given message if reference is null. |
||||
/// </summary> |
||||
public static T CheckNotNull<T> (T reference, string errorMessage) |
||||
{ |
||||
if (reference == null) |
||||
{ |
||||
throw new NullReferenceException(errorMessage); |
||||
} |
||||
return reference; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Throws InvalidOperationException if condition is false. |
||||
/// </summary> |
||||
public static void CheckState(bool condition) |
||||
{ |
||||
if (!condition) |
||||
{ |
||||
throw new InvalidOperationException(); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Throws InvalidOperationException with given message if condition is false. |
||||
/// </summary> |
||||
public static void CheckState(bool condition, string errorMessage) |
||||
{ |
||||
if (!condition) |
||||
{ |
||||
throw new InvalidOperationException(errorMessage); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue