Google APIs Client Library for C++ A C++ library for client applications to access Google APIs.
Foundation Types

This document discusses the basic types upon which the SDK is built. Some of these are introduced by the SDK itself, but are considered part of the foundation. They don't have much to do with interacting with cloud services as much as providing a programming environment.

Many of these types will appear throughout this Developer's Guide with the assumption that they are already understood. This is the only place many or all of these are documented.

Contents

  1. Primitive Values
  2. Strings and Byte Sequences
  3. Memory Management
  4. Error Status
  5. Synchronization
  6. Callbacks
  7. Executors

Primitive Values

Type Description
bool boolean values
int Native integer values assumed to be 32-bits but shouldn't matter.
int64

64-bit integer values.

int64 is also used where size_t might normally be used. The SDK defines this type in googleapis/base/integral_types.h.

double Native double values.
googleapis::client::DateTime

Date and time values.

The DateTime can convert into different standard date/time representations used by standard C libraries.

Strings and Byte Sequence

Type Description
char* These usually denote byte sequences. Sometimes, especially in the JSON related APIs, these are null-terminated C-strings.
std::string Standard C++ string objects are usually used for text. Sometimes string is used for the storage of binary byte sequences.
StringPiece

StringPiece is an encapsulation of a char* and its int64 length. The data is not null-terminated so can be any byte sequence. They are very light weight because they only reference the data and do not have a copy. However this means that the data must remain valid and unchanged over the lifetime of the instance. StringPiece has implicit constructors from string and char* where the char* assumes a null-terminated string for determining the length. You can also explicitly construct one and specify the length.

The SDK defines this type in strings/stringpiece.h.

#include "googleapis/strings/stringpiece.h"

// The use of asserts below is just for illustrative purposes.
void ExampleUsage() {
  StringPiece empty_stringpiece;

  // This works because "" is promoted to a StringPiece,
  // which has an '==' operator.
  assert(empty_stringpiece == "");

  string hello = "hello";
  StringPiece from_string = hello;
  StringPiece from_cstr = "hello";
  assert(from_string == hello);
  assert(from_str == hello);

  string bigstring = "hello, world!";
  StringPiece from_substr(bigstring.c_str(), hello.size());
  assert(from_substr == hello);
  assert(from_substr.data() == bigstring.c_str());

  string from_stringpiece = from_substr.as_string();
}

Memory Management

Type Description
scoped_ptr<T>

Scoped pointers are containers for dynamic objects. They overload -> and * operators to provide access the dynamic object making the container transparent. scoped_ptr owns the object and will delete the object when the container is destroyed.

scoped_ptr never appears in a public SDK interface however they are used as local variables and object attributes to indicate ownership.

malloc vs new Within the implementation of the googleapis::client namespace, malloc is used when out-of-memory errors are recoverable and new when they are fatal. we assume new will never return NULL however malloc may.
Pointers vs References vs Copy Constructors

The client APIs typically take references or const pointers to indicate that the caller retains ownership and non-const pointers to indicate that ownership is being passed to the method or object. A non-const pointer may also simply be an out parameter that is modified by the method.

Return results are similar where non-const pointers often pass ownership back, though might also be returning mutable state. These are documented by the APIs on a case-by-case basis. APIs never take or return non-const references.

Some parameters and results are objects passed by value. For return results, this is in cases where the objects are very lightweight or require copied memory but do not want to burden the caller with having to manage a dynamic object. Typical examples are googleapis::util::Status is always returned by value. Methods that transform strings return string by value whereas methods that return already-managed strings return references.

The googleapis::client::JsonCppData class uses a call-by-value syntax however the semantics are actually call-by-reference. See Using the JSON Data Model for more information about JsonCppData.

#include "googleapis/base/scoped_ptr.h"

void ProcessReference(const string& str);
void ProcessPointer(const string* str);

// The use of asserts below is just for illustrative purposes.
void SampleScopedPtr() {
  string local_string("hello");
  scoped_ptr<string> dynamic_string(new string("hello"));
  assert(*dynamic_string == local_string);
  assert(dynamic_string->size() == local_string.size());

  ProcessReference(local_string);
  ProcessReference(*dynamic_string);
  ProcessPointer(&local_string);
  ProcessPointer(dynamic_string.get());
}

Error Status

Type Description
googleapis::util::Status

A googleapis::util::Status is used to return errors (or success) as a return result or out-parameter. The status contains an error code and a message string explaining more details. In general a status should be used as a binary condition. It is either .ok() or it is not. If it is not .ok() then .error_message will provide more human-consumable details.

The types of errors returned by a given API currently undefined. Where there are specific values, they are only suggestive. Assume they will change in future versions of the API until further notice or explicitly documented.

The API always uses the full name googleapis::util::Status to avoid potential namespace collisions with external libraries since the name is so generic.

For more information on error handling, see the document Error Handling and Reporting.

bool Methods returning a bool usually use true for success and false otherwise.

#include "googleapis/client/util/status.h"
#include "googleapis/util/status.h"
using googleapis::client::StatusOk;
using googleapis::client::StatusUnknown;

googleapis::util::Status FunctionReturningStatus(int x) {
  if (x >= 0) return StatusOk();
  else return StatusInvalidArgument("Non-negative numbers required.");
}

void Example(int x) {
  googleapis::util::Status status = FunctionReturningStatus(x);
  if (!status.ok()) {
     cerr << "Function failed: " << status.error_message();
  }
}

Synchronization

Type Description
Mutex

A Mutex are non-rentrant mutexes. In general the client library is thread-friendly, not thread-safe, unless otherwise noted. That means that if you provide proper mutex locking in your code using this library then the result will be thread-safe.

Mutex is only used internally as an implementation detail and never exposed in a components public interface. However if you are writing multithreaded usage patterns requiring thread-safety, you may consider using Mutex for the mutex.

The SDK implements mutex in googleapis/base/mutex.h.

Condition A Condition is a condition variable that can be used for a thread to wait on. It requires another thread to eventually change state and signal the condition so the first may proceed. Like Mutex, condition variables are not exposed in the public API interfaces but you are welcome to use them from your code.
MutexLock MutexLock is used to grab and release a lock within a C++ scope. The lock takes a mutex in its constructor. It will lock the mutex when constructed and release the mutex when destroyed. The constructor will block on contention so the code between the lock and closing scope becomes a critical section.

#include "googleapis/base/mutex.h"
class MyClass {
  void MyThreadsafeMethod() {
    MutexLock l(&mutex_);
    // critical section
  }

  void AnotherThreadsafeMethod() {
    // outside critical section
    {
      MutexLock l(&mutex_);
      // inside critical section
    }
    // outside critical section
  }

  void ConditionWaiter(const int64 timeout_millis) {
    MutexLock l(&mutex_);
    if (mutex_.AwaitWithTimeout(condition_, timeout_millis)) {
       // in critical section with condition met
    } else {
      // in critical section with timeout before condition met
    }
  }

  void ConditionNotifier() {
    MutexLock l(&mutex_);
    // Tell anyone waiting on this condition that it has now been met.
    condition_.Notify();
  }

  private:
    Mutex mutex_;
    Condition condition_;
}

Callbacks

Type Description
Closure

A Closure is an executable object that can be Run(). It is like a function pointer but, being an object, can encapsulate additional state. The components in the SDK typically use closures where an API might desire a callback. Closures are always dynamic instances. They are never created on the stack.

Since Closure are dynamic, they must eventually be freed. A closure can be constructed in one of two modes: repeatable or one-time-usable. APIs expecting closures will document which type they need. Unless otherwise noted, a repeatable closure is owned by the caller and must be expicitly destroyed when no longer needed. A non-repeatable closure will manage itself and self-destruct after it is Run().

Closures are constructed using either NewCallback or NewPermanentCallback where 'permanent' means a repeatable closure. The closure's is_repeatable() method will tell you which type it is.

There are different variants of Closure that expect different numbers of arguments and/ore return results. These are named ResultCallbackN where N is the number of arguments. For result callbacks, the first template argument is the result type.

Finally, closures may be constructed with additional variables to pass when invoking their bound function. These bonus variables do not count as part of the specific ResultCallback's signature. See the example.

#include "googleapis/base/callback.h"
static void MyFunction();
class MyClass {
 public:
   void MyMethod();
   void MyMethodWithArg(int foo);
   string MyOtherMethod(const string& a, int b);
};

MyClass* me = new MyClass;

Closure* function_closure = NewCallback(&MyFunction);
function_closure->Run();

Closure* method_closure = NewCallback(me, &MyClass::MyMethod);
method_closure->Run();

Closure* curried_closure = NewCallback(me, &MyClass::MyMethodWithArg, 1);
curried_closure->Run();

Callback1<int>* callback_expecting_parameter =
  NewCallback(me, &MyClass::MyMethodWithArg);
callback_expecting_parameter->Run(1);

ResultCallback1<string, int>* curried_string =
   NewCallback(me, &MyClass::MyOtherMethod, "hello");
string x = curried_string->Run(1);

ResultCallback2<string, const string&, int>* other_closure =
   NewCallback(me, &MyClass::MyOtherMethod);
string y = other_closure->Run("hello", 1);

scoped_ptr<Closure> permanent(NewPermanentCallback(&MyFunction));
permanent->Run();
permanent->Run();
permanent->Run();

Executors

An Executor is an abstract class providing an interface that can process one or more Closures. Concrete executors manage a queue and processing resources to run the closures they are given.

Type Description
Inline Executor Executes closures immediately in the same thread making the request on the executor.
#include "googleapis/base/callback.h"
#include "googleapis/thread/executor.h"

class MyExecutor : public googleapis::thread::Executor {
  public:
    virtual void Add(Closure* closure);
    ...
};

googleapis::thread::Executor* executor = new MyExecutor;

// I'm keeping ownrship so must guarantee the executor instance stays valid.
googleapis::thread::Executor::SetDefaultExecutor(executor);