The Wayback Machine - https://web.archive.org/web/20160314183821/http://eli.thegreenplace.net/

gRPC sample in C++ and Python



Almost exactly five years ago I posted a code sample of using the Protocol Buffers library for client-server communication. Even though protobufs are very convenient for serializing/deserializing data in multiple languages, I had to roll my own networking layer for the actual client and server.

I resorted to using boost::asio (which is on its way into C++17, by the way) to ease on the details in the C++ server. But even boost::asio won't do everything for you; for example, actually putting serialized protobufs on the wire requires additional mechanisms like length-prefixing and a special enumeration value in every message to select the request type ("message polymorphism"). It's a lot of custom coding for a problem that was solved long ago.

The reality is that I was hand-rolling a simple RPC implementation. Now, in 2016 it's no longer necessary as Google has recently open-sourced gRPC, the yang to the Protocol Buffers yin. gRPC expands the protobuf specification to define RPC services and then auto-generates server and client code from them, taking care of the whole networking layer. All you have remaining is to implement your custom application logic. gRPC is very new (still in beta, and only released last year), but it's a rewrite of the Google-internal Stubby system which has been used for at least a decade for the same purpose. Google appears to be committed to maintaining gRPC in the long haul since it uses it as the API for some of its cloud offerings.

gRPC diagram from www.grpc.io

The code for the new sample is available in full here. Here is the message / service definition:

syntax = "proto3";

package stringdb;

service StringDb {
  // Get the value stored on the server for a given key
  rpc GetValue (GetValueRequest) returns (GetValueReply) {}

  // Set the server's value for a given key
  rpc SetValue (SetValueRequest) returns (SetValueReply) {}

  // Count the size of the server's value for a given key
  rpc CountValue (CountValueRequest) returns (CountValueReply) {}
}

message GetValueRequest {
  string key = 1;
}

message GetValueReply {
  // Empty string returned when key not found on the server.
  string value = 1;
}

message SetValueRequest {
  string key = 1;
  string value = 2;
}

message SetValueReply {
  // Returns the value.
  string value = 1;
}

message CountValueRequest {
  string key = 1;
}

message CountValueReply {
  // Returns the size of the value, in bytes. If key isn't found on the server,
  // returns -1.
  int64 count = 1;
}

It's longer than before because now it also specifies the service, which is an RPC contract the server and the client implement. We get a lot of buck from gRPC for this simple definition, because now the networking server logic is rolled into ~10 lines of C++ code. The vast majority of the code is spent imlementing the server-side RPC methods. Here's an example:

grpc::Status GetValue(grpc::ServerContext* context,
                      const stringdb::GetValueRequest* request,
                      stringdb::GetValueReply* reply) override {
  // Get data from request; do work; populate reply; return a status.
  return grpc::Status::OK;
}

On the Python side, all the client has to do is:

channel = implementations.insecure_channel('localhost', PORT)
stub = stringdb_pb2.beta_create_StringDb_stub(channel)

...

# Invoke methods on the stub...

request = stringdb_pb2.CountValueRequest(key=key)
response = stub.CountValue(request, TIMEOUT_SECONDS)
return response.count

It's quite incredible how much code gRPC saves you from writing... just compare to the previous sample!

But that's not all. What I have here is a very simplistic service. gRPC gives us many advanced features out of the box that would take serious time investment to implement:

  • HTTP/2 support out of the box (reduced latency over traditional HTTP servers)
  • Multi-language support for the network layers, not only data (de)serialization. Want to write your server in Go and client in Objective C? No problem
  • Performance through thread pools and other server implementation variations
  • Authentication with SSL/TLS or OAuth
  • Blocking and non-blocking servers and clients
  • Streaming
  • Flow-control
  • Cancellation and timeouts on RPC calls

Installing gRPC on an Ubuntu box was pretty simple. I just went through the instructions in their INSTALL.md file to build and install it from source. The Python plugin and related code can be installed with pip (be sure to use a virtualenv). One small wrinkle I ran into is that you also have to make install the protobuf library (pulled in as a Git submodule by the gRPC checkout process). Even though gRPC's Makefile compiles it, it doesn't install it.

Link to the code.


Returning multiple values from functions in C++



Since C++ has no built-in syntax for returning multiple values from functions and methods, programmers have been using a number of techniques to simulate this when needed, and the number has grown since the introduction of C++11. In this post I want to provide an overview of some of the options we have today for returning multiple values from functions, and possible future directions in the language.

Introduction - why multiple return values?

Multiple return values from functions are not a new concept in programming - some old and venerable languages like Common Lisp have had them since the early 1980s.

There are many scenarios where multiple return values are useful:

First and foremost, for functions that naturally have more than one value to compute. For example, the Common Lisp floor function computes the quotient and the remainder of its two operands, and returns both. Another example is std::minmax in C++11, that finds the minimal and the maximal value in a container simultaneously.

Second, multiple return values are helpful when the data structure the function operates on contains multiple values per entry. For example, Python 3's dict.items is an iterator over key / value pairs, and each iteration returns both, which is frequently useful. Similarly, in C++ the mapping family of containers provides iterators that hold key / value pairs, and methods like std::map::find logically return a pair, even though it's encapsulated in an iterator object. Another related, but slightly different example is Python's enumerate, which takes any sequence or iterator and returns index / value pairs - very useful for writing some kinds of for loops.

Third, the multiple return values may signal different "paths" - like error conditions or "not found" flags, in addition to actual values. In Go, map lookup returns a value / found pair, where "found" is a boolean flag saying whether the key was found in the map. In general, in Go it's idiomatic to return a value / error pair from functions. This method is useful in C++ as well, and I'll cover an example in the next section.

Multiple return values are so convenient that programmers usually find ways to simulate them even in languages that don't support them directly. As for new programming languages, most of them come with this feature natively supported. Go, Swift, Clojure, Rust and Scala all support multiple return values.

Multiple return values in C++ with output parameters

Back to C++, let's start our quest with the oldest and possibly still most common method - using some of the function's parameters as "out" parameters. This method is made possible by C++ (based on C before it) making a strict distinction between parameters passed by value and by reference (or pointer) into functions. Parameters passed by pointers can be used to "return" values to the caller.

This technique has old roots in C, where it's used in many places in the standard library; for example fgets and fscanf. Many POSIX functions adopt the conventions of returning an integer "error code" (0 for success), while writing any output they have into an output parameter. Examples abound - gettimeofday, pthread_create... there are hundreds (or thousands). This has become such a common convention that some code-bases adopt a special marker for output parameters, either with a comment or a dummy macro. This is to distinguish by-pointer input parameters from output parameters in the function signature, thus signaling to the user which is which:

#define OUT

int myfunc(int input1, int* input2, OUT int* out) {
   ...
}

C++ employs this technique in the standard library as well. A good example is the std::getline function. Here's how we read everything from stdin and echo every line back with a prefix:

#include <iostream>
#include <string>

int main(int argc, const char** argv) {
  std::string line;
  while (std::getline(std::cin, line)) {
    std::cout << "echo: " << line << "\n";
  }
  return 0;
}

std::getline writes the line it has read into its second parameter. It returns the stream (the first parameter), since a C++ stream has interesting behavior in boolean context. It's true so long as everything is OK, but flips to false once an error occurs, or an end-of-file condition is reached. The latter is what the sample above uses to concisely invoke std::getline in the condition of a while loop.

C++'s introduction of reference types adds a choice over the C approach. Do we use pointers or references for output parameters? On one hand references result in simpler syntax (if the line would have to be passed by pointer in the code above, we'd have to use &line in the call) and also cannot be nullptr, which is important for output parameters. On the other hand, with references it is very hard to look at a call and discern which parameters are input and which are output. Also, the nullptr argument works both ways - occasionally it is useful to convey to the callee that some output is not needed and a nullptr in an output parameter is a common way to do this.

As a result, some coding guidelines recommend only using pointers for output parameters, while using const references for input parameters. But as with all issues of style, YMMV.

Whichever style you pick, this approach has obvious downsides:

  • The output values are not uniform - some are returned, some are parameters, and it's not easy to know which parameters are for output. std::getline is simple enough, but when your function takes 4 and returns 3 values, things start getting hairy.
  • Calls require declarations of output parameters beforehead (such as line in the example above). This bloats the code.
  • Worse, the separation of parameter declaration from its assignment within the function call can result in uninitialized variables in some cases. To analyze whether line is initialized in the example above, one has to carefully understand the semantics of std::getline.

On the other hand, prior to the introduction of move semantics in C++11, this style had serious performance advantages over the alternatives, since it can avoid extra copying. I'll discuss this a bit more later on in the article.

Pairs and tuples

The std::pair type is a veteran in C++. It's used in a bunch of places in the standard library to do things like hold keys and values of mappings, or to hold "status, result" pairs. Here's an example that demonstrates both:

#include <iostream>
#include <unordered_map>

using map_int_to_string = std::unordered_map<int, std::string>;

void try_insert(map_int_to_string& m, int i, const std::string& s) {
  std::pair<map_int_to_string::iterator, bool> p = m.insert({i, s});

  if (p.second) {
    std::cout << "insertion succeeded. ";
  } else {
    std::cout << "insertion failed. ";
  }

  std::cout << "key=" << p.first->first << " value=" << p.first->second << "\n";
}

int main(int argc, const char** argv) {
  std::unordered_map<int, std::string> mymap;
  mymap[1] = "one";

  try_insert(mymap, 2, "two");
  try_insert(mymap, 1, "one");

  return 0;
}

The std::unordered_map::insert method returns two values: an element iterator and a boolen flag saying whether the requested pair was inserted or not (it won't be inserted if the key already exists in the map). What makes the example really interesting is that there are nested multiple values being returned here. insert returns a std::pair. But the first element of the pair, the iterator, is just a thin wrapper over another pair - the key/value pair - hence the first->first and first->second accesses we use when printing the values out.

Thus we also have an example of a shortcoming of std::pair - the obscureness of first and second, which requires us to always remember the relative positions of values within the pairs. p.first->second gets the job done but it's not exactly a paragon of readable code.

With C++11, we have an alternative - std::tie:

void try_insert_with_tie(map_int_to_string& m, int i, const std::string& s) {
  map_int_to_string::iterator iter;
  bool did_insert;
  std::tie(iter, did_insert) = m.insert({i, s});

  if (did_insert) {
    std::cout << "insertion succeeded. ";
  } else {
    std::cout << "insertion failed. ";
  }

  std::cout << "key=" << iter->first << " value=" << iter->second << "\n";
}

Now we can give the pair members readable names. The disadvantage of this approach is, of course, that we need the separate declarations that take extra space. Also, while in the original example we could use auto to infer the type of the pair (useful for really hairy iterators), here we have to declare them fully.

Pairs work for two return values, but sometimes we need more. C++11's introduction of variadic templates finally made it possible to add a generic tuple type into the standard library. A std::tuple is a generalization of a std::pair for multiple values. Here's an example:

std::tuple<int, std::string, float> create_a_tuple() {
  return std::make_tuple(20, std::string("baz"), 1.2f);
}

int main(int argc, const char** argv) {
  auto data = create_a_tuple();
  std::cout << "the int: " << std::get<0>(data) << "\n"
            << "the string: " << std::get<1>(data) << "\n"
            << "the float: " << std::get<2>(data) << "\n";

  return 0;
}

The std::get template is used to access tuple members. Again, this is not the friendliest syntax but we can alleviate it somewhat with std::tie:

int i;
std::string s;
float f;
std::tie(i, s, f) = create_a_tuple();
std::cout << "the int: " << i << "\n"
          << "the string: " << s << "\n"
          << "the float: " << f << "\n";

Another alternative is to use even more template metaprogramming magic to create a "named" tuple (similar to the Python namedtuple type). Here's an example. There are no standard solutions for this, though.

Structs

When faced with sophisticated "named tuple" implementations, old-timers snort and remind us that in the olden days of C, this problem already had a perfectly valid solution - a struct. Here's the last example rewritten using a struct:

struct RetVal {
  int inumber;
  std::string str;
  float fnumber;
};

RetVal create_a_struct() {
  return {20, std::string("baz"), 1.2f};
}

// ... usage

{
  // ...
  auto retvaldata = create_a_struct();
  std::cout << "the int: " << retvaldata.inumber << "\n"
            << "the string: " << retvaldata.str << "\n"
            << "the float: " << retvaldata.fnumber << "\n";
}

When the returned value is created, the syntax and nice an concise. We could even omit some of the fields if their default values are good enough (or the struct has constructors for partial field initialization). Also note how natural the access to the returned value's fields is: all fields have descriptive names - this is perfect! C99 went a step further here, allowing named initialization syntax for struct fields:

RetVal create_a_struct_named() {
  return {.inumber = 20, .str = std::string("baz"), .fnumber = 1.2f};
}

This is very useful for self-documenting code that doesn't force you to go peek into the RetVal type every time you want to decode a value. Unfortunately, even if your C++ compiler supports this, it's not standard C++, because C++ did not adopt the feature. Apparently there was an active proposal to add it, but it wasn't accepted; at least not yet.

The rationale of the C++ committee, AFAIU, is to prefer constructors to initialize struct fields. Still, since C++ functions don't have a named parameter ("keyword argument" in Python parlance) syntax, using ctors here wouldn't be more readable. What it would allow, though, is convenient non-zero default initialization values.

For example:

struct RetValInitialized {
  int inumber = 17;
  std::string str = "foobar";
  float fnumber = 2.24f;
};

RetValInitialized create_an_initialized_struct() {
  return {};
}

Or even fancier initialization patterns with a constructor:

struct RetValWithCtor {
  RetValWithCtor(int i)
    : inumber(i), str(i, 'x'), fnumber(i) {}

  int inumber;
  std::string str;
  float fnumber;
};

RetValWithCtor create_a_constructed_struct() {
  return {10};
}

This would also be a good place to briefly address the performance issue I mentioned earlier. In C++11, it's almost certain that structs returned by value will not actually copied due to the return-value optimization mechanism. Neither will the std::string held by value within the struct be copied. For even more details, see section 12.8 of the C++11 standard, in the paragraph starting with:

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization

This mechanism is called copy elision by the standard.

Structured bindings: a new hope for C++17

Luckily, the C++ standard committee consists of brilliant folks who have already recognized that even though C++ has many ways to do multiple return values, none is really perfect. So there's a new proposal making the rounds now for the C++17 edition of the language, called Structured bindings.

In brief, the idea is to support a new syntax that will make tying results of tuple-returning functions easier. Recall from the discussion above that while tuples have a fairly convenient syntax returning them from functions, the situation on the receiving side is less than optimal with a choice between clunky std::get calls or pre-declaration and std::tie.

What the proposal puts forward is the following syntax for receiving the tuple returned by create_a_tuple:

auto {i, s, f} = create_a_tuple();
// Note: proposed C++17 code, doesn't compile yet

The types of i, s and f are "auto"-inferred by the compiler from the return type of create_a_tuple. Moreover, a different enhancement of C++17 is to permit a shorter tuple creation syntax as well, removing the need for std::make_tuple and making it as concise as struct creation:

std::tuple<int, std::string, float> create_a_tuple() {
  return {20, std::string("baz"), 1.2f};
}
// Note: proposed C++17 code, doesn't compile yet

The structured bindings proposal is for returned struct values as well, not just tuples, so we'll be able to do this:

auto {i, s, f} = create_a_struct();

I sure hope this proposal will get accepted. It will make simple code pleasant to write and read, at no cost to the compiler and runtime.

Conclusion

So many possibilities, what to choose? Personally, since I believe code readability is more important than making it quick to compose, I like the explicit approach of wrapping multiple values in structs. When the returned values logically belong together, this is a great way to collect them in a natural self-documenting way. So this would be the approach I'd use most often.

That said, sometimes the two values returned really don't belong together in any logical sense - such as a stream and a string in the getline example. Littering the source code with one-off struct types named StreamAndResult or OutputAndStatus is far from ideal, so in these cases I'd actually consider a std::pair or a std::tuple.

It goes without saying that the proposed structured bindings in C++17 can make all of this even easier to write, making folks less averse to the current verboseness of tuples.


C++: RAII without exceptions



I've read a random quote online about "RAII in C++ is only possible with exceptions" once too much. I can't take it any more.

XKCD 386

TL; DR: this post is not about whether exceptions are good or bad. What it is about is RAII as a C++ dynamic resource management technique that stands on its own and is useful with or without exceptions. In particular, I want to explain why RAII is indeed useful even if you have exceptions disabled in your C++ code.

The basics

Let's take the poster child of RAII, an auto-closing handle to wrap FILE* [1]:

class FileHandle {
  public:
    FileHandle(const char* name, const char* mode) {
      f_ = fopen(name, mode);
    }

    FILE* file() {
      return f_;
    }

    ~FileHandle() {
      if (f_ != nullptr) {
        fclose(f_);
      }
    }

  private:
    FILE* f_;
};

Here's an example of how we'd use it:

std::string do_stuff_with_file(std::string filename) {
  FileHandle handle(filename.c_str(), "r");
  int firstchar = fgetc(handle.file());

  if (firstchar != '$') {
    return "bad bad bad";
  }

  return std::string(1, firstchar);
}

Remember: no exceptions here - the code is built with -fno-exceptions and there are no try statements. However, the RAII-ness of FileHandle is still important because do_stuff_with_file has two exit points, and the file has to be closed in each one. do_stuff_with_file is a short and simple function. In a larger function with multiple exit points managing resource release becomes even more error prone, and RAII techniques are paramount.

The essence of RAII is to acquire some resource in the constructor of a stack-allocated object, and release it in the destructor. The compiler guarantees that the destructors of all stack-allocated objects will be called in the right order when these objects go out of scope, whether due to raised exceptions or just because the function returns.

RAII doesn't mean you have to allocate or actually create anything in a constructor. It can do any operation that has a logical "undo" that must be performed later on. A good example is reference counting. Many databases and similar software libraries have abstractions of "cursors" that provide access to data. Here's how we could increase and decrease the reference count on a given cursor safely while working with it:

class CursorGuard {
public:
  CursorGuard(Cursor* cursor) : cursor_(cursor) {
    cursor_->incref();
  }

  Cursor* cursor() {
    return cursor_;
  }

  ~CursorGuard() {
    cursor_->decref();
  }

private:
  Cursor* cursor_;
};


void work_with_cursor(Cursor* cursor) {
  CursorGuard cursor_guard(cursor);

  if (cursor_guard.cursor()->do_stuff()) {
    // ... do something
    return;
  }

  // ... do something else
  return;
}

Once again, usage of RAII here ensures that under no circumstances work_with_cursor will leak a cursor reference: once incref'd, it is guaranteed to be decref's no matter how the function ends up returning.

RAII in the standard library

Such "guard" RAII classes are extremely useful and widespread, even in the standard library. The C++11 threading library has lock_guard for mutexes, for example:

void safe_data_munge(std::mutex& shared_mutex, Data* shared_data) {
  std::lock_guard<std::mutex> lock(shared_mutex);
  shared_data->munge();

  if (...) {
    shared_data();
    return;
  }

  shared_data->munge_less();
  return;
}

std::lock_guard locks the mutex in its constructor, and unlocks it in its destructor, ensuring that access to the shared data is protected throughout safe_data_munge and the actual unlocking always happens.

RAII and C++11

While on the topic of the standard library, I can't fail mentioning the most important RAII object of them all - std::unique_ptr. Resource management in C and C++ is a big and complex subject; the most common kind of resource managed in C++ code is heap memory. Prior to C++11, there were many third party solutions for "smart pointers", and C++11's move semantics finally allowed the language to have a very robust smart pointer for RAII:

void using_big_data() {
  std::unique_ptr<VeryVeryBigData> data(new VeryVeryBigData);

  data->do_stuff();

  if (data->do_other_stuff(42)) {
    return;
  }

  data->do_stuff();
  return;
}

Whatever we do with data, and no matter where how function returns, the allocated memory will be released. If your compiler supports C++14, the line that creates the pointer can be made more succinct with std::make_unique:

// Good usage of 'auto': removes the need to repeat a (potentially long)
// type name, and the actual type assigned to 'data' is trivially obvious.
auto data = std::make_unique<VeryVeryBigData>();

std::unique_ptr is versatile and has other uses, though here I'm just focusing on its value as a RAII enabler for heap memory.

To to stress how important C++11 is for proper RAII: prior to C++11, without move semantics, the only "smart" pointers we could write were really somewhat dumb because they led to too much copying and overhead. There was simply no way to "transfer ownership" of an object from one function to another without considerable overhead. Since C++ programmers are often all about squeezing the last bit of performance from their code, many preferred to just live on the edge and deal with raw pointers. With C++11 and std::unique_ptr, which can be efficiently moved and occupies no additional memory, this problem is much less serious and safety doesn't have to come at the price of performance.

RAII in other languages

A common question asked about C++ is "why doesn't C++ have the finally construct enjoyed by other languages like Java, C# and Python?". The answer, given by Stroustrup himself is that RAII is a replacement. Stroustrup reasons (rightly, IMHO) that in realistic codebases there are far more resource acquisitions and releases than distinct "kinds" of resources, so RAII leads to less code. Besides, it's less error prone since you code the RAII wrapper once and don't have to remember to release the resource manually. Here's the work_with_cursor sample from above rewritten with a hypothetical finally construct:

// Warning: this is not real C++
void work_with_cursor(Cursor* cursor) {
  try {
    cursor->incref();

    if (cursor->do_stuff()) {
      // ... do something
      return;
    }

    // ... do something else
    return;
  }
  finally {
    cursor->decref();
  }
}

Yes, it's a bit more code. But the bigger problem is remembering to call cursor-decref(). Since large codebases juggle resources all the time, in practice you'll end up with try...finally blocks around every function's body and having to remember which resources to release. With our CursorGuard helper, all of that is saved at the cost of a one-time definition of the guard class itself.

A good example to mention here is Python. Even though Python has a finally construct, in modern Python code the alternative with statement is much more widely used. with supports "context managers", which are very similar to C++ RAII. with statements end up being more versatile and nice to use than finally, which is why you'll see more of them in idiomatic code.

So what about exceptions?

I hope that this post has, so far, convinced you that the RAII technique in C++ is important and useful even when exceptions are disabled. The close association people have between RAII and exceptions is warranted, however, because writing exception-safe code without RAII is nearly impossible. With exceptions enabled, we don't just have to examine each explicit return statement in a function to figure out where resources can be leaked. Every line becomes a suspect. Function or method call? Can throw. Creating a new non-POD object on the stack? Can throw. Copying one object to another? Yep, can throw. a + b? Can throw in the + operator.

Another strong link between exceptions and RAII is in constructors. Constructors cannot have return values. Therefore, if a constructor encounters an error condition, you either throw an exception or mark some internal error state. The latter has its issues (which is why alternative methods of construction are recommended in code without exceptions), so throwing an exception is the most common approach. Since RAII is so important for exceptions, and also because RAII and constructors go hand in hand (remember - RAII starts when an object is constructed), the link is burned deep into the minds of C++ students.

But RAII is not just about exceptions. It is about disciplined resource management in C++. Therefore, it makes no sense to assume that RAII somehow means your code is an exception-riddled mess. Or even that it uses exceptions at all. Attacking C++ for its exception safety woes is legitimate, but attacking RAII is less so because RAII is just a solution, it's not the source of the problem.

Finally, on a more personal note, I'll add that while I'm not a big fan of exceptions in C++, I am a huge fan of RAII. When I write C++ code these days, I would rather not use exceptions at all, or at least confine and constrain them to tiny areas in the program. But I use RAII all the time, whether in standard library classes like std::unique_ptr or in my own code. In my mind it's one of the best and most useful features of C++ to help keeping large code bases sane and safe.


[1]I'm not handling the error condition here. What if fopen failed? Since this post is specifically about exception-less code, throwing an exception is not an option. So some sort of error state is needed to be flagged and checked. There are multiple solutions to this issue, and I'll leave them to a separate post. By the way, a point for consideration: is a "file not found" condition truly horrific enough to warrant an exception? This is a deep question that deals with the very nature of what exceptions should and should not be used for.