Merge branch 'c++api' of github.com:ctiller/grpc into c++api

pull/501/head
Craig Tiller 10 years ago
commit c8296be777
  1. 37
      INSTALL
  2. 8370
      Makefile
  3. 113
      build.json
  4. 12
      examples/pubsub/README
  5. 0
      examples/pubsub/empty.proto
  6. 0
      examples/pubsub/label.proto
  7. 10
      examples/pubsub/main.cc
  8. 6
      examples/pubsub/publisher.cc
  9. 12
      examples/pubsub/publisher.h
  10. 6
      examples/pubsub/publisher_test.cc
  11. 4
      examples/pubsub/pubsub.proto
  12. 6
      examples/pubsub/subscriber.cc
  13. 12
      examples/pubsub/subscriber.h
  14. 6
      examples/pubsub/subscriber_test.cc
  15. 68
      include/grpc++/client_context.h
  16. 32
      include/grpc++/completion_queue.h
  17. 2
      include/grpc++/config.h
  18. 31
      include/grpc++/impl/call.h
  19. 3
      include/grpc++/impl/client_unary_call.h
  20. 15
      include/grpc++/impl/rpc_service_method.h
  21. 5
      include/grpc++/impl/service_type.h
  22. 6
      include/grpc++/server.h
  23. 12
      include/grpc++/server_context.h
  24. 126
      include/grpc++/stream.h
  25. 11
      include/grpc/grpc.h
  26. 33
      include/grpc/support/port_platform.h
  27. 20
      src/compiler/cpp_generator.cc
  28. 14
      src/core/iomgr/resolve_address.c
  29. 2
      src/core/iomgr/sockaddr_utils.c
  30. 5
      src/core/iomgr/socket_utils_linux.c
  31. 6
      src/core/iomgr/tcp_client_posix.c
  32. 14
      src/core/iomgr/tcp_server_posix.c
  33. 13
      src/core/support/file_posix.c
  34. 10
      src/core/support/log_posix.c
  35. 7
      src/core/support/string_posix.c
  36. 7
      src/core/support/sync_posix.c
  37. 12
      src/core/support/time_posix.c
  38. 7
      src/core/surface/server.c
  39. 18
      src/core/transport/chttp2_transport.c
  40. 46
      src/core/transport/stream_op.c
  41. 6
      src/core/transport/stream_op.h
  42. 3
      src/cpp/client/channel.cc
  43. 3
      src/cpp/client/channel.h
  44. 6
      src/cpp/client/client_context.cc
  45. 29
      src/cpp/client/client_unary_call.cc
  46. 44
      src/cpp/common/call.cc
  47. 4
      src/cpp/common/completion_queue.cc
  48. 4
      src/cpp/server/async_server_context.cc
  49. 2
      src/cpp/server/server_context.cc
  50. 33
      src/csharp/GrpcApi/MathExamples.cs
  51. 33
      src/csharp/GrpcApi/MathGrpc.cs
  52. 33
      src/csharp/GrpcApi/MathServiceImpl.cs
  53. 41
      src/csharp/GrpcApiTests/MathClientServerTests.cs
  54. 33
      src/csharp/GrpcCore/Call.cs
  55. 33
      src/csharp/GrpcCore/Calls.cs
  56. 40
      src/csharp/GrpcCore/Channel.cs
  57. 33
      src/csharp/GrpcCore/ClientStreamingAsyncResult.cs
  58. 1
      src/csharp/GrpcCore/GrpcCore.csproj
  59. 100
      src/csharp/GrpcCore/GrpcEnvironment.cs
  60. 33
      src/csharp/GrpcCore/Internal/AsyncCall.cs
  61. 33
      src/csharp/GrpcCore/Internal/CallSafeHandle.cs
  62. 33
      src/csharp/GrpcCore/Internal/ChannelSafeHandle.cs
  63. 33
      src/csharp/GrpcCore/Internal/CompletionQueueSafeHandle.cs
  64. 33
      src/csharp/GrpcCore/Internal/Enums.cs
  65. 33
      src/csharp/GrpcCore/Internal/Event.cs
  66. 33
      src/csharp/GrpcCore/Internal/GrpcThreadPool.cs
  67. 33
      src/csharp/GrpcCore/Internal/SafeHandleZeroIsInvalid.cs
  68. 33
      src/csharp/GrpcCore/Internal/ServerSafeHandle.cs
  69. 33
      src/csharp/GrpcCore/Internal/ServerWritingObserver.cs
  70. 33
      src/csharp/GrpcCore/Internal/StreamingInputObserver.cs
  71. 33
      src/csharp/GrpcCore/Internal/Timespec.cs
  72. 33
      src/csharp/GrpcCore/Marshaller.cs
  73. 33
      src/csharp/GrpcCore/Method.cs
  74. 33
      src/csharp/GrpcCore/RpcException.cs
  75. 37
      src/csharp/GrpcCore/Server.cs
  76. 33
      src/csharp/GrpcCore/ServerCallHandler.cs
  77. 33
      src/csharp/GrpcCore/ServerCalls.cs
  78. 33
      src/csharp/GrpcCore/ServerServiceDefinition.cs
  79. 33
      src/csharp/GrpcCore/Status.cs
  80. 33
      src/csharp/GrpcCore/StatusCode.cs
  81. 50
      src/csharp/GrpcCore/Utils/PortPicker.cs
  82. 33
      src/csharp/GrpcCore/Utils/RecordingObserver.cs
  83. 34
      src/csharp/GrpcCore/Utils/RecordingQueue.cs
  84. 41
      src/csharp/GrpcCoreTests/ClientServerTest.cs
  85. 57
      src/csharp/GrpcCoreTests/GrpcEnvironmentTest.cs
  86. 39
      src/csharp/GrpcCoreTests/ServerTest.cs
  87. 33
      src/csharp/GrpcCoreTests/TimespecTest.cs
  88. 35
      src/csharp/InteropClient/Client.cs
  89. 35
      src/csharp/MathClient/MathClient.cs
  90. 33
      src/csharp/ext/grpc_csharp_ext.c
  91. 195
      src/python/src/_framework/face/_calls.py
  92. 84
      src/python/src/_framework/face/testing/future_invocation_asynchronous_event_service_test_case.py
  93. 62
      src/python/src/_framework/foundation/_later_test.py
  94. 116
      src/python/src/_framework/foundation/_timer_future.py
  95. 39
      src/python/src/_framework/foundation/callable_util.py
  96. 232
      src/python/src/_framework/foundation/future.py
  97. 342
      templates/Makefile.template
  98. 79
      templates/vsprojects/vs2013/Grpc.mak.template
  99. 40
      templates/vsprojects/vs2013/build_and_run_tests.bat.template
  100. 10
      test/build/protobuf.cc
  101. Some files were not shown because too many files have changed in this diff Show More

@ -14,10 +14,14 @@ A typical unix installation won't require any more steps than running:
$ make
# make install
You don't need anything else than GNU Make and gcc. Under a Debian or
Ubuntu system, this should boil down to the following package:
You don't need anything else than GNU Make, gcc and autotools. Under a Debian
or Ubuntu system, this should boil down to the following packages:
# apt-get install build-essential python-all-dev python-virtualenv
# apt-get install build-essential autoconf libtool
Building the python wrapper requires the following:
# apt-get install python-all-dev python-virtualenv
*******************************
@ -68,33 +72,28 @@ Compiling and running grpc plain-C tests dont't require any more dependency.
Compiling and running grpc C++ tests depend on protobuf 3.0.0, gtest and
gflags. Although gflags and protobuf are provided in third_party, you will
need to manually install these dependencies on your system to run these tests.
gflags. Although gflags is provided in third_party, you will need to manually
install that dependency on your system to run these tests.
Under a Debian or Ubuntu system, you can install the gtests and gflags packages
using apt-get:
# apt-get install libgflags-dev libgtest-dev
However, protobuf 3.0.0 isn't in a debian package yet: you'll need to compile
and install it from the sources in the third_party. Note that if you already
have the protobuf and protoc packages installed on your system, they will most
likely interfere, and you'll need to uninstall them first.
However, protobuf 3.0.0 isn't in a debian package yet, but the Makefile will
automatically try and compile the one present in third_party if you cloned the
repository recursively, and that it detects your system is lacking it.
Compiling and installing protobuf 3.0.0 requires a few more dependencies in
itself, notably the autoconf suite, curl, and unzip. If you have apt-get, you
can install these dependencies this way:
itself, notably the autoconf suite. If you have apt-get, you can install
these dependencies this way:
# apt-get install unzip curl autoconf libtool
# apt-get install autoconf libtool
Then, you can build and install protobuf 3.0.0:
If you want to run the tests using one of the sanitized configurations, you
will need clang and its instrumented libc++:
$ cd third_party/protobuf
$ ./autogen.sh
$ ./configure
$ make
# make install
# ldconfig
# apt-get install clang libc++-dev
A word on OpenSSL

8370
Makefile

File diff suppressed because one or more lines are too long

@ -292,6 +292,9 @@
"src": [
"test/core/util/test_config.c"
],
"deps": [
"gpr"
],
"vs_project_guid": "{EAB0A629-17A9-44DB-B5FF-E91A721FE037}"
},
{
@ -370,6 +373,10 @@
"test/core/util/port_posix.c",
"test/core/util/slice_splitter.c"
],
"deps": [
"gpr",
"grpc"
],
"vs_project_guid": "{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}"
},
{
@ -455,15 +462,15 @@
]
},
{
"name": "tips_client_lib",
"name": "pubsub_client_lib",
"build": "private",
"language": "c++",
"src": [
"examples/tips/label.proto",
"examples/tips/empty.proto",
"examples/tips/pubsub.proto",
"examples/tips/publisher.cc",
"examples/tips/subscriber.cc"
"examples/pubsub/label.proto",
"examples/pubsub/empty.proto",
"examples/pubsub/pubsub.proto",
"examples/pubsub/publisher.cc",
"examples/pubsub/subscriber.cc"
],
"deps": [
"grpc++",
@ -1524,6 +1531,22 @@
"gpr"
]
},
{
"name": "async_end2end_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/end2end/async_end2end_test.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "channel_arguments_test",
"build": "test",
@ -1622,15 +1645,15 @@
]
},
{
"name": "qps_client",
"name": "pubsub_client",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/client.cc"
"examples/pubsub/main.cc"
],
"deps": [
"pubsub_client_lib",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
@ -1640,15 +1663,14 @@
]
},
{
"name": "qps_server",
"name": "pubsub_publisher_test",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/server.cc"
"examples/pubsub/publisher_test.cc"
],
"deps": [
"pubsub_client_lib",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
@ -1658,30 +1680,15 @@
]
},
{
"name": "ruby_plugin",
"build": "protoc",
"language": "c++",
"headers": [
"src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers-inl.h",
"src/compiler/cpp_generator_map-inl.h",
"src/compiler/cpp_generator_string-inl.h"
],
"src": [
"src/compiler/ruby_generator.cc",
"src/compiler/ruby_plugin.cc"
],
"deps": [],
"secure": false
},
{
"name": "status_test",
"name": "pubsub_subscriber_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/util/status_test.cc"
"examples/pubsub/subscriber_test.cc"
],
"deps": [
"pubsub_client_lib",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
@ -1690,13 +1697,16 @@
]
},
{
"name": "thread_pool_test",
"name": "qps_client",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/server/thread_pool_test.cc"
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/client.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
@ -1705,15 +1715,15 @@
]
},
{
"name": "tips_client",
"name": "qps_server",
"build": "test",
"run": false,
"language": "c++",
"src": [
"examples/tips/main.cc"
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/server.cc"
],
"deps": [
"tips_client_lib",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
@ -1723,15 +1733,30 @@
]
},
{
"name": "tips_publisher_test",
"name": "ruby_plugin",
"build": "protoc",
"language": "c++",
"headers": [
"src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers-inl.h",
"src/compiler/cpp_generator_map-inl.h",
"src/compiler/cpp_generator_string-inl.h"
],
"src": [
"src/compiler/ruby_generator.cc",
"src/compiler/ruby_plugin.cc"
],
"deps": [],
"secure": false
},
{
"name": "status_test",
"build": "test",
"language": "c++",
"src": [
"examples/tips/publisher_test.cc"
"test/cpp/util/status_test.cc"
],
"deps": [
"tips_client_lib",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
@ -1740,15 +1765,13 @@
]
},
{
"name": "tips_subscriber_test",
"name": "thread_pool_test",
"build": "test",
"language": "c++",
"src": [
"examples/tips/subscriber_test.cc"
"test/cpp/server/thread_pool_test.cc"
],
"deps": [
"tips_client_lib",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",

@ -1,4 +1,4 @@
C++ Client implementation for Cloud Pub/Sub service (TIPS)
C++ Client implementation for Cloud Pub/Sub service
(https://developers.google.com/apis-explorer/#p/pubsub/v1beta1/).
"Google Cloud Pub/Sub" API needs to be enabled at
@ -11,16 +11,20 @@ be created with scope "https://www.googleapis.com/auth/cloud-platform" as below:
gcloud compute instances create instance-name
--image debian-7 --scopes https://www.googleapis.com/auth/cloud-platform
Google TLS cert is required to run the client, which can be downloaded from
Chrome browser.
To run the client from GCE:
make tips_client
bins/opt/tips_client --project_id="your project id"
make pubsub_client
GRPC_DEFAULT_SSL_ROOTS_FILE_PATH="Google TLS cert" bins/opt/pubsub_client
--project_id="your project id"
A service account credential is required to run the client from other
environments, which can be generated as a JSON key file from
https://console.developers.google.com/project/. To run the client with a service
account credential:
bins/opt/tips_client
GRPC_DEFAULT_SSL_ROOTS_FILE_PATH="Google TLS cert" bins/opt/pubsub_client
--project_id="your project id"
--service_account_key_file="absolute path to the JSON key file"

@ -46,8 +46,8 @@
#include <grpc++/credentials.h>
#include <grpc++/status.h>
#include "examples/tips/publisher.h"
#include "examples/tips/subscriber.h"
#include "examples/pubsub/publisher.h"
#include "examples/pubsub/subscriber.h"
#include "test/cpp/util/create_test_channel.h"
DEFINE_int32(server_port, 443, "Server port.");
@ -82,7 +82,7 @@ grpc::string GetServiceAccountJsonKey() {
int main(int argc, char** argv) {
grpc_init();
google::ParseCommandLineFlags(&argc, &argv, true);
gpr_log(GPR_INFO, "Start TIPS client");
gpr_log(GPR_INFO, "Start PUBSUB client");
std::ostringstream ss;
@ -104,8 +104,8 @@ int main(int argc, char** argv) {
true, // use prod roots
creds));
grpc::examples::tips::Publisher publisher(channel);
grpc::examples::tips::Subscriber subscriber(channel);
grpc::examples::pubsub::Publisher publisher(channel);
grpc::examples::pubsub::Subscriber subscriber(channel);
GPR_ASSERT(FLAGS_project_id != "");
ss.str("");

@ -35,7 +35,7 @@
#include <grpc++/client_context.h>
#include "examples/tips/publisher.h"
#include "examples/pubsub/publisher.h"
using tech::pubsub::Topic;
using tech::pubsub::DeleteTopicRequest;
@ -48,7 +48,7 @@ using tech::pubsub::PubsubMessage;
namespace grpc {
namespace examples {
namespace tips {
namespace pubsub {
Publisher::Publisher(std::shared_ptr<ChannelInterface> channel)
: stub_(PublisherService::NewStub(channel)) {
@ -119,6 +119,6 @@ Status Publisher::Publish(const grpc::string& topic, const grpc::string& data) {
return stub_->Publish(&context, request, &response);
}
} // namespace tips
} // namespace pubsub
} // namespace examples
} // namespace grpc

@ -31,17 +31,17 @@
*
*/
#ifndef __GRPCPP_EXAMPLES_TIPS_PUBLISHER_H_
#define __GRPCPP_EXAMPLES_TIPS_PUBLISHER_H_
#ifndef __GRPCPP_EXAMPLES_PUBSUB_PUBLISHER_H_
#define __GRPCPP_EXAMPLES_PUBSUB_PUBLISHER_H_
#include <grpc++/channel_interface.h>
#include <grpc++/status.h>
#include "examples/tips/pubsub.pb.h"
#include "examples/pubsub/pubsub.pb.h"
namespace grpc {
namespace examples {
namespace tips {
namespace pubsub {
class Publisher {
public:
@ -60,8 +60,8 @@ class Publisher {
std::unique_ptr<tech::pubsub::PublisherService::Stub> stub_;
};
} // namespace tips
} // namespace pubsub
} // namespace examples
} // namespace grpc
#endif // __GRPCPP_EXAMPLES_TIPS_PUBLISHER_H_
#endif // __GRPCPP_EXAMPLES_PUBSUB_PUBLISHER_H_

@ -43,7 +43,7 @@
#include <grpc++/status.h>
#include <gtest/gtest.h>
#include "examples/tips/publisher.h"
#include "examples/pubsub/publisher.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
@ -112,7 +112,7 @@ class PublisherTest : public ::testing::Test {
channel_ = CreateChannel(server_address_.str(), ChannelArguments());
publisher_.reset(new grpc::examples::tips::Publisher(channel_));
publisher_.reset(new grpc::examples::pubsub::Publisher(channel_));
}
void TearDown() override {
@ -126,7 +126,7 @@ class PublisherTest : public ::testing::Test {
std::shared_ptr<ChannelInterface> channel_;
std::unique_ptr<grpc::examples::tips::Publisher> publisher_;
std::unique_ptr<grpc::examples::pubsub::Publisher> publisher_;
};
TEST_F(PublisherTest, TestPublisher) {

@ -4,8 +4,8 @@
syntax = "proto2";
import "examples/tips/empty.proto";
import "examples/tips/label.proto";
import "examples/pubsub/empty.proto";
import "examples/pubsub/label.proto";
package tech.pubsub;

@ -33,7 +33,7 @@
#include <grpc++/client_context.h>
#include "examples/tips/subscriber.h"
#include "examples/pubsub/subscriber.h"
using tech::pubsub::Topic;
using tech::pubsub::DeleteTopicRequest;
@ -46,7 +46,7 @@ using tech::pubsub::PubsubMessage;
namespace grpc {
namespace examples {
namespace tips {
namespace pubsub {
Subscriber::Subscriber(std::shared_ptr<ChannelInterface> channel)
: stub_(SubscriberService::NewStub(channel)) {
@ -113,6 +113,6 @@ Status Subscriber::Pull(const grpc::string& name, grpc::string* data) {
return s;
}
} // namespace tips
} // namespace pubsub
} // namespace examples
} // namespace grpc

@ -31,17 +31,17 @@
*
*/
#ifndef __GRPCPP_EXAMPLES_TIPS_SUBSCRIBER_H_
#define __GRPCPP_EXAMPLES_TIPS_SUBSCRIBER_H_
#ifndef __GRPCPP_EXAMPLES_PUBSUB_SUBSCRIBER_H_
#define __GRPCPP_EXAMPLES_PUBSUB_SUBSCRIBER_H_
#include <grpc++/channel_interface.h>
#include <grpc++/status.h>
#include "examples/tips/pubsub.pb.h"
#include "examples/pubsub/pubsub.pb.h"
namespace grpc {
namespace examples {
namespace tips {
namespace pubsub {
class Subscriber {
public:
@ -61,8 +61,8 @@ class Subscriber {
std::unique_ptr<tech::pubsub::SubscriberService::Stub> stub_;
};
} // namespace tips
} // namespace pubsub
} // namespace examples
} // namespace grpc
#endif // __GRPCPP_EXAMPLES_TIPS_SUBSCRIBER_H_
#endif // __GRPCPP_EXAMPLES_PUBSUB_SUBSCRIBER_H_

@ -43,7 +43,7 @@
#include <grpc++/status.h>
#include <gtest/gtest.h>
#include "examples/tips/subscriber.h"
#include "examples/pubsub/subscriber.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
@ -111,7 +111,7 @@ class SubscriberTest : public ::testing::Test {
channel_ = CreateChannel(server_address_.str(), ChannelArguments());
subscriber_.reset(new grpc::examples::tips::Subscriber(channel_));
subscriber_.reset(new grpc::examples::pubsub::Subscriber(channel_));
}
void TearDown() override {
@ -125,7 +125,7 @@ class SubscriberTest : public ::testing::Test {
std::shared_ptr<ChannelInterface> channel_;
std::unique_ptr<grpc::examples::tips::Subscriber> subscriber_;
std::unique_ptr<grpc::examples::pubsub::Subscriber> subscriber_;
};
TEST_F(SubscriberTest, TestSubscriber) {

@ -47,15 +47,31 @@ using std::chrono::system_clock;
struct grpc_call;
struct grpc_completion_queue;
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
namespace grpc {
class CallOpBuffer;
template <class R> class ClientReader;
template <class W> class ClientWriter;
template <class R, class W> class ClientReaderWriter;
template <class R> class ClientAsyncReader;
template <class W> class ClientAsyncWriter;
template <class R, class W> class ClientAsyncReaderWriter;
class ChannelInterface;
class CompletionQueue;
class RpcMethod;
class Status;
template <class R>
class ClientReader;
template <class W>
class ClientWriter;
template <class R, class W>
class ClientReaderWriter;
template <class R>
class ClientAsyncReader;
template <class W>
class ClientAsyncWriter;
template <class R, class W>
class ClientAsyncReaderWriter;
class ClientContext {
public:
@ -65,10 +81,20 @@ class ClientContext {
void AddMetadata(const grpc::string &meta_key,
const grpc::string &meta_value);
std::multimap<grpc::string, grpc::string> GetServerInitialMetadata() {
GPR_ASSERT(initial_metadata_received_);
return recv_initial_metadata_;
}
std::multimap<grpc::string, grpc::string> GetServerTrailingMetadata() {
// TODO(yangg) check finished
return trailing_metadata_;
}
void set_absolute_deadline(const system_clock::time_point &deadline);
system_clock::time_point absolute_deadline();
void StartCancel();
void TryCancel();
private:
// Disallow copy and assign.
@ -77,12 +103,28 @@ class ClientContext {
friend class CallOpBuffer;
friend class Channel;
template <class R> friend class ::grpc::ClientReader;
template <class W> friend class ::grpc::ClientWriter;
template <class R, class W> friend class ::grpc::ClientReaderWriter;
template <class R> friend class ::grpc::ClientAsyncReader;
template <class W> friend class ::grpc::ClientAsyncWriter;
template <class R, class W> friend class ::grpc::ClientAsyncReaderWriter;
template <class R>
friend class ::grpc::ClientReader;
template <class W>
friend class ::grpc::ClientWriter;
template <class R, class W>
friend class ::grpc::ClientReaderWriter;
template <class R>
friend class ::grpc::ClientAsyncReader;
template <class W>
friend class ::grpc::ClientAsyncWriter;
template <class R, class W>
friend class ::grpc::ClientAsyncReaderWriter;
friend Status BlockingUnaryCall(ChannelInterface *channel,
const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result);
friend void AsyncUnaryCall(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result, Status *status,
CompletionQueue *cq, void *tag);
grpc_call *call() { return call_; }
void set_call(grpc_call *call) {

@ -58,6 +58,7 @@ class Server;
class CompletionQueueTag {
public:
virtual ~CompletionQueueTag() {}
// Called prior to returning from Next(), return value
// is the status of the operation (return status is the default thing
// to do)
@ -80,24 +81,31 @@ class CompletionQueue {
// destructed when false is returned from Next().
void Shutdown();
grpc_completion_queue* cq() { return cq_; }
grpc_completion_queue *cq() { return cq_; }
private:
template <class R> friend class ::grpc::ClientReader;
template <class W> friend class ::grpc::ClientWriter;
template <class R, class W> friend class ::grpc::ClientReaderWriter;
template <class R> friend class ::grpc::ServerReader;
template <class W> friend class ::grpc::ServerWriter;
template <class R, class W> friend class ::grpc::ServerReaderWriter;
template <class R>
friend class ::grpc::ClientReader;
template <class W>
friend class ::grpc::ClientWriter;
template <class R, class W>
friend class ::grpc::ClientReaderWriter;
template <class R>
friend class ::grpc::ServerReader;
template <class W>
friend class ::grpc::ServerWriter;
template <class R, class W>
friend class ::grpc::ServerReaderWriter;
friend class ::grpc::Server;
friend Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result);
friend Status BlockingUnaryCall(ChannelInterface *channel,
const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result);
bool Pluck(CompletionQueueTag *tag);
grpc_completion_queue* cq_; // owned
grpc_completion_queue *cq_; // owned
};
} // namespace grpc

@ -40,6 +40,6 @@ namespace grpc {
typedef std::string string;
} // namespace grpc
} // namespace grpc
#endif // __GRPCPP_CONFIG_H__

@ -54,7 +54,7 @@ namespace grpc {
class Call;
class CallOpBuffer final : public CompletionQueueTag {
class CallOpBuffer : public CompletionQueueTag {
public:
CallOpBuffer() : return_tag_(this) {}
~CallOpBuffer();
@ -68,13 +68,13 @@ class CallOpBuffer final : public CompletionQueueTag {
void AddRecvInitialMetadata(
std::multimap<grpc::string, grpc::string> *metadata);
void AddSendMessage(const google::protobuf::Message &message);
void AddRecvMessage(google::protobuf::Message *message, bool* got_message);
void AddRecvMessage(google::protobuf::Message *message);
void AddClientSendClose();
void AddClientRecvStatus(std::multimap<grpc::string, grpc::string> *metadata,
Status *status);
void AddServerSendStatus(std::multimap<grpc::string, grpc::string> *metadata,
const Status& status);
void AddServerRecvClose(bool* cancelled);
const Status &status);
void AddServerRecvClose(bool *cancelled);
// INTERNAL API:
@ -84,33 +84,34 @@ class CallOpBuffer final : public CompletionQueueTag {
// Called by completion queue just prior to returning from Next() or Pluck()
void FinalizeResult(void **tag, bool *status) override;
bool got_message = false;
private:
void *return_tag_ = nullptr;
// Send initial metadata
bool send_initial_metadata_ = false;
size_t initial_metadata_count_ = 0;
grpc_metadata* initial_metadata_ = nullptr;
grpc_metadata *initial_metadata_ = nullptr;
// Recv initial metadta
std::multimap<grpc::string, grpc::string>* recv_initial_metadata_ = nullptr;
std::multimap<grpc::string, grpc::string> *recv_initial_metadata_ = nullptr;
grpc_metadata_array recv_initial_metadata_arr_ = {0, 0, nullptr};
// Send message
const google::protobuf::Message* send_message_ = nullptr;
grpc_byte_buffer* send_message_buf_ = nullptr;
const google::protobuf::Message *send_message_ = nullptr;
grpc_byte_buffer *send_message_buf_ = nullptr;
// Recv message
google::protobuf::Message* recv_message_ = nullptr;
bool* got_message_ = nullptr;
grpc_byte_buffer* recv_message_buf_ = nullptr;
google::protobuf::Message *recv_message_ = nullptr;
grpc_byte_buffer *recv_message_buf_ = nullptr;
// Client send close
bool client_send_close_ = false;
// Client recv status
std::multimap<grpc::string, grpc::string>* recv_trailing_metadata_ = nullptr;
Status* recv_status_ = nullptr;
std::multimap<grpc::string, grpc::string> *recv_trailing_metadata_ = nullptr;
Status *recv_status_ = nullptr;
grpc_metadata_array recv_trailing_metadata_arr_ = {0, 0, nullptr};
grpc_status_code status_code_ = GRPC_STATUS_OK;
char *status_details_ = nullptr;
size_t status_details_capacity_ = 0;
// Server send status
const Status* send_status_ = nullptr;
const Status *send_status_ = nullptr;
size_t trailing_metadata_count_ = 0;
grpc_metadata *trailing_metadata_ = nullptr;
int cancelled_buf_;
@ -138,7 +139,7 @@ class Call final {
private:
CallHook *call_hook_;
CompletionQueue *cq_;
grpc_call* call_;
grpc_call *call_;
};
} // namespace grpc

@ -61,7 +61,6 @@ Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
const google::protobuf::Message &request,
google::protobuf::Message *result);
} // namespace grpc
} // namespace grpc
#endif

@ -55,14 +55,10 @@ class MethodHandler {
public:
virtual ~MethodHandler() {}
struct HandlerParameter {
HandlerParameter(Call *c,
ServerContext* context,
HandlerParameter(Call* c, ServerContext* context,
const google::protobuf::Message* req,
google::protobuf::Message* resp)
: call(c),
server_context(context),
request(req),
response(resp) {}
: call(c), server_context(context), request(req), response(resp) {}
Call* call;
ServerContext* server_context;
const google::protobuf::Message* request;
@ -152,7 +148,8 @@ class BidiStreamingHandler : public MethodHandler {
: func_(func), service_(service) {}
Status RunHandler(const HandlerParameter& param) final {
ServerReaderWriter<ResponseType, RequestType> stream(param.call, param.server_context);
ServerReaderWriter<ResponseType, RequestType> stream(param.call,
param.server_context);
return func_(service_, param.server_context, &stream);
}
@ -195,9 +192,7 @@ class RpcServiceMethod : public RpcMethod {
class RpcService {
public:
// Takes ownership.
void AddMethod(RpcServiceMethod* method) {
methods_.emplace_back(method);
}
void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); }
RpcServiceMethod* GetMethod(int i) { return methods_[i].get(); }
int GetMethodCount() const { return methods_.size(); }

@ -59,7 +59,6 @@ class ServerAsyncStreamingInterface {
virtual ~ServerAsyncStreamingInterface() {}
virtual void SendInitialMetadata(void* tag) = 0;
virtual void Finish(const Status& status, void* tag) = 0;
private:
friend class Server;
@ -82,7 +81,7 @@ class AsynchronousService {
size_t method_count)
: cq_(cq), method_names_(method_names), method_count_(method_count) {}
~AsynchronousService();
~AsynchronousService() { delete[] request_args_; }
CompletionQueue* completion_queue() const { return cq_; }
@ -125,4 +124,4 @@ class AsynchronousService {
} // namespace grpc
#endif // __GRPCPP_IMPL_SERVICE_TYPE_H__
#endif // __GRPCPP_IMPL_SERVICE_TYPE_H__

@ -96,9 +96,9 @@ class Server final : private CallHook,
// DispatchImpl
void RequestAsyncCall(void* registered_method, ServerContext* context,
::google::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag);
::google::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag);
// Completion queue.
CompletionQueue cq_;

@ -45,10 +45,12 @@ struct grpc_call;
namespace grpc {
template <class R>
template <class W, class R>
class ServerAsyncReader;
template <class W>
class ServerAsyncWriter;
template <class W>
class ServerAsyncResponseWriter;
template <class R, class W>
class ServerAsyncReaderWriter;
template <class R>
@ -74,12 +76,18 @@ class ServerContext final {
void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
std::multimap<grpc::string, grpc::string> client_metadata() {
return client_metadata_;
}
private:
friend class ::grpc::Server;
template <class R>
template <class W, class R>
friend class ::grpc::ServerAsyncReader;
template <class W>
friend class ::grpc::ServerAsyncWriter;
template <class W>
friend class ::grpc::ServerAsyncResponseWriter;
template <class R, class W>
friend class ::grpc::ServerAsyncReaderWriter;
template <class R>

@ -87,9 +87,8 @@ class ClientReader final : public ClientStreamingInterface,
public ReaderInterface<R> {
public:
// Blocking create a stream and write the first request out.
ClientReader(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request)
ClientReader(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, const google::protobuf::Message& request)
: context_(context), call_(channel->CreateCall(method, context, &cq_)) {
CallOpBuffer buf;
buf.AddSendInitialMetadata(&context->send_initial_metadata_);
@ -113,16 +112,15 @@ class ClientReader final : public ClientStreamingInterface,
context_->initial_metadata_received_ = true;
}
virtual bool Read(R *msg) override {
virtual bool Read(R* msg) override {
CallOpBuffer buf;
if (!context_->initial_metadata_received_) {
buf.AddRecvInitialMetadata(&context_->recv_initial_metadata_);
context_->initial_metadata_received_ = true;
}
bool got_message;
buf.AddRecvMessage(msg, &got_message);
buf.AddRecvMessage(msg);
call_.PerformOps(&buf);
return cq_.Pluck(&buf) && got_message;
return cq_.Pluck(&buf) && buf.got_message;
}
virtual Status Finish() override {
@ -145,10 +143,10 @@ class ClientWriter final : public ClientStreamingInterface,
public WriterInterface<W> {
public:
// Blocking create a stream.
ClientWriter(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
google::protobuf::Message *response)
: context_(context), response_(response),
ClientWriter(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, google::protobuf::Message* response)
: context_(context),
response_(response),
call_(channel->CreateCall(method, context, &cq_)) {
CallOpBuffer buf;
buf.AddSendInitialMetadata(&context->send_initial_metadata_);
@ -174,17 +172,16 @@ class ClientWriter final : public ClientStreamingInterface,
virtual Status Finish() override {
CallOpBuffer buf;
Status status;
bool got_message;
buf.AddRecvMessage(response_, &got_message);
buf.AddRecvMessage(response_);
buf.AddClientRecvStatus(&context_->trailing_metadata_, &status);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf) && got_message);
GPR_ASSERT(cq_.Pluck(&buf) && buf.got_message);
return status;
}
private:
ClientContext* context_;
google::protobuf::Message *const response_;
google::protobuf::Message* const response_;
CompletionQueue cq_;
Call call_;
};
@ -196,8 +193,8 @@ class ClientReaderWriter final : public ClientStreamingInterface,
public ReaderInterface<R> {
public:
// Blocking create a stream.
ClientReaderWriter(ChannelInterface *channel,
const RpcMethod &method, ClientContext *context)
ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context)
: context_(context), call_(channel->CreateCall(method, context, &cq_)) {
CallOpBuffer buf;
buf.AddSendInitialMetadata(&context->send_initial_metadata_);
@ -219,16 +216,15 @@ class ClientReaderWriter final : public ClientStreamingInterface,
context_->initial_metadata_received_ = true;
}
virtual bool Read(R *msg) override {
virtual bool Read(R* msg) override {
CallOpBuffer buf;
if (!context_->initial_metadata_received_) {
buf.AddRecvInitialMetadata(&context_->recv_initial_metadata_);
context_->initial_metadata_received_ = true;
}
bool got_message;
buf.AddRecvMessage(msg, &got_message);
buf.AddRecvMessage(msg);
call_.PerformOps(&buf);
return cq_.Pluck(&buf) && got_message;
return cq_.Pluck(&buf) && buf.got_message;
}
virtual bool Write(const W& msg) override {
@ -277,10 +273,9 @@ class ServerReader final : public ReaderInterface<R> {
virtual bool Read(R* msg) override {
CallOpBuffer buf;
bool got_message;
buf.AddRecvMessage(msg, &got_message);
buf.AddRecvMessage(msg);
call_->PerformOps(&buf);
return call_->cq()->Pluck(&buf) && got_message;
return call_->cq()->Pluck(&buf) && buf.got_message;
}
private:
@ -322,7 +317,7 @@ class ServerWriter final : public WriterInterface<W> {
// Server-side interface for bi-directional streaming.
template <class W, class R>
class ServerReaderWriter final : public WriterInterface<W>,
public ReaderInterface<R> {
public ReaderInterface<R> {
public:
ServerReaderWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
@ -338,10 +333,9 @@ class ServerReaderWriter final : public WriterInterface<W>,
virtual bool Read(R* msg) override {
CallOpBuffer buf;
bool got_message;
buf.AddRecvMessage(msg, &got_message);
buf.AddRecvMessage(msg);
call_->PerformOps(&buf);
return call_->cq()->Pluck(&buf) && got_message;
return call_->cq()->Pluck(&buf) && buf.got_message;
}
virtual bool Write(const W& msg) override {
@ -391,12 +385,12 @@ class AsyncWriterInterface {
template <class R>
class ClientAsyncReader final : public ClientAsyncStreamingInterface,
public AsyncReaderInterface<R> {
public AsyncReaderInterface<R> {
public:
// Create a stream and write the first request out.
ClientAsyncReader(ChannelInterface *channel, CompletionQueue* cq,
const RpcMethod &method, ClientContext *context,
const google::protobuf::Message &request, void* tag)
ClientAsyncReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const google::protobuf::Message& request, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
@ -414,14 +408,13 @@ class ClientAsyncReader final : public ClientAsyncStreamingInterface,
context_->initial_metadata_received_ = true;
}
void Read(R *msg, void* tag) override {
void Read(R* msg, void* tag) override {
read_buf_.Reset(tag);
if (!context_->initial_metadata_received_) {
read_buf_.AddRecvInitialMetadata(&context_->recv_initial_metadata_);
context_->initial_metadata_received_ = true;
}
bool ignore;
read_buf_.AddRecvMessage(msg, &ignore);
read_buf_.AddRecvMessage(msg);
call_.PerformOps(&read_buf_);
}
@ -446,12 +439,13 @@ class ClientAsyncReader final : public ClientAsyncStreamingInterface,
template <class W>
class ClientAsyncWriter final : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public AsyncWriterInterface<W> {
public:
ClientAsyncWriter(ChannelInterface *channel, CompletionQueue* cq,
const RpcMethod &method, ClientContext *context,
google::protobuf::Message *response, void* tag)
: context_(context), response_(response),
ClientAsyncWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
google::protobuf::Message* response, void* tag)
: context_(context),
response_(response),
call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
@ -485,16 +479,14 @@ class ClientAsyncWriter final : public ClientAsyncStreamingInterface,
finish_buf_.AddRecvInitialMetadata(&context_->recv_initial_metadata_);
context_->initial_metadata_received_ = true;
}
bool ignore;
finish_buf_.AddRecvMessage(response_, &ignore);
finish_buf_.AddRecvMessage(response_);
finish_buf_.AddClientRecvStatus(&context_->trailing_metadata_, status);
call_.PerformOps(&finish_buf_);
}
private:
ClientContext* context_ = nullptr;
google::protobuf::Message *const response_;
bool got_message_;
google::protobuf::Message* const response_;
Call call_;
CallOpBuffer init_buf_;
CallOpBuffer meta_buf_;
@ -506,11 +498,12 @@ class ClientAsyncWriter final : public ClientAsyncStreamingInterface,
// Client-side interface for bi-directional streaming.
template <class W, class R>
class ClientAsyncReaderWriter final : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
ClientAsyncReaderWriter(ChannelInterface *channel, CompletionQueue* cq,
const RpcMethod &method, ClientContext *context, void* tag)
ClientAsyncReaderWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
@ -526,14 +519,13 @@ class ClientAsyncReaderWriter final : public ClientAsyncStreamingInterface,
context_->initial_metadata_received_ = true;
}
void Read(R *msg, void* tag) override {
void Read(R* msg, void* tag) override {
read_buf_.Reset(tag);
if (!context_->initial_metadata_received_) {
read_buf_.AddRecvInitialMetadata(&context_->recv_initial_metadata_);
context_->initial_metadata_received_ = true;
}
bool ignore;
read_buf_.AddRecvMessage(msg, &ignore);
read_buf_.AddRecvMessage(msg);
call_.PerformOps(&read_buf_);
}
@ -616,7 +608,7 @@ class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface {
}
private:
void BindCall(Call *call) override { call_ = *call; }
void BindCall(Call* call) override { call_ = *call; }
Call call_;
ServerContext* ctx_;
@ -624,7 +616,7 @@ class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface {
CallOpBuffer finish_buf_;
};
template <class R>
template <class W, class R>
class ServerAsyncReader : public ServerAsyncStreamingInterface,
public AsyncReaderInterface<R> {
public:
@ -646,21 +638,37 @@ class ServerAsyncReader : public ServerAsyncStreamingInterface,
call_.PerformOps(&read_buf_);
}
void Finish(const Status& status, void* tag) override {
void Finish(const W& msg, const Status& status, void* tag) {
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
if (status.IsOk()) {
finish_buf_.AddSendMessage(msg);
}
bool cancelled = false;
finish_buf_.AddServerRecvClose(&cancelled);
finish_buf_.AddServerSendStatus(&ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_buf_);
}
void FinishWithError(const Status& status, void* tag) {
GPR_ASSERT(!status.IsOk());
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
bool cancelled = false;
finish_buf_.AddServerRecvClose(&cancelled);
finish_buf_.AddServerSendStatus(&ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_buf_);
}
private:
void BindCall(Call *call) override { call_ = *call; }
void BindCall(Call* call) override { call_ = *call; }
Call call_;
ServerContext* ctx_;
@ -695,7 +703,7 @@ class ServerAsyncWriter : public ServerAsyncStreamingInterface,
call_.PerformOps(&write_buf_);
}
void Finish(const Status& status, void* tag) override {
void Finish(const Status& status, void* tag) {
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
@ -708,7 +716,7 @@ class ServerAsyncWriter : public ServerAsyncStreamingInterface,
}
private:
void BindCall(Call *call) override { call_ = *call; }
void BindCall(Call* call) override { call_ = *call; }
Call call_;
ServerContext* ctx_;
@ -751,7 +759,7 @@ class ServerAsyncReaderWriter : public ServerAsyncStreamingInterface,
call_.PerformOps(&write_buf_);
}
void Finish(const Status& status, void* tag) override {
void Finish(const Status& status, void* tag) {
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
@ -764,7 +772,7 @@ class ServerAsyncReaderWriter : public ServerAsyncStreamingInterface,
}
private:
void BindCall(Call *call) override { call_ = *call; }
void BindCall(Call* call) override { call_ = *call; }
Call call_;
ServerContext* ctx_;

@ -44,7 +44,7 @@
extern "C" {
#endif
/* Completion Channels enable notification of the completion of asynchronous
/* Completion Queues enable notification of the completion of asynchronous
actions. */
typedef struct grpc_completion_queue grpc_completion_queue;
@ -156,7 +156,8 @@ typedef enum grpc_op_error {
struct grpc_byte_buffer;
typedef struct grpc_byte_buffer grpc_byte_buffer;
/* Sample helpers to obtain byte buffers (these will certainly move place */
/* Sample helpers to obtain byte buffers (these will certainly move
someplace else) */
grpc_byte_buffer *grpc_byte_buffer_create(gpr_slice *slices, size_t nslices);
grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb);
size_t grpc_byte_buffer_length(grpc_byte_buffer *bb);
@ -351,12 +352,12 @@ typedef struct grpc_op {
/* Initialize the grpc library */
void grpc_init(void);
/* Shutdown the grpc library */
/* Shut down the grpc library */
void grpc_shutdown(void);
grpc_completion_queue *grpc_completion_queue_create(void);
/* Blocks until an event is available, the completion queue is being shutdown,
/* Blocks until an event is available, the completion queue is being shut down,
or deadline is reached. Returns NULL on timeout, otherwise the event that
occurred. Callers should call grpc_event_finish once they have processed
the event.
@ -376,7 +377,7 @@ grpc_event *grpc_completion_queue_next(grpc_completion_queue *cq,
grpc_event *grpc_completion_queue_pluck(grpc_completion_queue *cq, void *tag,
gpr_timespec deadline);
/* Cleanup any data owned by the event */
/* Clean up any data owned by the event */
void grpc_event_finish(grpc_event *event);
/* Begin destruction of a completion queue. Once all possible events are

@ -37,10 +37,6 @@
/* Override this file with one for your platform if you need to redefine
things. */
/* For a common case, assume that the platform has a C99-like stdint.h */
#include <stdint.h>
#if !defined(GPR_NO_AUTODETECT_PLATFORM)
#if defined(_WIN64) || defined(WIN64)
#define GPR_WIN32 1
@ -70,20 +66,40 @@
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
#elif defined(__linux__)
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <features.h>
#define GPR_CPU_LINUX 1
#define GPR_GCC_ATOMIC 1
#define GPR_LINUX 1
#define GPR_LINUX_MULTIPOLL_WITH_EPOLL 1
#define GPR_POSIX_WAKEUP_FD 1
#define GPR_LINUX_EVENTFD 1
#define GPR_POSIX_SOCKET 1
#define GPR_POSIX_SOCKETADDR 1
#ifdef __GLIBC_PREREQ
#if __GLIBC_PREREQ(2, 9)
#define GPR_LINUX_EVENTFD 1
#endif
#if __GLIBC_PREREQ(2, 10)
#define GPR_LINUX_SOCKETUTILS 1
#endif
#if __GLIBC_PREREQ(2, 17)
#define GPR_LINUX_ENV 1
#endif
#endif
#ifndef GPR_LINUX_EVENTFD
#define GPR_POSIX_NO_SPECIAL_WAKEUP_FD 1
#endif
#ifndef GPR_LINUX_SOCKETUTILS
#define GPR_POSIX_SOCKETUTILS
#endif
#ifndef GPR_LINUX_ENV
#define GPR_POSIX_ENV 1
#endif
@ -98,6 +114,9 @@
#define GPR_ARCH_32 1
#endif /* _LP64 */
#elif defined(__APPLE__)
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#define GPR_CPU_POSIX 1
#define GPR_GCC_ATOMIC 1
#define GPR_POSIX_LOG 1
@ -123,6 +142,10 @@
#endif
#endif /* GPR_NO_AUTODETECT_PLATFORM */
/* For a common case, assume that the platform has a C99-like stdint.h */
#include <stdint.h>
/* Cache line alignment */
#ifndef GPR_CACHELINE_SIZE
#if defined(__i386__) || defined(__x86_64__)

@ -133,7 +133,7 @@ std::string GetHeaderIncludes(const google::protobuf::FileDescriptor *file) {
temp.append("template <class OutMessage> class ClientWriter;\n");
temp.append("template <class InMessage> class ServerReader;\n");
temp.append("template <class OutMessage> class ClientAsyncWriter;\n");
temp.append("template <class InMessage> class ServerAsyncReader;\n");
temp.append("template <class OutMessage, class InMessage> class ServerAsyncReader;\n");
}
if (HasServerOnlyStreaming(file)) {
temp.append("template <class InMessage> class ClientReader;\n");
@ -197,10 +197,10 @@ void PrintHeaderClientMethod(google::protobuf::io::Printer *printer,
printer->Print(
*vars,
"::grpc::ClientReader< $Response$>* $Method$("
"::grpc::ClientContext* context, const $Request$* request);\n");
"::grpc::ClientContext* context, const $Request$& request);\n");
printer->Print(*vars,
"::grpc::ClientAsyncReader< $Response$>* $Method$("
"::grpc::ClientContext* context, const $Request$* request, "
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag);\n");
} else if (BidiStreaming(method)) {
printer->Print(*vars,
@ -267,7 +267,7 @@ void PrintHeaderServerMethodAsync(
printer->Print(*vars,
"void Request$Method$("
"::grpc::ServerContext* context, "
"::grpc::ServerAsyncReader< $Request$>* reader, "
"::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
"::grpc::CompletionQueue* cq, void *tag);\n");
} else if (ServerOnlyStreaming(method)) {
printer->Print(*vars,
@ -335,7 +335,7 @@ void PrintHeaderService(google::protobuf::io::Printer *printer,
printer->Indent();
(*vars)["MethodCount"] = as_string(service->method_count());
printer->Print("explicit AsyncService(::grpc::CompletionQueue* cq);\n");
printer->Print("~AsyncService();\n");
printer->Print("~AsyncService() {};\n");
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderServerMethodAsync(printer, service->method(i), vars);
}
@ -415,25 +415,25 @@ void PrintSourceClientMethod(google::protobuf::io::Printer *printer,
printer->Print(
*vars,
"::grpc::ClientReader< $Response$>* $Service$::Stub::$Method$("
"::grpc::ClientContext* context, const $Request$* request) {\n");
"::grpc::ClientContext* context, const $Request$& request) {\n");
printer->Print(*vars,
" return new ::grpc::ClientReader< $Response$>("
"channel(),"
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
"::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
"context, *request);\n"
"context, request);\n"
"}\n\n");
printer->Print(
*vars,
"::grpc::ClientAsyncReader< $Response$>* $Service$::Stub::$Method$("
"::grpc::ClientContext* context, const $Request$* request, "
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(*vars,
" return new ::grpc::ClientAsyncReader< $Response$>("
"channel(), cq, "
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
"::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
"context, *request, tag);\n"
"context, request, tag);\n"
"}\n\n");
} else if (BidiStreaming(method)) {
printer->Print(
@ -538,7 +538,7 @@ void PrintSourceServerAsyncMethod(
printer->Print(*vars,
"void $Service$::AsyncService::Request$Method$("
"::grpc::ServerContext* context, "
"::grpc::ServerAsyncReader< $Request$>* reader, "
"::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(
*vars,

@ -39,6 +39,7 @@
#include "src/core/iomgr/resolve_address.h"
#include <sys/types.h>
#include <sys/un.h>
#include <string.h>
#include "src/core/iomgr/iomgr_internal.h"
@ -123,6 +124,19 @@ grpc_resolved_addresses *grpc_blocking_resolve_address(
size_t i;
grpc_resolved_addresses *addrs = NULL;
const gpr_timespec start_time = gpr_now();
struct sockaddr_un *un;
if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' &&
name[4] == ':' && name[5] != 0) {
addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
addrs->naddrs = 1;
addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address));
un = (struct sockaddr_un *)addrs->addrs->addr;
un->sun_family = AF_UNIX;
strcpy(un->sun_path, name + 5);
addrs->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family);
return addrs;
}
/* parse name, splitting it into host and port parts */
split_host_port(name, &host, &port);

@ -166,6 +166,8 @@ int grpc_sockaddr_get_port(const struct sockaddr *addr) {
return ntohs(((struct sockaddr_in *)addr)->sin_port);
case AF_INET6:
return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
case AF_UNIX:
return 1;
default:
gpr_log(GPR_ERROR, "Unknown socket family %d in %s", addr->sa_family,
__FUNCTION__);

@ -31,12 +31,9 @@
*
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <grpc/support/port_platform.h>
#ifdef GPR_LINUX
#ifdef GPR_LINUX_SOCKETUTILS
#include "src/core/iomgr/socket_utils_posix.h"

@ -62,13 +62,13 @@ typedef struct {
int refs;
} async_connect;
static int prepare_socket(int fd) {
static int prepare_socket(const struct sockaddr *addr, int fd) {
if (fd < 0) {
goto error;
}
if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
!grpc_set_socket_low_latency(fd, 1)) {
(addr->sa_family != AF_UNIX && !grpc_set_socket_low_latency(fd, 1))) {
gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
strerror(errno));
goto error;
@ -200,7 +200,7 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
addr = (struct sockaddr *)&addr4_copy;
addr_len = sizeof(addr4_copy);
}
if (!prepare_socket(fd)) {
if (!prepare_socket(addr, fd)) {
cb(arg, NULL);
return;
}

@ -48,12 +48,14 @@
#include <netinet/tcp.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "src/core/iomgr/pollset_posix.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/iomgr/socket_utils_posix.h"
#include "src/core/iomgr/tcp_posix.h"
@ -73,6 +75,8 @@ typedef struct {
int fd;
grpc_fd *emfd;
grpc_tcp_server *server;
gpr_uint8 addr[GRPC_MAX_SOCKADDR_SIZE];
int addr_len;
} server_port;
/* the overall server */
@ -121,6 +125,10 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s) {
/* delete ALL the things */
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
if (((struct sockaddr *)sp->addr)->sa_family == AF_UNIX) {
struct sockaddr_un *un = (struct sockaddr_un *)sp->addr;
unlink(un->sun_path);
}
grpc_fd_orphan(sp->emfd, NULL, NULL);
}
gpr_free(s->ports);
@ -170,8 +178,8 @@ static int prepare_socket(int fd, const struct sockaddr *addr, int addr_len) {
}
if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
!grpc_set_socket_low_latency(fd, 1) ||
!grpc_set_socket_reuse_addr(fd, 1)) {
(addr->sa_family != AF_UNIX && (!grpc_set_socket_low_latency(fd, 1) ||
!grpc_set_socket_reuse_addr(fd, 1)))) {
gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
strerror(errno));
goto error;
@ -265,6 +273,8 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd,
sp->server = s;
sp->fd = fd;
sp->emfd = grpc_fd_create(fd);
memcpy(sp->addr, addr, addr_len);
sp->addr_len = addr_len;
GPR_ASSERT(sp->emfd);
gpr_mu_unlock(&s->mu);
}

@ -31,19 +31,6 @@
*
*/
/* Posix code for gpr fdopen and mkstemp support. */
#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 200112L
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
/* Don't know why I have to do this for mkstemp, looks like _POSIX_C_SOURCE
should be enough... */
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#include <grpc/support/port_platform.h>
#ifdef GPR_POSIX_FILE

@ -31,16 +31,6 @@
*
*/
#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 200112L
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
/* FIXME: "posix" files probably shouldn't depend on _GNU_SOURCE */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <grpc/support/port_platform.h>
#if defined(GPR_POSIX_LOG)

@ -31,13 +31,6 @@
*
*/
/* Posix code for gpr snprintf support. */
#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 200112L
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
#include <grpc/support/port_platform.h>
#ifdef GPR_POSIX_STRING

@ -31,13 +31,6 @@
*
*/
/* Posix gpr synchroization support code. */
#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 199309L
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199309L
#endif
#include <grpc/support/port_platform.h>
#ifdef GPR_POSIX_SYNC

@ -31,14 +31,6 @@
*
*/
/* Posix code for gpr time support. */
/* So we get nanosleep and clock_* */
#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 199309L
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199309L
#endif
#include <grpc/support/port_platform.h>
#ifdef GPR_POSIX_TIME
@ -70,7 +62,9 @@ gpr_timespec gpr_now(void) {
}
#else
/* For some reason Apple's OSes haven't implemented clock_gettime. */
/* TODO(klempner): Add special handling for Apple. */
#include <sys/time.h>
gpr_timespec gpr_now(void) {
gpr_timespec now;
struct timeval now_tv;

@ -708,6 +708,7 @@ grpc_transport_setup_result grpc_server_setup_transport(
gpr_uint32 slots;
gpr_uint32 probes;
gpr_uint32 max_probes = 0;
grpc_transport_setup_result result;
for (i = 0; i < s->channel_filter_count; i++) {
filters[i] = s->channel_filters[i];
@ -758,6 +759,9 @@ grpc_transport_setup_result grpc_server_setup_transport(
chand->registered_method_max_probes = max_probes;
}
result = grpc_connected_channel_bind_transport(
grpc_channel_get_channel_stack(channel), transport);
gpr_mu_lock(&s->mu);
chand->next = &s->root_channel_data;
chand->prev = chand->next->prev;
@ -766,8 +770,7 @@ grpc_transport_setup_result grpc_server_setup_transport(
gpr_free(filters);
return grpc_connected_channel_bind_transport(
grpc_channel_get_channel_stack(channel), transport);
return result;
}
static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,

@ -685,10 +685,11 @@ static void unlock(transport *t) {
int i;
pending_goaway *goaways = NULL;
grpc_endpoint *ep = t->ep;
grpc_stream_op_buffer nuke_now = t->nuke_later_sopb;
if (nuke_now.nops) {
memset(&t->nuke_later_sopb, 0, sizeof(t->nuke_later_sopb));
grpc_stream_op_buffer nuke_now;
grpc_sopb_init(&nuke_now);
if (t->nuke_later_sopb.nops) {
grpc_sopb_swap(&nuke_now, &t->nuke_later_sopb);
}
/* see if we need to trigger a write - and if so, get the data ready */
@ -758,9 +759,7 @@ static void unlock(transport *t) {
unref_transport(t);
}
if (nuke_now.nops) {
grpc_sopb_destroy(&nuke_now);
}
grpc_sopb_destroy(&nuke_now);
gpr_free(goaways);
}
@ -1701,13 +1700,10 @@ static grpc_stream_state compute_state(gpr_uint8 write_closed,
static int prepare_callbacks(transport *t) {
stream *s;
grpc_stream_op_buffer temp_sopb;
int n = 0;
while ((s = stream_list_remove_head(t, PENDING_CALLBACKS))) {
int execute = 1;
temp_sopb = s->parser.incoming_sopb;
s->parser.incoming_sopb = s->callback_sopb;
s->callback_sopb = temp_sopb;
grpc_sopb_swap(&s->parser.incoming_sopb, &s->callback_sopb);
s->callback_state = compute_state(s->sent_write_closed, s->read_closed);
if (s->callback_state == GRPC_STREAM_CLOSED) {

@ -38,23 +38,19 @@
#include <string.h>
/* Initial number of operations to allocate */
#define INITIAL_SLOTS 8
/* Exponential growth function: Given x, return a larger x.
Currently we grow by 1.5 times upon reallocation.
Assumes INITIAL_SLOTS > 1 */
Currently we grow by 1.5 times upon reallocation. */
#define GROW(x) (3 * (x) / 2)
void grpc_sopb_init(grpc_stream_op_buffer *sopb) {
sopb->ops = gpr_malloc(sizeof(grpc_stream_op) * INITIAL_SLOTS);
GPR_ASSERT(sopb->ops);
sopb->ops = sopb->inlined_ops;
sopb->nops = 0;
sopb->capacity = INITIAL_SLOTS;
sopb->capacity = GRPC_SOPB_INLINE_ELEMENTS;
}
void grpc_sopb_destroy(grpc_stream_op_buffer *sopb) {
grpc_stream_ops_unref_owned_objects(sopb->ops, sopb->nops);
gpr_free(sopb->ops);
if (sopb->ops != sopb->inlined_ops) gpr_free(sopb->ops);
}
void grpc_sopb_reset(grpc_stream_op_buffer *sopb) {
@ -62,6 +58,19 @@ void grpc_sopb_reset(grpc_stream_op_buffer *sopb) {
sopb->nops = 0;
}
void grpc_sopb_swap(grpc_stream_op_buffer *a, grpc_stream_op_buffer *b) {
grpc_stream_op_buffer temp = *a;
*a = *b;
*b = temp;
if (a->ops == b->inlined_ops) {
a->ops = a->inlined_ops;
}
if (b->ops == a->inlined_ops) {
b->ops = b->inlined_ops;
}
}
void grpc_stream_ops_unref_owned_objects(grpc_stream_op *ops, size_t nops) {
size_t i;
for (i = 0; i < nops; i++) {
@ -84,17 +93,21 @@ void grpc_stream_ops_unref_owned_objects(grpc_stream_op *ops, size_t nops) {
}
}
static void expand(grpc_stream_op_buffer *sopb) {
sopb->capacity = GROW(sopb->capacity);
sopb->ops = gpr_realloc(sopb->ops, sizeof(grpc_stream_op) * sopb->capacity);
GPR_ASSERT(sopb->ops);
static void expandto(grpc_stream_op_buffer *sopb, size_t new_capacity) {
sopb->capacity = new_capacity;
if (sopb->ops == sopb->inlined_ops) {
sopb->ops = gpr_malloc(sizeof(grpc_stream_op) * new_capacity);
memcpy(sopb->ops, sopb->inlined_ops, sopb->nops * sizeof(grpc_stream_op));
} else {
sopb->ops = gpr_realloc(sopb->ops, sizeof(grpc_stream_op) * new_capacity);
}
}
static grpc_stream_op *add(grpc_stream_op_buffer *sopb) {
grpc_stream_op *out;
if (sopb->nops == sopb->capacity) {
expand(sopb);
expandto(sopb, GROW(sopb->capacity));
}
out = sopb->ops + sopb->nops;
sopb->nops++;
@ -152,12 +165,7 @@ void grpc_sopb_append(grpc_stream_op_buffer *sopb, grpc_stream_op *ops,
size_t new_nops = orig_nops + nops;
if (new_nops > sopb->capacity) {
size_t new_capacity = GROW(sopb->capacity);
if (new_capacity < new_nops) {
new_capacity = new_nops;
}
sopb->ops = gpr_realloc(sopb->ops, sizeof(grpc_stream_op) * new_capacity);
sopb->capacity = new_capacity;
expandto(sopb, GPR_MAX(GROW(sopb->capacity), new_nops));
}
memcpy(sopb->ops + orig_nops, ops, sizeof(grpc_stream_op) * nops);

@ -40,6 +40,9 @@
#include <grpc/support/time.h>
#include "src/core/transport/metadata.h"
/* this many stream ops are inlined into a sopb before allocating */
#define GRPC_SOPB_INLINE_ELEMENTS 16
/* Operations that can be performed on a stream.
Used by grpc_stream_op. */
typedef enum grpc_stream_op_code {
@ -96,6 +99,7 @@ typedef struct grpc_stream_op_buffer {
grpc_stream_op *ops;
size_t nops;
size_t capacity;
grpc_stream_op inlined_ops[GRPC_SOPB_INLINE_ELEMENTS];
} grpc_stream_op_buffer;
/* Initialize a stream op buffer */
@ -104,6 +108,8 @@ void grpc_sopb_init(grpc_stream_op_buffer *sopb);
void grpc_sopb_destroy(grpc_stream_op_buffer *sopb);
/* Reset a sopb to no elements */
void grpc_sopb_reset(grpc_stream_op_buffer *sopb);
/* Swap two sopbs */
void grpc_sopb_swap(grpc_stream_op_buffer *a, grpc_stream_op_buffer *b);
void grpc_stream_ops_unref_owned_objects(grpc_stream_op *ops, size_t nops);

@ -93,8 +93,7 @@ void Channel::PerformOpsOnCall(CallOpBuffer *buf, Call *call) {
grpc_op ops[MAX_OPS];
buf->FillOps(ops, &nops);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_batch(call->call(), ops, nops,
buf));
grpc_call_start_batch(call->call(), ops, nops, buf));
}
} // namespace grpc

@ -59,8 +59,7 @@ class Channel final : public ChannelInterface {
virtual Call CreateCall(const RpcMethod &method, ClientContext *context,
CompletionQueue *cq) override;
virtual void PerformOpsOnCall(CallOpBuffer *ops,
Call *call) override;
virtual void PerformOpsOnCall(CallOpBuffer *ops, Call *call) override;
private:
const grpc::string target_;

@ -75,6 +75,10 @@ void ClientContext::AddMetadata(const grpc::string &meta_key,
send_initial_metadata_.insert(std::make_pair(meta_key, meta_value));
}
void ClientContext::StartCancel() {}
void ClientContext::TryCancel() {
if (call_) {
grpc_call_cancel(call_);
}
}
} // namespace grpc

@ -34,6 +34,7 @@
#include <grpc++/impl/client_unary_call.h>
#include <grpc++/impl/call.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/completion_queue.h>
#include <grpc++/status.h>
#include <grpc/support/log.h>
@ -51,20 +52,38 @@ Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
Status status;
buf.AddSendInitialMetadata(context);
buf.AddSendMessage(request);
bool got_message;
buf.AddRecvMessage(result, &got_message);
buf.AddRecvInitialMetadata(&context->recv_initial_metadata_);
buf.AddRecvMessage(result);
buf.AddClientSendClose();
buf.AddClientRecvStatus(nullptr, &status); // TODO metadata
buf.AddClientRecvStatus(&context->trailing_metadata_, &status);
call.PerformOps(&buf);
GPR_ASSERT(cq.Pluck(&buf) && (got_message || !status.IsOk()));
GPR_ASSERT(cq.Pluck(&buf) && (buf.got_message || !status.IsOk()));
return status;
}
class ClientAsyncRequest final : public CallOpBuffer {
public:
void FinalizeResult(void **tag, bool *status) override {
CallOpBuffer::FinalizeResult(tag, status);
delete this;
}
};
void AsyncUnaryCall(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result, Status *status,
CompletionQueue *cq, void *tag) {
ClientAsyncRequest *buf = new ClientAsyncRequest;
buf->Reset(tag);
Call call(channel->CreateCall(method, context, cq));
buf->AddSendInitialMetadata(context);
buf->AddSendMessage(request);
buf->AddRecvInitialMetadata(&context->recv_initial_metadata_);
buf->AddRecvMessage(result);
buf->AddClientSendClose();
buf->AddClientRecvStatus(&context->trailing_metadata_, status);
call.PerformOps(buf);
}
} // namespace grpc

@ -57,7 +57,7 @@ void CallOpBuffer::Reset(void* next_return_tag) {
}
recv_message_ = nullptr;
got_message_ = nullptr;
got_message = false;
if (recv_message_buf_) {
grpc_byte_buffer_destroy(recv_message_buf_);
recv_message_buf_ = nullptr;
@ -95,13 +95,13 @@ namespace {
// mess. Make sure it does not happen.
grpc_metadata* FillMetadataArray(
std::multimap<grpc::string, grpc::string>* metadata) {
if (metadata->empty()) { return nullptr; }
grpc_metadata* metadata_array = (grpc_metadata*)gpr_malloc(
metadata->size()* sizeof(grpc_metadata));
if (metadata->empty()) {
return nullptr;
}
grpc_metadata* metadata_array =
(grpc_metadata*)gpr_malloc(metadata->size() * sizeof(grpc_metadata));
size_t i = 0;
for (auto iter = metadata->cbegin();
iter != metadata->cend();
++iter, ++i) {
for (auto iter = metadata->cbegin(); iter != metadata->cend(); ++iter, ++i) {
metadata_array[i].key = iter->first.c_str();
metadata_array[i].value = iter->second.c_str();
metadata_array[i].value_length = iter->second.size();
@ -114,7 +114,8 @@ void FillMetadataMap(grpc_metadata_array* arr,
for (size_t i = 0; i < arr->count; i++) {
// TODO(yangg) handle duplicates?
metadata->insert(std::pair<grpc::string, grpc::string>(
arr->metadata[i].key, {arr->metadata[i].value, arr->metadata[i].value_length}));
arr->metadata[i].key,
{arr->metadata[i].value, arr->metadata[i].value_length}));
}
grpc_metadata_array_destroy(arr);
grpc_metadata_array_init(arr);
@ -133,8 +134,7 @@ void CallOpBuffer::AddRecvInitialMetadata(
recv_initial_metadata_ = metadata;
}
void CallOpBuffer::AddSendInitialMetadata(ClientContext *ctx) {
void CallOpBuffer::AddSendInitialMetadata(ClientContext* ctx) {
AddSendInitialMetadata(&ctx->send_initial_metadata_);
}
@ -142,21 +142,18 @@ void CallOpBuffer::AddSendMessage(const google::protobuf::Message& message) {
send_message_ = &message;
}
void CallOpBuffer::AddRecvMessage(google::protobuf::Message *message, bool* got_message) {
void CallOpBuffer::AddRecvMessage(google::protobuf::Message* message) {
recv_message_ = message;
got_message_ = got_message;
}
void CallOpBuffer::AddClientSendClose() {
client_send_close_ = true;
}
void CallOpBuffer::AddClientSendClose() { client_send_close_ = true; }
void CallOpBuffer::AddServerRecvClose(bool* cancelled) {
recv_closed_ = cancelled;
}
void CallOpBuffer::AddClientRecvStatus(
std::multimap<grpc::string, grpc::string>* metadata, Status *status) {
std::multimap<grpc::string, grpc::string>* metadata, Status* status) {
recv_trailing_metadata_ = metadata;
recv_status_ = status;
}
@ -172,7 +169,7 @@ void CallOpBuffer::AddServerSendStatus(
send_status_ = &status;
}
void CallOpBuffer::FillOps(grpc_op *ops, size_t *nops) {
void CallOpBuffer::FillOps(grpc_op* ops, size_t* nops) {
*nops = 0;
if (send_initial_metadata_) {
ops[*nops].op = GRPC_OP_SEND_INITIAL_METADATA;
@ -233,7 +230,7 @@ void CallOpBuffer::FillOps(grpc_op *ops, size_t *nops) {
}
}
void CallOpBuffer::FinalizeResult(void **tag, bool *status) {
void CallOpBuffer::FinalizeResult(void** tag, bool* status) {
// Release send buffers.
if (send_message_buf_) {
grpc_byte_buffer_destroy(send_message_buf_);
@ -256,12 +253,14 @@ void CallOpBuffer::FinalizeResult(void **tag, bool *status) {
// Parse received message if any.
if (recv_message_) {
if (recv_message_buf_) {
*got_message_ = true;
got_message = true;
*status = DeserializeProto(recv_message_buf_, recv_message_);
grpc_byte_buffer_destroy(recv_message_buf_);
recv_message_buf_ = nullptr;
} else {
*got_message_ = false;
// Read failed
got_message = false;
*status = false;
}
}
// Parse received status.
@ -269,15 +268,14 @@ void CallOpBuffer::FinalizeResult(void **tag, bool *status) {
FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_);
*recv_status_ = Status(
static_cast<StatusCode>(status_code_),
status_details_ ? grpc::string(status_details_)
: grpc::string());
status_details_ ? grpc::string(status_details_) : grpc::string());
}
if (recv_closed_) {
*recv_closed_ = cancelled_buf_ != 0;
}
}
Call::Call(grpc_call* call, CallHook *call_hook, CompletionQueue* cq)
Call::Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
: call_hook_(call_hook), cq_(cq), call_(call) {}
void Call::PerformOps(CallOpBuffer* buffer) {

@ -52,7 +52,9 @@ void CompletionQueue::Shutdown() { grpc_completion_queue_shutdown(cq_); }
// Helper class so we can declare a unique_ptr with grpc_event
class EventDeleter {
public:
void operator()(grpc_event *ev) { if (ev) grpc_event_finish(ev); }
void operator()(grpc_event *ev) {
if (ev) grpc_event_finish(ev);
}
};
bool CompletionQueue::Next(void **tag, bool *ok) {

@ -54,8 +54,8 @@ AsyncServerContext::~AsyncServerContext() { grpc_call_destroy(call_); }
void AsyncServerContext::Accept(grpc_completion_queue *cq) {
GPR_ASSERT(grpc_call_server_accept_old(call_, cq, this) == GRPC_CALL_OK);
GPR_ASSERT(grpc_call_server_end_initial_metadata_old(call_, GRPC_WRITE_BUFFER_HINT) ==
GRPC_CALL_OK);
GPR_ASSERT(grpc_call_server_end_initial_metadata_old(
call_, GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK);
}
bool AsyncServerContext::StartRead(google::protobuf::Message *request) {

@ -38,6 +38,8 @@
namespace grpc {
ServerContext::ServerContext() {}
ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata *metadata,
size_t metadata_count)
: deadline_(Timespec2Timepoint(deadline)) {

@ -1,3 +1,36 @@
#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;

@ -1,3 +1,36 @@
#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;
using System.Threading.Tasks;

@ -1,3 +1,36 @@
#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;
using System.Threading.Tasks;

@ -1,3 +1,36 @@
#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 NUnit.Framework;
using Google.GRPC.Core;
@ -13,7 +46,7 @@ namespace math.Tests
/// </summary>
public class MathClientServerTest
{
string serverAddr = "localhost:" + PortPicker.PickUnusedPort();
string host = "localhost";
Server server;
Channel channel;
MathGrpc.IMathServiceClient client;
@ -21,11 +54,13 @@ namespace math.Tests
[TestFixtureSetUp]
public void Init()
{
GrpcEnvironment.Initialize();
server = new Server();
server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl()));
server.AddPort(serverAddr);
int port = server.AddPort(host + ":0");
server.Start();
channel = new Channel(serverAddr);
channel = new Channel(host + ":" + port);
client = MathGrpc.NewStub(channel);
}

@ -1,3 +1,36 @@
#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 Google.GRPC.Core.Internal;

@ -1,3 +1,36 @@
#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;
using System.Threading.Tasks;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using System.Threading;
@ -8,13 +41,6 @@ namespace Google.GRPC.Core
{
public class Channel : IDisposable
{
/// <summary>
/// Make sure GPRC environment is initialized before any channels get used.
/// </summary>
static Channel() {
GrpcEnvironment.EnsureInitialized();
}
readonly ChannelSafeHandle handle;
readonly String target;

@ -1,3 +1,36 @@
#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;

@ -61,7 +61,6 @@
<Compile Include="Marshaller.cs" />
<Compile Include="ServerServiceDefinition.cs" />
<Compile Include="Utils\RecordingObserver.cs" />
<Compile Include="Utils\PortPicker.cs" />
<Compile Include="Utils\RecordingQueue.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

@ -1,3 +1,36 @@
#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 Google.GRPC.Core.Internal;
using System.Runtime.InteropServices;
@ -5,11 +38,9 @@ using System.Runtime.InteropServices;
namespace Google.GRPC.Core
{
/// <summary>
/// Encapsulates initialization and shutdown of GRPC C core library.
/// You should not need to initialize it manually, as static constructors
/// should load the library when needed.
/// Encapsulates initialization and shutdown of gRPC library.
/// </summary>
public static class GrpcEnvironment
public class GrpcEnvironment
{
const int THREAD_POOL_SIZE = 1;
@ -20,21 +51,24 @@ namespace Google.GRPC.Core
static extern void grpcsharp_shutdown();
static object staticLock = new object();
static bool initCalled = false;
static bool shutdownCalled = false;
static GrpcThreadPool threadPool = new GrpcThreadPool(THREAD_POOL_SIZE);
static volatile GrpcEnvironment instance;
readonly GrpcThreadPool threadPool;
bool isClosed;
/// <summary>
/// Makes sure GRPC environment is initialized.
/// Makes sure GRPC environment is initialized. Subsequent invocations don't have any
/// effect unless you call Shutdown first.
/// Although normal use cases assume you will call this just once in your application's
/// lifetime (and call Shutdown once you're done), for the sake of easier testing it's
/// allowed to initialize the environment again after it has been successfully shutdown.
/// </summary>
public static void EnsureInitialized() {
public static void Initialize() {
lock(staticLock)
{
if (!initCalled)
if (instance == null)
{
initCalled = true;
GrpcInit();
instance = new GrpcEnvironment();
}
}
}
@ -47,45 +81,55 @@ namespace Google.GRPC.Core
{
lock(staticLock)
{
if (initCalled && !shutdownCalled)
if (instance != null)
{
shutdownCalled = true;
GrpcShutdown();
instance.Close();
instance = null;
}
}
}
internal static GrpcThreadPool ThreadPool
{
get
{
var inst = instance;
if (inst == null)
{
throw new InvalidOperationException("GRPC environment not initialized");
}
return inst.threadPool;
}
}
/// <summary>
/// Initializes GRPC C Core library.
/// Creates gRPC environment.
/// </summary>
private static void GrpcInit()
private GrpcEnvironment()
{
grpcsharp_init();
threadPool = new GrpcThreadPool(THREAD_POOL_SIZE);
threadPool.Start();
// TODO: use proper logging here
Console.WriteLine("GRPC initialized.");
}
/// <summary>
/// Shutdown GRPC C Core library.
/// Shuts down this environment.
/// </summary>
private static void GrpcShutdown()
private void Close()
{
if (isClosed)
{
throw new InvalidOperationException("Close has already been called");
}
threadPool.Stop();
grpcsharp_shutdown();
isClosed = true;
// TODO: use proper logging here
Console.WriteLine("GRPC shutdown.");
}
internal static GrpcThreadPool ThreadPool
{
get
{
return threadPool;
}
}
}
}

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using System.Diagnostics;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using System.Diagnostics;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using System.Threading;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using System.Threading.Tasks;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using Google.GRPC.Core;

@ -1,3 +1,36 @@
#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 Google.GRPC.Core.Internal;
using System.Runtime.InteropServices;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using System.Diagnostics;

@ -1,3 +1,36 @@
#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 Google.GRPC.Core.Internal;

@ -1,3 +1,36 @@
#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 Google.GRPC.Core.Internal;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using System.Threading;

@ -1,3 +1,36 @@
#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 Google.GRPC.Core

@ -1,3 +1,36 @@
#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 Google.GRPC.Core

@ -1,3 +1,36 @@
#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 Google.GRPC.Core

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using System.Diagnostics;
@ -26,10 +59,6 @@ namespace Google.GRPC.Core
readonly TaskCompletionSource<object> shutdownTcs = new TaskCompletionSource<object>();
static Server() {
GrpcEnvironment.EnsureInitialized();
}
public Server()
{
// TODO: what is the tag for server shutdown?

@ -1,3 +1,36 @@
#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 Google.GRPC.Core.Internal;

@ -1,3 +1,36 @@
#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 Google.GRPC.Core

@ -1,3 +1,36 @@
#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.Collections.Generic;

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;

@ -1,3 +1,36 @@
#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 Google.GRPC.Core

@ -1,50 +0,0 @@
using System;
using System.Net;
using System.Net.Sockets;
namespace Google.GRPC.Core.Utils
{
public class PortPicker
{
static Random random = new Random();
// TODO: cleanup this code a bit
public static int PickUnusedPort()
{
int port;
do
{
port = random.Next(2000, 50000);
} while(!IsPortAvailable(port));
return port;
}
// TODO: cleanup this code a bit
public static bool IsPortAvailable(int port)
{
bool available = true;
TcpListener server = null;
try
{
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
server = new TcpListener(ipAddress, port);
server.Start();
}
catch (Exception ex)
{
available = false;
}
finally
{
if (server != null)
{
server.Stop();
}
}
return available;
}
}
}

@ -1,3 +1,36 @@
#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;

@ -1,3 +1,36 @@
#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;
@ -5,6 +38,7 @@ using System.Collections.Concurrent;
namespace Google.GRPC.Core.Utils
{
// TODO: replace this by something that implements IAsyncEnumerator.
/// <summary>
/// Observer that allows us to await incoming messages one-by-one.
/// The implementation is not ideal and class will be probably replaced

@ -1,3 +1,36 @@
#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 NUnit.Framework;
using Google.GRPC.Core;
@ -10,7 +43,7 @@ namespace Google.GRPC.Core.Tests
{
public class ClientServerTest
{
string serverAddr = "localhost:" + PortPicker.PickUnusedPort();
string host = "localhost";
Method<string, string> unaryEchoStringMethod = new Method<string, string>(
MethodType.Unary,
@ -21,15 +54,17 @@ namespace Google.GRPC.Core.Tests
[Test]
public void EmptyCall()
{
GrpcEnvironment.Initialize();
Server server = new Server();
server.AddServiceDefinition(
ServerServiceDefinition.CreateBuilder("someService")
.AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build());
server.AddPort(serverAddr);
int port = server.AddPort(host + ":0");
server.Start();
using (Channel channel = new Channel(serverAddr))
using (Channel channel = new Channel(host + ":" + port))
{
var call = new Call<string, string>(unaryEchoStringMethod, channel);

@ -1,3 +1,36 @@
#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 NUnit.Framework;
using Google.GRPC.Core;
@ -9,10 +42,30 @@ namespace Google.GRPC.Core.Tests
{
[Test]
public void InitializeAndShutdownGrpcEnvironment() {
GrpcEnvironment.EnsureInitialized();
Thread.Sleep(500);
GrpcEnvironment.Initialize();
Assert.IsNotNull(GrpcEnvironment.ThreadPool.CompletionQueue);
GrpcEnvironment.Shutdown();
}
[Test]
public void SubsequentInvocations() {
GrpcEnvironment.Initialize();
GrpcEnvironment.Initialize();
GrpcEnvironment.Shutdown();
GrpcEnvironment.Shutdown();
}
[Test]
public void InitializeAfterShutdown() {
GrpcEnvironment.Initialize();
var tp1 = GrpcEnvironment.ThreadPool;
GrpcEnvironment.Shutdown();
GrpcEnvironment.Initialize();
var tp2 = GrpcEnvironment.ThreadPool;
GrpcEnvironment.Shutdown();
Assert.IsFalse(Object.ReferenceEquals(tp1, tp2));
}
}
}

@ -1,3 +1,36 @@
#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 NUnit.Framework;
using Google.GRPC.Core.Internal;
@ -9,10 +42,12 @@ namespace Google.GRPC.Core.Tests
public class ServerTest
{
[Test]
public void StartAndShutdownServer() {
public void StartAndShutdownServer()
{
GrpcEnvironment.Initialize();
Server server = new Server();
server.AddPort("localhost:" + PortPicker.PickUnusedPort());
int port = server.AddPort("localhost:0");
server.Start();
server.ShutdownAsync().Wait();

@ -1,3 +1,36 @@
#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 NUnit.Framework;
using System.Runtime.InteropServices;

@ -1,3 +1,36 @@
#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.Collections.Generic;
using NUnit.Framework;
@ -60,6 +93,8 @@ namespace Google.GRPC.Interop
private void Run()
{
GrpcEnvironment.Initialize();
string addr = string.Format("{0}:{1}", options.serverHost, options.serverPort);
using (Channel channel = new Channel(addr))
{

@ -1,3 +1,36 @@
#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.Runtime.InteropServices;
using Google.GRPC.Core;
@ -9,6 +42,8 @@ namespace math
{
public static void Main (string[] args)
{
GrpcEnvironment.Initialize();
using (Channel channel = new Channel("127.0.0.1:23456"))
{
MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel);

@ -1,3 +1,36 @@
/*
*
* 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.
*
*/
#include <grpc/support/port_platform.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>

@ -29,6 +29,7 @@
"""Utility functions for invoking RPCs."""
import sys
import threading
from _framework.base import interfaces as base_interfaces
@ -79,20 +80,46 @@ def _stream_event_subscription(result_consumer, abortion_callback):
_EventServicedIngestor(result_consumer, abortion_callback))
# NOTE(nathaniel): This class has some extremely special semantics around
# cancellation that allow it to be used by both "blocking" APIs and "futures"
# APIs.
#
# Since futures.Future defines its own exception for cancellation, we want these
# objects, when returned by methods of a returning-Futures-from-other-methods
# object, to raise the same exception for cancellation. But that's weird in a
# blocking API - why should this object, also returned by methods of blocking
# APIs, raise exceptions from the "future" module? Should we do something like
# have this class be parameterized by the type of exception that it raises in
# cancellation circumstances?
#
# We don't have to take such a dramatic step: since blocking APIs define no
# cancellation semantics whatsoever, there is no supported way for
# blocking-API-users of these objects to cancel RPCs, and thus no supported way
# for them to see an exception the type of which would be weird to them.
#
# Bonus: in both blocking and futures APIs, this object still properly raises
# exceptions.CancellationError for any *server-side cancellation* of an RPC.
class _OperationCancellableIterator(interfaces.CancellableIterator):
"""An interfaces.CancellableIterator for response-streaming operations."""
def __init__(self, rendezvous, operation):
self._lock = threading.Lock()
self._rendezvous = rendezvous
self._operation = operation
self._cancelled = False
def __iter__(self):
return self
def next(self):
with self._lock:
if self._cancelled:
raise future.CancelledError()
return next(self._rendezvous)
def cancel(self):
with self._lock:
self._cancelled = True
self._operation.cancel()
self._rendezvous.set_outcome(base_interfaces.Outcome.CANCELLED)
@ -105,46 +132,126 @@ class _OperationFuture(future.Future):
self._rendezvous = rendezvous
self._operation = operation
self._outcome = None
self._cancelled = False
self._computed = False
self._payload = None
self._exception = None
self._traceback = None
self._callbacks = []
def cancel(self):
"""See future.Future.cancel for specification."""
with self._condition:
if self._outcome is None:
if not self._cancelled and not self._computed:
self._operation.cancel()
self._outcome = future.aborted()
self._cancelled = True
self._condition.notify_all()
return False
def cancelled(self):
"""See future.Future.cancelled for specification."""
return False
with self._condition:
return self._cancelled
def running(self):
"""See future.Future.running for specification."""
with self._condition:
return not self._cancelled and not self._computed
def done(self):
"""See future.Future.done for specification."""
with self._condition:
return (self._outcome is not None and
self._outcome.category is not future.ABORTED)
return self._cancelled or self._computed
def result(self, timeout=None):
"""See future.Future.result for specification."""
with self._condition:
if self._cancelled:
raise future.CancelledError()
if self._computed:
if self._payload is None:
raise self._exception # pylint: disable=raising-bad-type
else:
return self._payload
condition = threading.Condition()
def notify_condition(unused_future):
with condition:
condition.notify()
self._callbacks.append(notify_condition)
with condition:
condition.wait(timeout=timeout)
with self._condition:
if self._cancelled:
raise future.CancelledError()
elif self._computed:
if self._payload is None:
raise self._exception # pylint: disable=raising-bad-type
else:
return self._payload
else:
raise future.TimeoutError()
def exception(self, timeout=None):
"""See future.Future.exception for specification."""
with self._condition:
if self._cancelled:
raise future.CancelledError()
if self._computed:
return self._exception
condition = threading.Condition()
def notify_condition(unused_future):
with condition:
condition.notify()
self._callbacks.append(notify_condition)
with condition:
condition.wait(timeout=timeout)
def outcome(self):
"""See future.Future.outcome for specification."""
with self._condition:
while self._outcome is None:
self._condition.wait()
return self._outcome
if self._cancelled:
raise future.CancelledError()
elif self._computed:
return self._exception
else:
raise future.TimeoutError()
def add_done_callback(self, callback):
def traceback(self, timeout=None):
"""See future.Future.traceback for specification."""
with self._condition:
if self._cancelled:
raise future.CancelledError()
if self._computed:
return self._traceback
condition = threading.Condition()
def notify_condition(unused_future):
with condition:
condition.notify()
self._callbacks.append(notify_condition)
with condition:
condition.wait(timeout=timeout)
with self._condition:
if self._cancelled:
raise future.CancelledError()
elif self._computed:
return self._traceback
else:
raise future.TimeoutError()
def add_done_callback(self, fn):
"""See future.Future.add_done_callback for specification."""
with self._condition:
if self._callbacks is not None:
self._callbacks.add(callback)
self._callbacks.add(fn)
return
outcome = self._outcome
callable_util.call_logging_exceptions(
callback, _DONE_CALLBACK_LOG_MESSAGE, outcome)
callable_util.call_logging_exceptions(fn, _DONE_CALLBACK_LOG_MESSAGE, self)
def on_operation_termination(self, operation_outcome):
"""Indicates to this object that the operation has terminated.
@ -154,34 +261,42 @@ class _OperationFuture(future.Future):
outcome of the operation.
"""
with self._condition:
if (self._outcome is None and
operation_outcome is not base_interfaces.Outcome.COMPLETED):
self._outcome = future.raised(
_control.abortion_outcome_to_exception(operation_outcome))
self._condition.notify_all()
outcome = self._outcome
rendezvous = self._rendezvous
callbacks = list(self._callbacks)
self._callbacks = None
if outcome is None:
try:
return_value = next(rendezvous)
except Exception as e: # pylint: disable=broad-except
outcome = future.raised(e)
cancelled = self._cancelled
if cancelled:
callbacks = list(self._callbacks)
self._callbacks = None
else:
outcome = future.returned(return_value)
rendezvous = self._rendezvous
if not cancelled:
payload = None
exception = None
traceback = None
if operation_outcome == base_interfaces.Outcome.COMPLETED:
try:
payload = next(rendezvous)
except Exception as e: # pylint: disable=broad-except
exception = e
traceback = sys.exc_info()[2]
else:
try:
# We raise and then immediately catch in order to create a traceback.
raise _control.abortion_outcome_to_exception(operation_outcome)
except Exception as e: # pylint: disable=broad-except
exception = e
traceback = sys.exc_info()[2]
with self._condition:
if self._outcome is None:
self._outcome = outcome
self._condition.notify_all()
else:
outcome = self._outcome
if not self._cancelled:
self._computed = True
self._payload = payload
self._exception = exception
self._traceback = traceback
callbacks = list(self._callbacks)
self._callbacks = None
for callback in callbacks:
callable_util.call_logging_exceptions(
callback, _DONE_CALLBACK_LOG_MESSAGE, outcome)
callback, _DONE_CALLBACK_LOG_MESSAGE, self)
class _Call(interfaces.Call):

@ -116,7 +116,7 @@ class FutureInvocationAsynchronousEventServiceTestCase(
response_future = self.stub.future_value_in_value_out(
name, request, _TIMEOUT)
response = response_future.outcome().return_value
response = response_future.result()
test_messages.verify(request, response, self)
@ -144,7 +144,7 @@ class FutureInvocationAsynchronousEventServiceTestCase(
with request_iterator.pause():
response_future = self.stub.future_stream_in_value_out(
name, request_iterator, _TIMEOUT)
response = response_future.outcome().return_value
response = response_future.result()
test_messages.verify(requests, response, self)
@ -173,13 +173,13 @@ class FutureInvocationAsynchronousEventServiceTestCase(
first_response_future = self.stub.future_value_in_value_out(
name, first_request, _TIMEOUT)
first_response = first_response_future.outcome().return_value
first_response = first_response_future.result()
test_messages.verify(first_request, first_response, self)
second_response_future = self.stub.future_value_in_value_out(
name, second_request, _TIMEOUT)
second_response = second_response_future.outcome().return_value
second_response = second_response_future.result()
test_messages.verify(second_request, second_response, self)
@ -192,10 +192,10 @@ class FutureInvocationAsynchronousEventServiceTestCase(
with self.control.pause():
response_future = self.stub.future_value_in_value_out(
name, request, _TIMEOUT)
outcome = response_future.outcome()
self.assertIsInstance(
outcome.exception, exceptions.ExpirationError)
self.assertIsInstance(
response_future.exception(), exceptions.ExpirationError)
with self.assertRaises(exceptions.ExpirationError):
response_future.result()
def testExpiredUnaryRequestStreamResponse(self):
for name, test_messages_sequence in (
@ -203,11 +203,11 @@ class FutureInvocationAsynchronousEventServiceTestCase(
for test_messages in test_messages_sequence:
request = test_messages.request()
with self.control.pause(), self.assertRaises(
exceptions.ExpirationError):
with self.control.pause():
response_iterator = self.stub.inline_value_in_stream_out(
name, request, _TIMEOUT)
list(response_iterator)
with self.assertRaises(exceptions.ExpirationError):
list(response_iterator)
def testExpiredStreamRequestUnaryResponse(self):
for name, test_messages_sequence in (
@ -218,10 +218,10 @@ class FutureInvocationAsynchronousEventServiceTestCase(
with self.control.pause():
response_future = self.stub.future_stream_in_value_out(
name, iter(requests), _TIMEOUT)
outcome = response_future.outcome()
self.assertIsInstance(
outcome.exception, exceptions.ExpirationError)
self.assertIsInstance(
response_future.exception(), exceptions.ExpirationError)
with self.assertRaises(exceptions.ExpirationError):
response_future.result()
def testExpiredStreamRequestStreamResponse(self):
for name, test_messages_sequence in (
@ -229,11 +229,11 @@ class FutureInvocationAsynchronousEventServiceTestCase(
for test_messages in test_messages_sequence:
requests = test_messages.requests()
with self.control.pause(), self.assertRaises(
exceptions.ExpirationError):
with self.control.pause():
response_iterator = self.stub.inline_stream_in_stream_out(
name, iter(requests), _TIMEOUT)
list(response_iterator)
with self.assertRaises(exceptions.ExpirationError):
list(response_iterator)
def testFailedUnaryRequestUnaryResponse(self):
for name, test_messages_sequence in (
@ -244,13 +244,15 @@ class FutureInvocationAsynchronousEventServiceTestCase(
with self.control.fail():
response_future = self.stub.future_value_in_value_out(
name, request, _TIMEOUT)
outcome = response_future.outcome()
# Because the servicer fails outside of the thread from which the
# servicer-side runtime called into it its failure is indistinguishable
# from simply not having called its response_callback before the
# expiration of the RPC.
self.assertIsInstance(outcome.exception, exceptions.ExpirationError)
# Because the servicer fails outside of the thread from which the
# servicer-side runtime called into it its failure is
# indistinguishable from simply not having called its
# response_callback before the expiration of the RPC.
self.assertIsInstance(
response_future.exception(), exceptions.ExpirationError)
with self.assertRaises(exceptions.ExpirationError):
response_future.result()
def testFailedUnaryRequestStreamResponse(self):
for name, test_messages_sequence in (
@ -276,13 +278,15 @@ class FutureInvocationAsynchronousEventServiceTestCase(
with self.control.fail():
response_future = self.stub.future_stream_in_value_out(
name, iter(requests), _TIMEOUT)
outcome = response_future.outcome()
# Because the servicer fails outside of the thread from which the
# servicer-side runtime called into it its failure is indistinguishable
# from simply not having called its response_callback before the
# expiration of the RPC.
self.assertIsInstance(outcome.exception, exceptions.ExpirationError)
# Because the servicer fails outside of the thread from which the
# servicer-side runtime called into it its failure is
# indistinguishable from simply not having called its
# response_callback before the expiration of the RPC.
self.assertIsInstance(
response_future.exception(), exceptions.ExpirationError)
with self.assertRaises(exceptions.ExpirationError):
response_future.result()
def testFailedStreamRequestStreamResponse(self):
for name, test_messages_sequence in (
@ -310,8 +314,8 @@ class FutureInvocationAsynchronousEventServiceTestCase(
name, first_request, _TIMEOUT)
second_response_future = self.stub.future_value_in_value_out(
name, second_request, _TIMEOUT)
first_response = first_response_future.outcome().return_value
second_response = second_response_future.outcome().return_value
first_response = first_response_future.result()
second_response = second_response_future.result()
test_messages.verify(first_request, first_response, self)
test_messages.verify(second_request, second_response, self)
@ -329,10 +333,10 @@ class FutureInvocationAsynchronousEventServiceTestCase(
with self.control.pause():
response_future = self.stub.future_value_in_value_out(
name, request, _TIMEOUT)
cancelled = response_future.cancel()
cancel_method_return_value = response_future.cancel()
self.assertFalse(cancelled)
self.assertEqual(future.ABORTED, response_future.outcome().category)
self.assertFalse(cancel_method_return_value)
self.assertTrue(response_future.cancelled())
def testCancelledUnaryRequestStreamResponse(self):
for name, test_messages_sequence in (
@ -345,7 +349,7 @@ class FutureInvocationAsynchronousEventServiceTestCase(
name, request, _TIMEOUT)
response_iterator.cancel()
with self.assertRaises(exceptions.CancellationError):
with self.assertRaises(future.CancelledError):
next(response_iterator)
def testCancelledStreamRequestUnaryResponse(self):
@ -357,10 +361,10 @@ class FutureInvocationAsynchronousEventServiceTestCase(
with self.control.pause():
response_future = self.stub.future_stream_in_value_out(
name, iter(requests), _TIMEOUT)
cancelled = response_future.cancel()
cancel_method_return_value = response_future.cancel()
self.assertFalse(cancelled)
self.assertEqual(future.ABORTED, response_future.outcome().category)
self.assertFalse(cancel_method_return_value)
self.assertTrue(response_future.cancelled())
def testCancelledStreamRequestStreamResponse(self):
for name, test_messages_sequence in (
@ -373,5 +377,5 @@ class FutureInvocationAsynchronousEventServiceTestCase(
name, iter(requests), _TIMEOUT)
response_iterator.cancel()
with self.assertRaises(exceptions.CancellationError):
with self.assertRaises(future.CancelledError):
next(response_iterator)

@ -33,7 +33,6 @@ import threading
import time
import unittest
from _framework.foundation import future
from _framework.foundation import later
TICK = 0.1
@ -44,10 +43,14 @@ class LaterTest(unittest.TestCase):
def test_simple_delay(self):
lock = threading.Lock()
cell = [0]
def increment_cell():
return_value = object()
def computation():
with lock:
cell[0] += 1
computation_future = later.later(TICK * 2, increment_cell)
return return_value
computation_future = later.later(TICK * 2, computation)
self.assertFalse(computation_future.done())
self.assertFalse(computation_future.cancelled())
time.sleep(TICK)
@ -60,22 +63,21 @@ class LaterTest(unittest.TestCase):
self.assertFalse(computation_future.cancelled())
with lock:
self.assertEqual(1, cell[0])
outcome = computation_future.outcome()
self.assertEqual(future.RETURNED, outcome.category)
self.assertEqual(return_value, computation_future.result())
def test_callback(self):
lock = threading.Lock()
cell = [0]
callback_called = [False]
outcome_passed_to_callback = [None]
def increment_cell():
future_passed_to_callback = [None]
def computation():
with lock:
cell[0] += 1
computation_future = later.later(TICK * 2, increment_cell)
computation_future = later.later(TICK * 2, computation)
def callback(outcome):
with lock:
callback_called[0] = True
outcome_passed_to_callback[0] = outcome
future_passed_to_callback[0] = outcome
computation_future.add_done_callback(callback)
time.sleep(TICK)
with lock:
@ -83,63 +85,67 @@ class LaterTest(unittest.TestCase):
time.sleep(TICK * 2)
with lock:
self.assertTrue(callback_called[0])
self.assertEqual(future.RETURNED, outcome_passed_to_callback[0].category)
self.assertTrue(future_passed_to_callback[0].done())
callback_called[0] = False
outcome_passed_to_callback[0] = None
future_passed_to_callback[0] = None
computation_future.add_done_callback(callback)
with lock:
self.assertTrue(callback_called[0])
self.assertEqual(future.RETURNED, outcome_passed_to_callback[0].category)
self.assertTrue(future_passed_to_callback[0].done())
def test_cancel(self):
lock = threading.Lock()
cell = [0]
callback_called = [False]
outcome_passed_to_callback = [None]
def increment_cell():
future_passed_to_callback = [None]
def computation():
with lock:
cell[0] += 1
computation_future = later.later(TICK * 2, increment_cell)
computation_future = later.later(TICK * 2, computation)
def callback(outcome):
with lock:
callback_called[0] = True
outcome_passed_to_callback[0] = outcome
future_passed_to_callback[0] = outcome
computation_future.add_done_callback(callback)
time.sleep(TICK)
with lock:
self.assertFalse(callback_called[0])
computation_future.cancel()
self.assertTrue(computation_future.cancelled())
self.assertFalse(computation_future.done())
self.assertEqual(future.ABORTED, computation_future.outcome().category)
self.assertFalse(computation_future.running())
self.assertTrue(computation_future.done())
with lock:
self.assertTrue(callback_called[0])
self.assertEqual(future.ABORTED, outcome_passed_to_callback[0].category)
self.assertTrue(future_passed_to_callback[0].cancelled())
def test_outcome(self):
def test_result(self):
lock = threading.Lock()
cell = [0]
callback_called = [False]
outcome_passed_to_callback = [None]
def increment_cell():
future_passed_to_callback_cell = [None]
return_value = object()
def computation():
with lock:
cell[0] += 1
computation_future = later.later(TICK * 2, increment_cell)
def callback(outcome):
return return_value
computation_future = later.later(TICK * 2, computation)
def callback(future_passed_to_callback):
with lock:
callback_called[0] = True
outcome_passed_to_callback[0] = outcome
future_passed_to_callback_cell[0] = future_passed_to_callback
computation_future.add_done_callback(callback)
returned_outcome = computation_future.outcome()
self.assertEqual(future.RETURNED, returned_outcome.category)
returned_value = computation_future.result()
self.assertEqual(return_value, returned_value)
# The callback may not yet have been called! Sleep a tick.
time.sleep(TICK)
with lock:
self.assertTrue(callback_called[0])
self.assertEqual(future.RETURNED, outcome_passed_to_callback[0].category)
self.assertEqual(return_value, future_passed_to_callback_cell[0].result())
if __name__ == '__main__':
unittest.main()

@ -29,6 +29,7 @@
"""Affords a Future implementation based on Python's threading.Timer."""
import sys
import threading
import time
@ -52,7 +53,9 @@ class TimerFuture(future.Future):
self._computing = False
self._computed = False
self._cancelled = False
self._outcome = None
self._result = None
self._exception = None
self._traceback = None
self._waiting = []
def _compute(self):
@ -70,19 +73,24 @@ class TimerFuture(future.Future):
self._computing = True
try:
returned_value = self._computation()
outcome = future.returned(returned_value)
return_value = self._computation()
exception = None
traceback = None
except Exception as e: # pylint: disable=broad-except
outcome = future.raised(e)
return_value = None
exception = e
traceback = sys.exc_info()[2]
with self._lock:
self._computing = False
self._computed = True
self._outcome = outcome
self._return_value = return_value
self._exception = exception
self._traceback = traceback
waiting = self._waiting
for callback in waiting:
callback(outcome)
callback(self)
def start(self):
"""Starts this Future.
@ -104,13 +112,11 @@ class TimerFuture(future.Future):
else:
self._timer.cancel()
self._cancelled = True
self._outcome = future.aborted()
outcome = self._outcome
waiting = self._waiting
for callback in waiting:
try:
callback(outcome)
callback(self)
except Exception: # pylint: disable=broad-except
pass
@ -121,36 +127,102 @@ class TimerFuture(future.Future):
with self._lock:
return self._cancelled
def running(self):
"""See future.Future.running for specification."""
with self._lock:
return not self._computed and not self._cancelled
def done(self):
"""See future.Future.done for specification."""
with self._lock:
return self._computed
return self._computed or self._cancelled
def result(self, timeout=None):
"""See future.Future.result for specification."""
with self._lock:
if self._cancelled:
raise future.CancelledError()
elif self._computed:
if self._exception is None:
return self._return_value
else:
raise self._exception # pylint: disable=raising-bad-type
condition = threading.Condition()
def notify_condition(unused_future):
with condition:
condition.notify()
self._waiting.append(notify_condition)
with condition:
condition.wait(timeout=timeout)
with self._lock:
if self._cancelled:
raise future.CancelledError()
elif self._computed:
if self._exception is None:
return self._return_value
else:
raise self._exception # pylint: disable=raising-bad-type
else:
raise future.TimeoutError()
def exception(self, timeout=None):
"""See future.Future.exception for specification."""
with self._lock:
if self._cancelled:
raise future.CancelledError()
elif self._computed:
return self._exception
condition = threading.Condition()
def notify_condition(unused_future):
with condition:
condition.notify()
self._waiting.append(notify_condition)
with condition:
condition.wait(timeout=timeout)
with self._lock:
if self._cancelled:
raise future.CancelledError()
elif self._computed:
return self._exception
else:
raise future.TimeoutError()
def outcome(self):
"""See future.Future.outcome for specification."""
def traceback(self, timeout=None):
"""See future.Future.traceback for specification."""
with self._lock:
if self._computed or self._cancelled:
return self._outcome
if self._cancelled:
raise future.CancelledError()
elif self._computed:
return self._traceback
condition = threading.Condition()
def notify_condition(unused_outcome):
def notify_condition(unused_future):
with condition:
condition.notify()
self._waiting.append(notify_condition)
with condition:
condition.wait()
condition.wait(timeout=timeout)
with self._lock:
return self._outcome
if self._cancelled:
raise future.CancelledError()
elif self._computed:
return self._traceback
else:
raise future.TimeoutError()
def add_done_callback(self, callback):
def add_done_callback(self, fn):
"""See future.Future.add_done_callback for specification."""
with self._lock:
if not self._computed and not self._cancelled:
self._waiting.append(callback)
self._waiting.append(fn)
return
else:
outcome = self._outcome
callback(outcome)
fn(self)

@ -29,18 +29,47 @@
"""Utilities for working with callables."""
import abc
import collections
import enum
import functools
import logging
from _framework.foundation import future
class Outcome(object):
"""A sum type describing the outcome of some call.
Attributes:
kind: One of Kind.RETURNED or Kind.RAISED respectively indicating that the
call returned a value or raised an exception.
return_value: The value returned by the call. Must be present if kind is
Kind.RETURNED.
exception: The exception raised by the call. Must be present if kind is
Kind.RAISED.
"""
__metaclass__ = abc.ABCMeta
@enum.unique
class Kind(enum.Enum):
"""Identifies the general kind of the outcome of some call."""
RETURNED = object()
RAISED = object()
class _EasyOutcome(
collections.namedtuple(
'_EasyOutcome', ['kind', 'return_value', 'exception']),
Outcome):
"""A trivial implementation of Outcome."""
def _call_logging_exceptions(behavior, message, *args, **kwargs):
try:
return future.returned(behavior(*args, **kwargs))
return _EasyOutcome(Outcome.Kind.RETURNED, behavior(*args, **kwargs), None)
except Exception as e: # pylint: disable=broad-except
logging.exception(message)
return future.raised(e)
return _EasyOutcome(Outcome.Kind.RAISED, None, e)
def with_exceptions_logged(behavior, message):
@ -72,7 +101,7 @@ def call_logging_exceptions(behavior, message, *args, **kwargs):
**kwargs: Keyword arguments to pass to the given behavior.
Returns:
A future.Outcome describing whether the given behavior returned a value or
raised an exception.
An Outcome describing whether the given behavior returned a value or raised
an exception.
"""
return _call_logging_exceptions(behavior, message, *args, **kwargs)

@ -27,146 +27,210 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""The Future interface missing from Python's standard library.
"""A Future interface.
Python's concurrent.futures library defines a Future class very much like the
Future defined here, but since that class is concrete and without construction
semantics it is only available within the concurrent.futures library itself.
The Future class defined here is an entirely abstract interface that anyone may
Python doesn't have a Future interface in its standard library. In the absence
of such a standard, three separate, incompatible implementations
(concurrent.futures.Future, ndb.Future, and asyncio.Future) have appeared. This
interface attempts to be as compatible as possible with
concurrent.futures.Future. From ndb.Future it adopts a traceback-object accessor
method.
Unlike the concrete and implemented Future classes listed above, the Future
class defined in this module is an entirely abstract interface that anyone may
implement and use.
The one known incompatibility between this interface and the interface of
concurrent.futures.Future is that this interface defines its own CancelledError
and TimeoutError exceptions rather than raising the implementation-private
concurrent.futures._base.CancelledError and the
built-in-but-only-in-3.3-and-later TimeoutError.
"""
import abc
import collections
RETURNED = object()
RAISED = object()
ABORTED = object()
class Outcome(object):
"""A sum type describing the outcome of some computation.
Attributes:
category: One of RETURNED, RAISED, or ABORTED, respectively indicating
that the computation returned a value, raised an exception, or was
aborted.
return_value: The value returned by the computation. Must be present if
category is RETURNED.
exception: The exception raised by the computation. Must be present if
category is RAISED.
"""
__metaclass__ = abc.ABCMeta
class TimeoutError(Exception):
"""Indicates that a particular call timed out."""
class _EasyOutcome(
collections.namedtuple('_EasyOutcome',
['category', 'return_value', 'exception']),
Outcome):
"""A trivial implementation of Outcome."""
# All Outcomes describing abortion are indistinguishable so there might as well
# be only one.
_ABORTED_OUTCOME = _EasyOutcome(ABORTED, None, None)
class CancelledError(Exception):
"""Indicates that the computation underlying a Future was cancelled."""
def aborted():
"""Returns an Outcome indicating that a computation was aborted.
class Future(object):
"""A representation of a computation in another control flow.
Returns:
An Outcome indicating that a computation was aborted.
Computations represented by a Future may be yet to be begun, may be ongoing,
or may have already completed.
"""
return _ABORTED_OUTCOME
def raised(exception):
"""Returns an Outcome indicating that a computation raised an exception.
Args:
exception: The exception raised by the computation.
__metaclass__ = abc.ABCMeta
Returns:
An Outcome indicating that a computation raised the given exception.
"""
return _EasyOutcome(RAISED, None, exception)
# NOTE(nathaniel): This isn't the return type that I would want to have if it
# were up to me. Were this interface being written from scratch, the return
# type of this method would probably be a sum type like:
#
# NOT_COMMENCED
# COMMENCED_AND_NOT_COMPLETED
# PARTIAL_RESULT<Partial_Result_Type>
# COMPLETED<Result_Type>
# UNCANCELLABLE
# NOT_IMMEDIATELY_DETERMINABLE
@abc.abstractmethod
def cancel(self):
"""Attempts to cancel the computation.
This method does not block.
def returned(value):
"""Returns an Outcome indicating that a computation returned a value.
Returns:
True if the computation has not yet begun, will not be allowed to take
place, and determination of both was possible without blocking. False
under all other circumstances including but not limited to the
computation's already having begun, the computation's already having
finished, and the computation's having been scheduled for execution on a
remote system for which a determination of whether or not it commenced
before being cancelled cannot be made without blocking.
"""
raise NotImplementedError()
Args:
value: The value returned by the computation.
# NOTE(nathaniel): Here too this isn't the return type that I'd want this
# method to have if it were up to me. I think I'd go with another sum type
# like:
#
# NOT_CANCELLED (this object's cancel method hasn't been called)
# NOT_COMMENCED
# COMMENCED_AND_NOT_COMPLETED
# PARTIAL_RESULT<Partial_Result_Type>
# COMPLETED<Result_Type>
# UNCANCELLABLE
# NOT_IMMEDIATELY_DETERMINABLE
#
# Notice how giving the cancel method the right semantics obviates most
# reasons for this method to exist.
@abc.abstractmethod
def cancelled(self):
"""Describes whether the computation was cancelled.
Returns:
An Outcome indicating that a computation returned the given value.
"""
return _EasyOutcome(RETURNED, value, None)
This method does not block.
Returns:
True if the computation was cancelled any time before its result became
immediately available. False under all other circumstances including but
not limited to this object's cancel method not having been called and
the computation's result having become immediately available.
"""
raise NotImplementedError()
class Future(object):
"""A representation of a computation happening in another control flow.
@abc.abstractmethod
def running(self):
"""Describes whether the computation is taking place.
Computations represented by a Future may have already completed, may be
ongoing, or may be yet to be begun.
This method does not block.
Computations represented by a Future are considered uninterruptable; once
started they will be allowed to terminate either by returning or raising
an exception.
"""
__metaclass__ = abc.ABCMeta
Returns:
True if the computation is scheduled to take place in the future or is
taking place now, or False if the computation took place in the past or
was cancelled.
"""
raise NotImplementedError()
# NOTE(nathaniel): These aren't quite the semantics I'd like here either. I
# would rather this only returned True in cases in which the underlying
# computation completed successfully. A computation's having been cancelled
# conflicts with considering that computation "done".
@abc.abstractmethod
def cancel(self):
"""Attempts to cancel the computation.
def done(self):
"""Describes whether the computation has taken place.
This method does not block.
Returns:
True if the computation will not be allowed to take place or False if
the computation has already taken place or is currently taking place.
True if the computation is known to have either completed or have been
unscheduled or interrupted. False if the computation may possibly be
executing or scheduled to execute later.
"""
raise NotImplementedError()
@abc.abstractmethod
def cancelled(self):
"""Describes whether the computation was cancelled.
def result(self, timeout=None):
"""Accesses the outcome of the computation or raises its exception.
This method may return immediately or may block.
Args:
timeout: The length of time in seconds to wait for the computation to
finish or be cancelled, or None if this method should block until the
computation has finished or is cancelled no matter how long that takes.
Returns:
True if the computation was cancelled and did not take place or False
if the computation took place, is taking place, or is scheduled to
take place in the future.
The return value of the computation.
Raises:
TimeoutError: If a timeout value is passed and the computation does not
terminate within the allotted time.
CancelledError: If the computation was cancelled.
Exception: If the computation raised an exception, this call will raise
the same exception.
"""
raise NotImplementedError()
@abc.abstractmethod
def done(self):
"""Describes whether the computation has taken place.
def exception(self, timeout=None):
"""Return the exception raised by the computation.
This method may return immediately or may block.
Args:
timeout: The length of time in seconds to wait for the computation to
terminate or be cancelled, or None if this method should block until
the computation is terminated or is cancelled no matter how long that
takes.
Returns:
True if the computation took place; False otherwise.
The exception raised by the computation, or None if the computation did
not raise an exception.
Raises:
TimeoutError: If a timeout value is passed and the computation does not
terminate within the allotted time.
CancelledError: If the computation was cancelled.
"""
raise NotImplementedError()
@abc.abstractmethod
def outcome(self):
"""Accesses the outcome of the computation.
def traceback(self, timeout=None):
"""Access the traceback of the exception raised by the computation.
If the computation has not yet completed, this method blocks until it has.
This method may return immediately or may block.
Args:
timeout: The length of time in seconds to wait for the computation to
terminate or be cancelled, or None if this method should block until
the computation is terminated or is cancelled no matter how long that
takes.
Returns:
An Outcome describing the outcome of the computation.
The traceback of the exception raised by the computation, or None if the
computation did not raise an exception.
Raises:
TimeoutError: If a timeout value is passed and the computation does not
terminate within the allotted time.
CancelledError: If the computation was cancelled.
"""
raise NotImplementedError()
@abc.abstractmethod
def add_done_callback(self, callback):
def add_done_callback(self, fn):
"""Adds a function to be called at completion of the computation.
The callback will be passed an Outcome object describing the outcome of
The callback will be passed this Future object describing the outcome of
the computation.
If the computation has already completed, the callback will be called
immediately.
Args:
callback: A callable taking an Outcome as its single parameter.
fn: A callable taking a this Future object as its single parameter.
"""
raise NotImplementedError()

@ -16,7 +16,7 @@
m = proto_re.match(filename)
if not m:
return filename
return 'gens/' + m.group(1) + '.pb.cc'
return '$(GENDIR)/' + m.group(1) + '.pb.cc'
%>
@ -27,6 +27,15 @@ SYSTEM = $(HOST_SYSTEM)
endif
ifndef BUILDDIR
BUILDDIR = .
endif
BINDIR = $(BUILDDIR)/bins
OBJDIR = $(BUILDDIR)/objs
LIBDIR = $(BUILDDIR)/libs
GENDIR = $(BUILDDIR)/gens
# Configurations
VALID_CONFIG_opt = 1
@ -83,15 +92,27 @@ DEFINES_asan = NDEBUG
VALID_CONFIG_msan = 1
REQUIRE_CUSTOM_LIBRARIES_msan = 1
CC_msan = clang
CXX_msan = clang++
CXX_msan = clang++-libc++
LD_msan = clang
LDXX_msan = clang++
CPPFLAGS_msan = -O1 -fsanitize=memory -fno-omit-frame-pointer
LDXX_msan = clang++-libc++
CPPFLAGS_msan = -O1 -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1
OPENSSL_CFLAGS_msan = -DPURIFY
OPENSSL_CONFIG_msan = no-asm
LDFLAGS_msan = -fsanitize=memory
LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1
DEFINES_msan = NDEBUG
VALID_CONFIG_ubsan = 1
REQUIRE_CUSTOM_LIBRARIES_ubsan = 1
CC_ubsan = clang
CXX_ubsan = clang++
LD_ubsan = clang
LDXX_ubsan = clang++
CPPFLAGS_ubsan = -O1 -fsanitize=undefined -fno-omit-frame-pointer
OPENSSL_CFLAGS_ubsan = -DPURIFY
OPENSSL_CONFIG_ubsan = no-asm
LDFLAGS_ubsan = -fsanitize=undefined
DEFINES_ubsan = NDEBUG
VALID_CONFIG_gcov = 1
CC_gcov = gcc
CXX_gcov = g++
@ -142,15 +163,13 @@ CXXFLAGS += -std=c++11
CPPFLAGS += -g -fPIC -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter
LDFLAGS += -g -fPIC
INCLUDES = . include gens
INCLUDES = . include $(GENDIR)
ifeq ($(SYSTEM),Darwin)
LIBS = m z
else
LIBS = rt m z pthread
LDFLAGS += -pthread
endif
LIBSXX = protobuf
LIBS_PROTOC = protoc protobuf
ifneq ($(wildcard /usr/src/gtest/src/gtest-all.cc),)
GTEST_LIB = /usr/src/gtest/src/gtest-all.cc -I/usr/src/gtest
@ -174,7 +193,6 @@ CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
LDFLAGS += $(ARCH_FLAGS)
LDLIBS += $(addprefix -l, $(LIBS))
LDLIBSXX += $(addprefix -l, $(LIBSXX))
HOST_LDLIBS_PROTOC += $(addprefix -l, $(LIBS_PROTOC))
HOST_CPPFLAGS = $(CPPFLAGS)
HOST_CFLAGS = $(CFLAGS)
@ -205,6 +223,8 @@ endif
OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS)
ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS)
PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/perftools.c -lprofiler $(LDFLAGS)
PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o /dev/null test/build/protobuf.cc -lprotobuf $(LDFLAGS)
PROTOC_CHECK_CMD = protoc --version | grep -q libprotoc.3
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false)
@ -217,12 +237,16 @@ endif
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
HAS_SYSTEM_ZLIB = $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
HAS_SYSTEM_PROTOBUF = $(shell $(PROTOBUF_CHECK_CMD) 2> /dev/null && echo true || echo false)
else
# override system libraries if the config requires a custom compiled library
HAS_SYSTEM_OPENSSL_ALPN = false
HAS_SYSTEM_ZLIB = false
HAS_SYSTEM_PROTOBUF = false
endif
HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(wildcard third_party/openssl/ssl/ssl.h),)
HAS_EMBEDDED_OPENSSL_ALPN = false
else
@ -235,11 +259,20 @@ else
HAS_EMBEDDED_ZLIB = true
endif
ifeq ($(wildcard third_party/protobuf/src/google/protobuf/descriptor.pb.h),)
HAS_EMBEDDED_PROTOBUF = false
ifneq ($(HAS_VALID_PROTOC),true)
NO_PROTOC = true
endif
else
HAS_EMBEDDED_PROTOBUF = true
endif
ifeq ($(HAS_SYSTEM_ZLIB),false)
ifeq ($(HAS_EMBEDDED_ZLIB),true)
ZLIB_DEP = libs/$(CONFIG)/zlib/libz.a
ZLIB_DEP = $(LIBDIR)/$(CONFIG)/zlib/libz.a
CPPFLAGS += -Ithird_party/zlib
LDFLAGS += -Lthird_party/zlib
LDFLAGS += -L$(LIBDIR)/$(CONFIG)/zlib
else
DEP_MISSING += zlib
endif
@ -247,10 +280,10 @@ endif
ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),false)
ifeq ($(HAS_EMBEDDED_OPENSSL_ALPN),true)
OPENSSL_DEP = libs/$(CONFIG)/openssl/libssl.a
OPENSSL_MERGE_LIBS += libs/$(CONFIG)/openssl/libssl.a libs/$(CONFIG)/openssl/libcrypto.a
OPENSSL_DEP = $(LIBDIR)/$(CONFIG)/openssl/libssl.a
OPENSSL_MERGE_LIBS += $(LIBDIR)/$(CONFIG)/openssl/libssl.a $(LIBDIR)/$(CONFIG)/openssl/libcrypto.a
CPPFLAGS += -Ithird_party/openssl/include
LDFLAGS += -Llibs/$(CONFIG)/openssl
LDFLAGS += -L$(LIBDIR)/$(CONFIG)/openssl
LIBS_SECURE = dl
else
NO_SECURE = true
@ -261,6 +294,24 @@ endif
LDLIBS_SECURE += $(addprefix -l, $(LIBS_SECURE))
ifeq ($(HAS_SYSTEM_PROTOBUF),false)
ifeq ($(HAS_EMBEDDED_PROTOBUF),true)
PROTOBUF_DEP = $(LIBDIR)/$(CONFIG)/protobuf/libprotobuf.a
CPPFLAGS += -Ithird_party/protobuf/src
LDFLAGS += -L$(LIBDIR)/$(CONFIG)/protobuf
PROTOC = $(BINDIR)/$(CONFIG)/protobuf/protoc
else
NO_PROTOBUF = true
endif
else
endif
LIBS_PROTOBUF = protobuf
LIBS_PROTOC = protoc protobuf
LDLIBS_PROTOBUF += $(addprefix -l, $(LIBS_PROTOBUF))
HOST_LDLIBS_PROTOC += $(addprefix -l, $(LIBS_PROTOC))
ifeq ($(MAKECMDGOALS),clean)
NO_DEPS = true
endif
@ -270,7 +321,7 @@ endif
PROTOC_PLUGINS=\
% for tgt in targets:
% if tgt.build == 'protoc':
bins/$(CONFIG)/${tgt.name}\
$(BINDIR)/$(CONFIG)/${tgt.name}\
% endif
% endfor
@ -278,7 +329,7 @@ ifeq ($(DEP_MISSING),)
all: static shared\
% for tgt in targets:
% if tgt.build == 'all':
bins/$(CONFIG)/${tgt.name}\
$(BINDIR)/$(CONFIG)/${tgt.name}\
% endif
% endfor
@ -316,6 +367,10 @@ endif
openssl_dep_error: openssl_dep_message git_update stop
protobuf_dep_error: protobuf_dep_message git_update stop
protoc_dep_error: protoc_dep_message git_update stop
openssl_dep_message:
@echo
@echo "DEPENDENCY ERROR"
@ -330,26 +385,57 @@ openssl_dep_message:
@echo " make run_dep_checks"
@echo
protobuf_dep_message:
@echo
@echo "DEPENDENCY ERROR"
@echo
@echo "The target you are trying to run requires protobuf 3.0.0+"
@echo "Your system doesn't have it, and neither does the third_party directory."
@echo
@echo "Please consult INSTALL to get more information."
@echo
@echo "If you need information about why these tests failed, run:"
@echo
@echo " make run_dep_checks"
@echo
protoc_dep_message:
@echo
@echo "DEPENDENCY ERROR"
@echo
@echo "The target you are trying to run requires protobuf-compiler 3.0.0+"
@echo "Your system doesn't have it, and neither does the third_party directory."
@echo
@echo "Please consult INSTALL to get more information."
@echo
@echo "If you need information about why these tests failed, run:"
@echo
@echo " make run_dep_checks"
@echo
stop:
@false
% for tgt in targets:
${tgt.name}: bins/$(CONFIG)/${tgt.name}
${tgt.name}: $(BINDIR)/$(CONFIG)/${tgt.name}
% endfor
run_dep_checks:
$(OPENSSL_ALPN_CHECK_CMD) || true
$(ZLIB_CHECK_CMD) || true
$(PERFTOOLS_CHECK_CMD) || true
$(PROTOBUF_CHECK_CMD) || true
$(PROTOC_CHECK_CMD) || true
libs/$(CONFIG)/zlib/libz.a:
$(LIBDIR)/$(CONFIG)/zlib/libz.a:
$(E) "[MAKE] Building zlib"
$(Q)(cd third_party/zlib ; CC="$(CC)" CFLAGS="-fPIC -fvisibility=hidden $(CPPFLAGS_$(CONFIG))" ./configure --static)
$(Q)$(MAKE) -C third_party/zlib clean
$(Q)$(MAKE) -C third_party/zlib
$(Q)mkdir -p libs/$(CONFIG)/zlib
$(Q)cp third_party/zlib/libz.a libs/$(CONFIG)/zlib
$(Q)mkdir -p $(LIBDIR)/$(CONFIG)/zlib
$(Q)cp third_party/zlib/libz.a $(LIBDIR)/$(CONFIG)/zlib
libs/$(CONFIG)/openssl/libssl.a:
$(LIBDIR)/$(CONFIG)/openssl/libssl.a:
$(E) "[MAKE] Building openssl for $(SYSTEM)"
ifeq ($(SYSTEM),Darwin)
$(Q)(cd third_party/openssl ; CC="$(CC) -fPIC -fvisibility=hidden $(CPPFLAGS_$(CONFIG)) $(OPENSSL_CFLAGS_$(CONFIG))" ./Configure darwin64-x86_64-cc $(OPENSSL_CONFIG_$(CONFIG)))
@ -358,15 +444,30 @@ else
endif
$(Q)$(MAKE) -C third_party/openssl clean
$(Q)$(MAKE) -C third_party/openssl build_crypto build_ssl
$(Q)mkdir -p libs/$(CONFIG)/openssl
$(Q)cp third_party/openssl/libssl.a third_party/openssl/libcrypto.a libs/$(CONFIG)/openssl
$(Q)mkdir -p $(LIBDIR)/$(CONFIG)/openssl
$(Q)cp third_party/openssl/libssl.a third_party/openssl/libcrypto.a $(LIBDIR)/$(CONFIG)/openssl
third_party/protobuf/configure:
$(E) "[AUTOGEN] Preparing protobuf"
$(Q)(cd third_party/protobuf ; autoreconf -f -i -Wall,no-obsolete)
$(LIBDIR)/$(CONFIG)/protobuf/libprotobuf.a: third_party/protobuf/configure
$(E) "[MAKE] Building protobuf"
$(Q)(cd third_party/protobuf ; CC="$(CC)" CXX="$(CXX)" LDFLAGS="$(LDFLAGS_$(CONFIG)) -g" CXXFLAGS="-DLANG_CXX11 -std=c++11" CPPFLAGS="$(CPPFLAGS_$(CONFIG)) -g" ./configure --disable-shared --enable-static)
$(Q)$(MAKE) -C third_party/protobuf clean
$(Q)$(MAKE) -C third_party/protobuf
$(Q)mkdir -p $(LIBDIR)/$(CONFIG)/protobuf
$(Q)mkdir -p $(BINDIR)/$(CONFIG)/protobuf
$(Q)cp third_party/protobuf/src/.libs/libprotoc.a $(LIBDIR)/$(CONFIG)/protobuf
$(Q)cp third_party/protobuf/src/.libs/libprotobuf.a $(LIBDIR)/$(CONFIG)/protobuf
$(Q)cp third_party/protobuf/src/protoc $(BINDIR)/$(CONFIG)/protobuf
static: static_c static_cxx
static_c: \
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c':
libs/$(CONFIG)/lib${lib.name}.a\
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
% endif
% endfor
@ -374,7 +475,7 @@ static_c: \
static_cxx: \
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c++':
libs/$(CONFIG)/lib${lib.name}.a\
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
% endif
% endfor
@ -384,7 +485,7 @@ shared: shared_c shared_cxx
shared_c: \
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c':
libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
$(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
% endif
% endfor
@ -392,7 +493,7 @@ shared_c: \
shared_cxx: \
% for lib in libs:
% if lib.build == 'all' and lib.language == 'c++':
libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
$(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
% endif
% endfor
@ -402,7 +503,7 @@ privatelibs: privatelibs_c privatelibs_cxx
privatelibs_c: \
% for lib in libs:
% if lib.build == 'private' and lib.language == 'c':
libs/$(CONFIG)/lib${lib.name}.a\
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
% endif
% endfor
@ -410,7 +511,7 @@ privatelibs_c: \
privatelibs_cxx: \
% for lib in libs:
% if lib.build == 'private' and lib.language == 'c++':
libs/$(CONFIG)/lib${lib.name}.a\
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a\
% endif
% endfor
@ -420,7 +521,7 @@ buildtests: buildtests_c buildtests_cxx
buildtests_c: privatelibs_c\
% for tgt in targets:
% if tgt.build == 'test' and not tgt.language == 'c++':
bins/$(CONFIG)/${tgt.name}\
$(BINDIR)/$(CONFIG)/${tgt.name}\
% endif
% endfor
@ -428,7 +529,7 @@ buildtests_c: privatelibs_c\
buildtests_cxx: privatelibs_cxx\
% for tgt in targets:
% if tgt.build == 'test' and tgt.language == 'c++':
bins/$(CONFIG)/${tgt.name}\
$(BINDIR)/$(CONFIG)/${tgt.name}\
% endif
% endfor
@ -439,7 +540,7 @@ test_c: buildtests_c
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and not tgt.language == 'c++':
$(E) "[RUN] Testing ${tgt.name}"
$(Q) ./bins/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
$(Q) $(BINDIR)/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
% endfor
@ -448,7 +549,7 @@ test_cxx: buildtests_cxx
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and tgt.language == 'c++':
$(E) "[RUN] Testing ${tgt.name}"
$(Q) ./bins/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
$(Q) $(BINDIR)/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
% endfor
@ -456,7 +557,7 @@ test_cxx: buildtests_cxx
tools: privatelibs\
% for tgt in targets:
% if tgt.build == 'tool':
bins/$(CONFIG)/${tgt.name}\
$(BINDIR)/$(CONFIG)/${tgt.name}\
% endif
% endfor
@ -464,7 +565,7 @@ tools: privatelibs\
buildbenchmarks: privatelibs\
% for tgt in targets:
% if tgt.build == 'benchmark':
bins/$(CONFIG)/${tgt.name}\
$(BINDIR)/$(CONFIG)/${tgt.name}\
% endif
% endfor
@ -488,7 +589,7 @@ ifeq ($(CONFIG),opt)
% if lib.language == "c":
% if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.a"
$(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.a
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a
% endif
% endif
% endfor
@ -500,7 +601,7 @@ ifeq ($(CONFIG),opt)
% if lib.language == "c++":
% if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.a"
$(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.a
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a
% endif
% endif
% endfor
@ -512,7 +613,7 @@ ifeq ($(CONFIG),opt)
% if lib.language == "c":
% if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.so"
$(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)
% endif
% endif
% endfor
@ -524,36 +625,40 @@ ifeq ($(CONFIG),opt)
% if lib.language == "c++":
% if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.so"
$(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)
% endif
% endif
% endfor
endif
% for p in protos:
gens/${p}.pb.cc: ${p}.proto $(PROTOC_PLUGINS)
ifeq ($(NO_PROTOC),true)
$(GENDIR)/${p}.pb.cc: protoc_dep_error
else
$(GENDIR)/${p}.pb.cc: ${p}.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=gens --grpc_out=gens --plugin=protoc-gen-grpc=bins/$(CONFIG)/cpp_plugin $<
$(Q) $(PROTOC) --cpp_out=$(GENDIR) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/cpp_plugin $<
endif
% endfor
objs/$(CONFIG)/%.o : %.c
$(OBJDIR)/$(CONFIG)/%.o : %.c
$(E) "[C] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CC) $(CFLAGS) $(CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
objs/$(CONFIG)/%.o : gens/%.pb.cc
$(OBJDIR)/$(CONFIG)/%.o : $(GENDIR)/%.pb.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
objs/$(CONFIG)/src/compiler/%.o : src/compiler/%.cc
$(OBJDIR)/$(CONFIG)/src/compiler/%.o : src/compiler/%.cc
$(E) "[HOSTCXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(HOST_CXX) $(HOST_CXXFLAGS) $(HOST_CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
objs/$(CONFIG)/%.o : %.cc
$(OBJDIR)/$(CONFIG)/%.o : %.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
@ -582,7 +687,7 @@ install-static_c: static_c strip-static_c
% if lib.language == "c":
% if lib.build == "all":
$(E) "[INSTALL] Installing lib${lib.name}.a"
$(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
% endif
% endif
% endfor
@ -592,7 +697,7 @@ install-static_cxx: static_cxx strip-static_cxx
% if lib.language == "c++":
% if lib.build == "all":
$(E) "[INSTALL] Installing lib${lib.name}.a"
$(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
% endif
% endif
% endfor
@ -603,11 +708,11 @@ install-shared_c: shared_c strip-shared_c
% if lib.build == "all":
ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)"
$(Q) $(INSTALL) libs/$(CONFIG)/${lib.name}.$(SHARED_EXT) $(prefix)/lib/${lib.name}.$(SHARED_EXT)
$(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/${lib.name}.$(SHARED_EXT) $(prefix)/lib/${lib.name}.$(SHARED_EXT)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a
else
$(E) "[INSTALL] Installing lib${lib.name}.$(SHARED_EXT)"
$(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.$(SHARED_EXT)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.$(SHARED_EXT)
ifneq ($(SYSTEM),Darwin)
$(Q) ln -sf lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so
endif
@ -627,11 +732,11 @@ install-shared_cxx: shared_cxx strip-shared_cxx
% if lib.build == "all":
ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)"
$(Q) $(INSTALL) libs/$(CONFIG)/${lib.name}.$(SHARED_EXT) $(prefix)/lib/${lib.name}.$(SHARED_EXT)
$(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/${lib.name}.$(SHARED_EXT) $(prefix)/lib/${lib.name}.$(SHARED_EXT)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a
else
$(E) "[INSTALL] Installing lib${lib.name}.$(SHARED_EXT)"
$(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.$(SHARED_EXT)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.$(SHARED_EXT)
ifneq ($(SYSTEM),Darwin)
$(Q) ln -sf lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so
endif
@ -646,7 +751,7 @@ endif
endif
clean:
$(Q) $(RM) -rf objs libs bins gens
$(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR)
# The various libraries
@ -684,7 +789,7 @@ PUBLIC_HEADERS_C += \\
% endfor
% endif
LIB${lib.name.upper()}_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(LIB${lib.name.upper()}_SRC))))
LIB${lib.name.upper()}_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIB${lib.name.upper()}_SRC))))
## If the library requires OpenSSL with ALPN, let's add some restrictions.
% if lib.get('secure', True):
@ -692,46 +797,89 @@ ifeq ($(NO_SECURE),true)
# You can't build secure libraries if you don't have OpenSSL with ALPN.
libs/$(CONFIG)/lib${lib.name}.a: openssl_dep_error
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a: openssl_dep_error
% if lib.build == "all":
ifeq ($(SYSTEM),MINGW32)
libs/$(CONFIG)/${lib.name}.$(SHARED_EXT): openssl_dep_error
$(LIBDIR)/$(CONFIG)/${lib.name}.$(SHARED_EXT): openssl_dep_error
else
libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT): openssl_dep_error
$(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT): openssl_dep_error
endif
% endif
else
% if lib.language == 'c++':
ifeq ($(NO_PROTOBUF),true)
# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a: protobuf_dep_error
% if lib.build == "all":
ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/${lib.name}.$(SHARED_EXT): protobuf_dep_error
else
$(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT): protobuf_dep_error
endif
% endif
else
% endif
ifneq ($(OPENSSL_DEP),)
# This is to ensure the embedded OpenSSL is built beforehand, properly
# installing headers to their final destination on the drive. We need this
# otherwise parallel compilation will fail if a source is compiled first.
% for src in lib.src:
${src}: $(OPENSSL_DEP)
% endfor
endif
libs/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(LIB${lib.name.upper()}_OBJS)
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP) $(OPENSSL_DEP)\
## The else here corresponds to the if secure earlier.
% else:
libs/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP) $(LIB${lib.name.upper()}_OBJS)
% if lib.language == 'c++':
ifeq ($(NO_PROTOBUF),true)
# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a: protobuf_dep_error
% if lib.build == "all":
ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/${lib.name}.$(SHARED_EXT): protobuf_dep_error
else
$(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT): protobuf_dep_error
endif
% endif
else
% endif
$(LIBDIR)/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP)\
% endif
% if lib.language == 'c++':
$(PROTOBUF_DEP)\
% endif
$(LIB${lib.name.upper()}_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) rm -f libs/$(CONFIG)/lib${lib.name}.a
$(Q) $(AR) rcs libs/$(CONFIG)/lib${lib.name}.a $(LIB${lib.name.upper()}_OBJS)
$(Q) rm -f $(LIBDIR)/$(CONFIG)/lib${lib.name}.a
$(Q) $(AR) rcs $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(LIB${lib.name.upper()}_OBJS)
% if lib.get('baselib', False):
% if lib.get('secure', True):
$(Q) rm -rf tmp-merge
$(Q) mkdir tmp-merge
$(Q) ( cd tmp-merge ; $(AR) x ../libs/$(CONFIG)/lib${lib.name}.a )
$(Q) ( cd tmp-merge ; $(AR) x ../$(LIBDIR)/$(CONFIG)/lib${lib.name}.a )
$(Q) for l in $(OPENSSL_MERGE_LIBS) ; do ( cd tmp-merge ; <%text>ar x ../$${l}</%text> ) ; done
$(Q) rm -f libs/$(CONFIG)/lib${lib.name}.a tmp-merge/__.SYMDEF*
$(Q) ar rcs libs/$(CONFIG)/lib${lib.name}.a tmp-merge/*
$(Q) rm -f $(LIBDIR)/$(CONFIG)/lib${lib.name}.a tmp-merge/__.SYMDEF*
$(Q) ar rcs $(LIBDIR)/$(CONFIG)/lib${lib.name}.a tmp-merge/*
$(Q) rm -rf tmp-merge
% endif
% endif
ifeq ($(SYSTEM),Darwin)
$(Q) ranlib libs/$(CONFIG)/lib${lib.name}.a
$(Q) ranlib $(LIBDIR)/$(CONFIG)/lib${lib.name}.a
endif
<%
@ -740,8 +888,8 @@ endif
else:
ld = '$(LD)'
out_base = 'libs/$(CONFIG)/' + lib.name
out_libbase = 'libs/$(CONFIG)/lib' + lib.name
out_base = '$(LIBDIR)/$(CONFIG)/' + lib.name
out_libbase = '$(LIBDIR)/$(CONFIG)/lib' + lib.name
common = '$(LIB' + lib.name.upper() + '_OBJS) $(LDLIBS)'
@ -751,9 +899,9 @@ endif
mingw_lib_deps = ' $(ZLIB_DEP)'
for dep in lib.get('deps', []):
libs = libs + ' -l' + dep
lib_deps = lib_deps + ' libs/$(CONFIG)/lib' + dep + '.$(SHARED_EXT)'
lib_deps = lib_deps + ' $(LIBDIR)/$(CONFIG)/lib' + dep + '.$(SHARED_EXT)'
mingw_libs = mingw_libs + ' -l' + dep + '-imp'
mingw_lib_deps = mingw_lib_deps + 'libs/$(CONFIG)/' + dep + '.$(SHARED_EXT)'
mingw_lib_deps = mingw_lib_deps + '$(LIBDIR)/$(CONFIG)/' + dep + '.$(SHARED_EXT)'
if lib.get('secure', True):
common = common + ' $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS)'
@ -766,24 +914,29 @@ ifeq ($(SYSTEM),MINGW32)
${out_base}.$(SHARED_EXT): $(LIB${lib.name.upper()}_OBJS) ${mingw_lib_deps}
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) ${ld} $(LDFLAGS) -Llibs/$(CONFIG) -shared -Wl,--output-def=${out_base}.def -Wl,--out-implib=${out_libbase}-imp.a -o ${out_base}.$(SHARED_EXT) ${common}${mingw_libs}
$(Q) ${ld} $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=${out_base}.def -Wl,--out-implib=${out_libbase}-imp.a -o ${out_base}.$(SHARED_EXT) ${common}${mingw_libs}
else
${out_libbase}.$(SHARED_EXT): $(LIB${lib.name.upper()}_OBJS) ${lib_deps}
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin)
$(Q) ${ld} $(LDFLAGS) -Llibs/$(CONFIG) -dynamiclib -o ${out_libbase}.$(SHARED_EXT) ${common}${libs}
$(Q) ${ld} $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -dynamiclib -o ${out_libbase}.$(SHARED_EXT) ${common}${libs}
else
$(Q) ${ld} $(LDFLAGS) -Llibs/$(CONFIG) -shared -Wl,-soname,lib${lib.name}.so.${settings.version.major} -o ${out_libbase}.$(SHARED_EXT) ${common}${libs}
$(Q) ${ld} $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,lib${lib.name}.so.${settings.version.major} -o ${out_libbase}.$(SHARED_EXT) ${common}${libs}
$(Q) ln -sf lib${lib.name}.$(SHARED_EXT) ${out_libbase}.so.${settings.version.major}
$(Q) ln -sf lib${lib.name}.$(SHARED_EXT) ${out_libbase}.so
endif
endif
% endif
% if lib.get('secure', True):
## If the lib was secure, we have to close the Makefile's if that tested
## the presence of an ALPN-capable OpenSSL.
% if lib.get('secure', True):
endif
% endif
% if lib.language == 'c++':
## If the lib was C++, we have to close the Makefile's if that tested
## the presence of protobuf 3.0.0+
endif
% endif
@ -800,7 +953,7 @@ endif
% for src in lib.src:
% if not proto_re.match(src):
objs/$(CONFIG)/${os.path.splitext(src)[0]}.o: \
$(OBJDIR)/$(CONFIG)/${os.path.splitext(src)[0]}.o: \
% for src2 in lib.src:
% if proto_re.match(src2):
${proto_to_cc(src2)}\
@ -819,14 +972,14 @@ ${tgt.name.upper()}_SRC = \\
% endfor
${tgt.name.upper()}_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(${tgt.name.upper()}_SRC))))
${tgt.name.upper()}_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(${tgt.name.upper()}_SRC))))
% if tgt.get('secure', True):
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL with ALPN.
bins/$(CONFIG)/${tgt.name}: openssl_dep_error
$(BINDIR)/$(CONFIG)/${tgt.name}: openssl_dep_error
else
@ -840,9 +993,22 @@ else
## That simplifies the codegen a bit, but prevents a fully defined Makefile.
## I can live with that.
##
bins/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\
% if tgt.build == 'protoc':
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/${tgt.name}: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/${tgt.name}: $(PROTOBUF_DEP) $(${tgt.name.upper()}_OBJS)\
% else:
$(BINDIR)/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\
% endif
% for dep in tgt.deps:
libs/$(CONFIG)/lib${dep}.a\
$(LIBDIR)/$(CONFIG)/lib${dep}.a\
% endfor
% if tgt.language == "c++":
@ -866,13 +1032,13 @@ bins/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\
$(Q) $(LD) $(LDFLAGS) $(${tgt.name.upper()}_OBJS)\
% endif
% for dep in tgt.deps:
libs/$(CONFIG)/lib${dep}.a\
$(LIBDIR)/$(CONFIG)/lib${dep}.a\
% endfor
% if tgt.language == "c++":
% if tgt.build == 'protoc':
$(HOST_LDLIBSXX)\
$(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC)\
% else:
$(LDLIBSXX)\
$(LDLIBSXX) $(LDLIBS_PROTOBUF)\
% endif
% endif
% if tgt.build == 'protoc':
@ -885,16 +1051,20 @@ bins/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\
% elif tgt.get('secure', True):
$(LDLIBS_SECURE)\
% endif
-o bins/$(CONFIG)/${tgt.name}
-o $(BINDIR)/$(CONFIG)/${tgt.name}
% if tgt.build == 'protoc':
endif
% endif
% if tgt.get('secure', True):
endif
% endif
% for src in tgt.src:
objs/$(CONFIG)/${os.path.splitext(src)[0]}.o: \
$(OBJDIR)/$(CONFIG)/${os.path.splitext(src)[0]}.o: \
% for dep in tgt.deps:
libs/$(CONFIG)/lib${dep}.a\
$(LIBDIR)/$(CONFIG)/lib${dep}.a\
% endfor
% endfor

@ -0,0 +1,79 @@
<%!
import re
%>\
<%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\
<%
allowed_dependencies = set(['gpr', 'grpc', 'gpr_test_util', 'grpc_test_util'])
buildable_targets = [ target for target in targets if set(target.deps).issubset(allowed_dependencies) and all([src.endswith('.c') for src in target.src])]
test_targets = [ target for target in buildable_targets if target.name.endswith('_test') ]
%>\
# NMake file to build secondary gRPC targets on Windows.
# Use grpc.sln to solution to build the gRPC libraries.
OUT_DIR=test_bin
CC=cl.exe
LINK=link.exe
INCLUDES=/I..\.. /I..\..\include /I..\..\third_party\zlib /I..\third_party /I..\..\third_party\openssl\inc32
DEFINES=/D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /D _CRT_SECURE_NO_WARNINGS
CFLAGS=/c $(INCLUDES) /nologo /Z7 /W3 /WX- /sdl $(DEFINES) /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze-
LFLAGS=/DEBUG /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86
OPENSSL_LIBS=..\..\third_party\openssl\out32\ssleay32.lib ..\..\third_party\openssl\out32\libeay32.lib
WINSOCK_LIBS=ws2_32.lib
ZLIB_LIBS=Debug\zlibwapi.lib
LIBS=$(OPENSSL_LIBS) $(WINSOCK_LIBS) $(ZLIB_LIBS)
gpr_test_util:
MSBuild.exe gpr_test_util.vcxproj /p:Configuration=Debug
grpc_test_util:
MSBuild.exe grpc_test_util.vcxproj /p:Configuration=Debug
$(OUT_DIR):
mkdir $(OUT_DIR)
buildtests: \
% for target in test_targets:
${target.name}.exe \
% endfor
echo All tests built.
test: \
% for target in test_targets:
${target.name} \
% endfor
echo All tests ran.
test_gpr: \
% for target in [ tgt for tgt in test_targets if tgt.name.startswith('gpr_')]:
${target.name} \
% endfor
echo All tests ran.
% for target in buildable_targets:
${target.name}.exe: grpc_test_util
echo Building ${target.name}
$(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ \
%for source in target.src:
..\..\${to_windows_path(source)} \
%endfor
$(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\${target.name}.exe" \
%for dep in target.deps:
Debug\${dep}.lib \
%endfor
$(LIBS) \
%for source in target.src:
$(OUT_DIR)\${re.search('([^/]+)\.c$', source).group(1)}.obj \
%endfor
${target.name}: ${target.name}.exe
echo Running ${target.name}
$(OUT_DIR)\${target.name}.exe
% endfor

@ -1,40 +0,0 @@
<%!
import re
%>\
<%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\
<%
test_targets = [ target for target in targets if target.name.startswith('gpr_') and target.name.endswith('_test')]
test_bin_dir = 'test_bin'
%>\
@rem Build and runs unit all unit tests
@rem Set VS variables
@call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
@rem Build the library dependencies first
MSBuild.exe gpr.vcxproj /p:Configuration=Debug
MSBuild.exe gpr_test_util.vcxproj /p:Configuration=Debug
mkdir ${test_bin_dir}
% for target in test_targets:
echo Building test ${target.name}
cl.exe /c /I..\.. /I..\..\include /nologo /Z7 /W3 /WX- /sdl /D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- /Fo:${test_bin_dir}\ \
%for source in target.src:
..\..\${to_windows_path(source)} \
%endfor
link.exe /DEBUG /OUT:"${test_bin_dir}\${target.name}.exe" /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 \
%for dep in target.deps:
Debug\${dep}.lib \
%endfor
%for source in target.src:
${test_bin_dir}\${re.search('([^/]+)\.c$', source).group(1)}.obj \
%endfor
echo(
echo Running test ${target.name}
${test_bin_dir}\${target.name}.exe || echo TEST FAILED: ${target.name} && exit /b
echo(
% endfor

@ -0,0 +1,10 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
bool protobuf_test(const google::protobuf::MethodDescriptor *method) {
return method->client_streaming() || method->server_streaming();
}
int main() {
return 0;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save