/**
 * @page cpp_client_tutorial Advanced C++ Client API
 * @brief Advanced C++ Client API Tutorial
 *
 * [TOC]
 *
 * @section cpp_client_Overview Overview
 * This page covers some of the more advanced aspects of the OLA C++ Client
 * API including using callbacks, handling a server-side shutdown and running
 * the client in a separate thread. For an introduction on using the OLA C++
 * Client see @ref dmx_cpp_client_tutorial.
 *
 * @section cpp_client_Fetch_Plugins Using Callbacks
 *
 * Almost all of the ola::client::OlaClient methods take a \ref callbacks
 * "Callback" object. Each callback is executed when the server responds with
 * the results of the method invocation.
 *
 * Lets look at the ola::client::OlaClient::FetchPluginList method. This method
 * is used to fetch a list of available plugins from the olad server. The
 * client may choose to present the list of plugins to the user so they know
 * what Devices / Protocols are supported.
 *
 * The code below calls FetchPluginList() and then waits for the results from
 * the olad server. When the list of plugins is received, the name of each
 * plugin is printed to stdout and the program exits.
 *
 * @snippet fetch_plugins.cpp Client Fetch Plugins
 *
 * @section cpp_client_Disconnects Handling Server Shutdown.
 *
 * To write a robust program, you'll need to handle the case of olad
 * shutting down. This can be done by setting a callback to be executed when the
 * connection to the olad server is closed.
 *
 * The following example builds on the @ref dmx_cpp_client_OLAClient_TX
 * "OlaClient TX" example. Instead of exiting after 100 DMX frames have been
 * sent, the program runs until the connection to olad is closed.
 *
 * @snippet client_disconnect.cpp Client Disconnect Example
 *
 * Instead of exiting, a better approach would be to try and reconnect to the
 * olad server. Clients that do this should use a ola::BackOffPolicy to avoid
 * spinning in a loop trying to reconnect.
 *
 * @section cpp_client_Thread Running the OlaClient within a thread.
 *
 * Sometimes it can be difficult to integrate OLA's @ref event_driven
 * "Event Driven" programming model with the main event loop of your program.
 * The  OlaClient is not thread safe, so a workaround is to run a separate
 * thread for the OlaClient.
 *
 * We can use ola::io::SelectServer::Execute to run a callback on a
 * SelectServer running in a different thread. This allows us to schedule the
 * calls to OlaClient on the thread where the SelectServer is running.
 *
 * @snippet client_thread.cpp Client Thread
 *
 * It's important to realize that the ShowPluginList function will be run from
 * the OLA thread. If this function uses any variables from the main program
 * (such as UI widgets), you must use locking, or some other thread
 * synchronization technique.
 */
