# C++ Services {#cpp_service}

Robot Raconteur is an object-oriented client-service RPC framework. Services expose objects, which are made available to clients using "object references", sometimes referred to as "proxies". See \ref introduction for an overview of the Robot Raconteur framework.

The object types and their members are defined in "service definition" files. See \ref service_definition for more information on how service objects are defined. C++ uses `RobotRaconteurGen` to generate "thunk" source that implements the object and value types defined in service definitions. See \ref cpp_intro_cmake_thunk_source_gen, \ref robotraconteurgen, and \ref robotraconteur_generate_thunk for more information on thunk source and thunk source generation.

For C++, the thunk source generates an abstract class with pure virtual functions for accessing the members. Services implement these abstract interfaces by creating objects that implement the defined members. Robot Raconteur then creates object references and member proxies to allow clients to interact with the members from the remote node.

Developing C++ services is not a trivial task. Because of the design of C++, the creation of security flaws or other terminal bugs is difficult to avoid for novice programmers. The use of Python, C\#, or Java is recommended unless C++ is absolutely necessary.

## Registering Services

Services are registered with a node using RobotRaconteur::RobotRaconteurNode::RegisterService(). This function takes the name of the service, the name of the service definition of the root object, and the root object instance. The root object must implement an abstract interface generated from a service definition. See \ref cpp_service_implement_objects. Once registered, the root object will be available to services.

The node must be configured to accept incoming connections. See \ref cpp_node_setup.

The service may have security configured. See \ref cpp_service_security.

## Server Context {#cpp_service_server_context}

Each service is managed by an instance of RobotRaconteur::ServerContext. This object interacts with the node to receive and send messages. It manages the service objects and client connections. See RobotRaconteur::ServerContext for the public API. It can be accessed using the RobotRaconteur::RRServiceObject interface, the return from RobotRaconteur::RobotRaconteurNode::RegisterService(), or using the RobotRaconteur::ServerContext::GetCurrentServerContext() function.

## Server Endpoints {#cpp_service_server_endpoint}

Each client has a RobotRaconteur::ServerEndpoint associated with it. It can be accessed during member calls using RobotRaconteur::ServerEndpoint::GetCurrentEndpoint(). The server endpoint is used by members to identify a client. The function RobotRaconteur::ServerEndpoint::GetCurrentAuthenticatedUser() can be used to retrieve the authentication for the current server endpoint. To retrieve the `uint32_t` endpoint ID, use RobotRaconteur::ServerEndpoint::GetCurrentEndpoint()->GetLocalEndpoint().

## Service Paths {#cpp_service_service_path}

Each object in a service has a "service path" that uniquely identifies the object. See \ref service_paths for more information.

## Implementing Service Objects {#cpp_service_implement_objects}

Services expose implementations of object types for use by clients. These implementations contain the real functionality that the service provides. For instance, a robot driver service object would have members that command the robot. This command can be done through a proprietary API provided by the robot vendor, directly using hardware registers, or one of the other variety of ways that software can interact directly with hardware. The implementation may also be a software component such as a robot planner. The members are used to command the planner to generate robot plans based on parameters passed through the members. Robot Raconteur is not specific about what the implementation of each service object does, rather Robot Raconteur is designed to provide access to the object members from a remote node through a client connection. It is up to the developer of the service to decide what the implemented object actually does. It is also up to the service developer to decide what object, member, and value types need to be used to implement a service. The use of standardized or commonly used service definitions is recommended to increase compatibility between services. Custom service definitions can be created if necessary, but should be avoided if possible.

The thunk source generated by `RobotRaconteurGen` or the CMake macro contains an "abstract interface" and a "default implementation" for each object type defined in the service definition. The "abstract interface" is a C++ class with pure virtual functions for each member. On the client, these pure virtual functions are implemented to proxy the interactions to the service. On the service side, a class implementing these virtual functions is expected. The implementation of the interface should extend the interface. A "default implementation" is also generated by the thunk source alongside the abstract interface. This is a bare-bones implementation extending the abstract interface. The service developer can extend this "default implementation" instead of extending the abstract interface directly. The developer can use the behavior of the "default implementation", overriding member virtual functions when necessary to change the behavior of the object. The rest of this section assumes that the developer chooses to use the "default implementation".

**Note that virtual inheritance must always be used with Robot Raconteur service objects!**

Consider the following example service definition:

    service experimental.service_example1

    object MyObject
        property double my_property
        function void my_function()
    end

The generated C++ "abstract interface" thunk source results in the following:

    // In namespace experimental::service_example1
    // Modified for brevity
    class MyObject : public virtual RobotRaconteur::RRObject
    {
    public:
        virtual double get_my_property()=0;
        virtual void set_my_property(double value)=0;

        virtual void my_function()=0;
    };

    using MyObjectPtr = boost::shared_ptr<MyObject>;

The service developer is responsible for developing a subclass of `MyObject` that implements all of the pure virtual functions. The exact form of pure virtual function function for each member is discussed later in this section.

The "default implementation" for `MyObject` results in the following declaration:

    // In namespace experimental::service_example1
    // Modified for brevity
    class MyObject_default_impl : public virtual MyObject, public virtual RobotRaconteur::RRObject_default_impl
    {
    protected:
        double rrvar_my_property;

    public:
        MyObject_default_impl();
        virtual double get_my_property();
        virtual void set_my_property(double value);

        virtual void my_function();
    };

and implementation:

    // In namespace experimental::service_example1
    // Modified for brevity

    MyObject_default_impl::MyObject_default_impl()
    {
        rrvar_my_property=0.0;
    }

    double MyObject_default_impl::get_my_property()
    {
        boost::mutex::scoped_lock lock(this_lock);
        return rrvar_my_property;
    }
    void MyObject_default_impl::set_my_property(double value)
    {
        boost::mutex::scoped_lock lock(this_lock);
        rrvar_my_property = value;
    }
    void MyObject_default_impl::my_function()
    {
        throw RobotRaconteur::NotImplementedException("");
    }

The "default implementation" is a class named with the object name with `_default_impl` appended. In the above example, the property `my_property` and function `my_function` are implemented by the default implementation. The property implementation stores the value of the property in a class field named with the property named prefixed with `rrvar_`. The accessors use `this_lock` for thread locking. `this_lock` is defined in RobotRaconteur::RRObject_default_impl, which is a virtual base class of all default implementations. Thu function `my_function` will throw RobotRaconteur::NotImplementedException when invoked. The service developer must implement this virtual function in the subclass of the default implementation.

The following is an example implementation of `MyObject` that uses the default implementation:

    using namespace RobotRaconteur;
    using namespace experimental::service_example1

    class MyObjectImpl : public virtual MyObject_default_impl
    {
    public:
        virtual void set_my_property(double value)
        {
            if (value < 0.0)
            {
                throw RobotRaconteur::InvalidArgumentException("my_property must not be negative");
            }

            boost::mutex::scoped_lock lock(this_lock);
            rrvar_my_property = value;
        }

        virtual void my_function()
        {
            double p;
            {
                boost::mutex::scoped_lock lock(this_lock);
                p = rrvar_my_property;
            }
            std::cout << "my_property is currently: " << p << std::endl;
        }
    };

This implementation does a bounds check on `my_property`, and implements `my_function` to print the current value to the terminal on the service side. Note the use of `this_lock` to protect `rrvar_my_property`. This is necessary because member calls on service objects come from the thread pool. Multiple threads may call members concurrently, which can lead to data corruption. Use `this_lock` to protect data that can be corrupted by concurrent calls. See \ref cpp_threading_and_async for more information on the thread pool.

The generated thunk source also provides an "abstract default implementation". The "abstract default implementation" ends with `_abstract_default_impl` and is intended to be used if a class extends another `_default_impl` class.

### `IRRServiceObject` Interface {#cpp_service_irrserviceobject_interface}

Object members such as `pipe`, `wire`, and `callback` need to be initialized by the service before they can be used. Service objects may inherit RobotRaconteur::IRRServiceObjectIntereface to be notified when the object has been initialized. The function RobotRaconteur::IRRServiceObject::RRServiceObjectInit() is called when the initialization is complete.

An example that improves `MyObjectImpl` to implement `IRRServiceObject`:

    using namespace RobotRaconteur;
    using namespace experimental::service_example1

    class MyObjectImpl : public virtual MyObject_default_impl, public virtual IRRServiceObject
    {
    protected:
        boost::weak_ptr<ServerContext> ctx;
        std::string this_service_path;

    public:

        virtual void RRServiceObjectInit(boost::weak_ptr<ServerContext> ctx, const std::string& service_path)
        {
            // Save ctx and service_path for later use
            this->ctx = ctx;
            this_service_path = service_path;

            // Do other initialization tasks here
        }

        virtual void set_my_property(double value)
        {
            if (value < 0.0)
            {
                throw RobotRaconteur::InvalidArgumentException("my_property must not be negative");
            }

            boost::mutex::scoped_lock lock(this_lock);
            rrvar_my_property = value;
        }

        virtual void my_function()
        {
            double p;
            {
                boost::mutex::scoped_lock lock(this_lock);
                p = rrvar_my_property;
            }
            std::cout << "my_property is currently: " << p << std::endl;
        }
    };

### Property Members {#cpp_service_property}

Property members allow clients to "get" and "set" a property value on the service object. Properties may use any valid Robot Raconteur value type.

Property members are implemented as two access functions in the object, a "get" and "set" function. The "get" function is the name of member prepended with `get_`. It takes no arguments, and returns the current value. The "set" function is the name of the member prepended with `set_`. It takes the new property value, and returns void. Service objects must implement the accessor functions, or use the `_default_impl` defaul implementation of the property.

For example, the property definition:

    property double my_property

An example implementation of the property accessors:

    virtual double get_my_property()
    {
        boost::mutex::scoped_lock lock(this_lock);

        // Return the current property value here
    }
    virtual void set_my_property(double val)
    {
        boost::mutex::scoped_lock lock(this_lock);

        // Set the property value here
    }

Properties can be declared `readonly` or `writeonly` using member modifiers. If a property is `readonly`, the `set_` accessor function is not used. If a property is `writeonly`, the `get_` accessor function is not used.

Properties can be implemented as asynchronous functions instead of the synchronous accessors above. The thunk source generates an asynchronous version of the abstract interface class that has asynchronous versions of the property member accessors and function members. The asynchronous interface starts with `async_` followed by the object name. The asynchronous accessor functions start with `async_get_` and `async_set_`. If the service object extends the asynchronous interface, the property and function members will always call the asynchronous versions. The `async_set_` accessor will not be generated if the property is declared `readonly`. The `async_get_` accessor will not be generated if the property is declared `writeonly`.

### Function Members {#cpp_service_function}

Function members allow clients to invoke a function on the service object. Functions may have zero or more value type parameters, and return a value or be declared `void` for no return. Functions may be "normal", not using a generator, or be "generator functions" which return a generator.

#### Normal Functions {#cpp_service_normal_functions}

Normal functions accept zero or more value type parameters, invoke the remote function with these parameters, and return the result, or `void`. They are implemented in the abstract interface as a C++ function with the same name as the member.

For example, the function definition:

    function double addTwoNumbers(int32 a, double b)

An example implementation of the function:

    virtual double addTwoNumbers(int32_t a, double b)
    {
        return (double)a + b;
    }

An example function definition with no parameters and void return:

    function void do_something()

An example implementation of the function:

    virtual void do_something()
    {
        // Do the operation
    }

Functions can be implemented as asynchronous functions instead of synchronous functions. The thunk source generates an asynchronous version of the abstract interface class that has asynchronous versions of function members. The asynchronous interface starts with `async_` followed by the object name. The asynchronous function implementation start with `async_` followed by the member name. If the service object extends the asynchronous interface, the asynchronous versions of the functions will always be called.

#### Generator Functions {#cpp_service_generator_functions}

Generator functions are similar to normal functions, but instead of returning a value or void, they return a generator. A generator is similar to an iterator, or can implement a coroutine. See RobotRaconteur::Generator and \ref service_definition_function for more discussion on generators.

Generators may be Type 1, 2, or 3 depending on the argument and return value configuration for `Next()`. See \ref cpp_client_generator_functions for a discussion of these different generator types.

The service implementation of generator functions must return a generator object. This generator object must extend RobotRaconteur::Generator. The client will then be able to call the generator using the generator reference provided to the client. RobotRaconteur::Generator has pure virtual functions for `Next()`, `Abort()`, `Close()`, and the asynchronous versions `AsyncNext()`, `AsyncAbort()`, and `AsyncClose()`. By default, the service will always call the asynchronous versions of these functions. If the service prefers to use synchronous versions of these function, the generator implementation can extend RobotRaconteur::SyncGenerator.

An example service definition containing a generator function to count to 100 with a given start:

    service experimental.service_example2

    object MyObject
        function int32{generator} count_to_100(int32 start)
    end

An implementation of `MyObject` and the generator returned by `count_to_100()`:

    using namespace RobotRaconteur;
    using namespace experimental::service_example2;

    class CountTo100Generator : public virtual SyncGenerator<int32_t,void>
    {
    protected:
        int32_t count = 0;
        bool aborted = false;
        bool closed = false;
        boost::mutex this_lock;

    public:
        CountTo100Generator(int32_t start)
        {
            count = start;
        }

        virtual int32_t Next()
        {
            boost::mutex::scoped_lock lock(this_lock);

            if (aborted)
            {
                // Throw OperationAbortedException if the generator was aborted
                throw OperationAbortedException("");
            }

            if (closed || count > 100)
            {
                // Throw StopIterationException if generator is complete or closed
                closed = true;
                throw StopIterationException("");
            }

            return count++;
        }

        virtual void Close()
        {
            boost::mutex::scoped_lock lock(this_lock);
            // Close the generator
            closed = true;
        }

        virtual void Abort()
        {
            boost::mutex::scoped_lock lock(this_lock);
            // Abort the generator
            aborted = true;
        }
    };

    class MyObjectImpl : public virtual MyObject_default_impl
    {
    public:
        GeneratorPtr<int32_t,void> count_to_100(int32_t start)
        {
            boost::mutex::scoped_lock lock(this_lock);

            if (start < 1 || start > 100)
            {
                throw InvalidArgumentException("start must be between 1 and 100");
            }

            return boost::make_shared<CountTo100Generator>(start);
        }
    };

As shown in the above example, the generator should return values until complete. If the generator runs out of values or is closed, it should throw RobotRaconteur::StopIterationException. If the generator is aborted, it should throw RobotRaconteur::OperationAbortedException. Abort should be used in situations where any modifications the generator may have made should not be commited. It can also be used if the generator represents a physical motion, like executing a robot trajectory, that requires the motion to be rapidly aborted.

### Event Members {#cpp_service_event}

Events are used by the service to notify all connected clients an event has occurred. Events may have zero or more value type parameters. Events are sent to all connected clients. In C++, events are implemented using `boost::signals2::signal`. See the documentation for `boost::signals2::signal` for more information on using Boost.Signals2. An example event definition:

    event somethingHappened(string what, double when)

The abstract interface generates an accessor for a `boost::signals2::signal` reference to be returned by the service. The service needs to create an instance of the signal as a field in the class, and return a reference to that instance in the accessor function. The `_default_impl` class does this automatically, creating a field `rrvar_` followed by the event member name.

The following example shows the event being fired from a class extending `_default_impl`.

    // In the same C++ class as the event, extending from the "_default_impl" class

    void fire_event(const std::string& what, double when)
    {
        boost::mutex::scoped_lock lock(this_lock);
        rrvar_somethingHappened(what, when);
    }

The `fire_event()` function will trigger the signal. The service listens to this signal, and will forward the event to all connected clients.

### ObjRef Members {#cpp_service_objref}

ObjRef members are used to access other objects within a service.  See \ref service_paths for more information on objrefs and service paths. An example objref definition:

   objref MyOtherObject other_object

This objref definition results in an accessor function in the abstract interface that needs to be implemented:

    class MyOtherObjectImpl : public virtual MyOtherObject
    {
        // TODO: Implement the other object
    };

    // In the object owning the other_object member:

    virtual MyOtherObjectPtr get_other_object()
    {
        // Return a new object, or a pointer to an existing object
        return boost::make_shared<MyOtherObject>();
    };

ObjRefs may also be indexed with an `int32_t` or `string`. See \ref cpp_client_objref for a discussion of the different forms of the accessor function. The index is passed to the service as a parameter to the accessor function. It is up to the service to decide what object to return based on the index. If the index is invalid, RobotRaconteur::InvalidArgumentException should be thrown.

ObjRefs also use the `async_` asynchronous abstract interface if the service object extends it. The asynchronous accessor function is prefixed with `async_get_`.

### Pipe Members {#cpp_service_pipe}

Pipe members provide reliable (or optionally unreliable) data streams between clients and service, in either direction. See \ref RobotRaconteur::Pipe for a discussion of pipes.

An example pipe definition:

    pipe double[] sensordata

Results in the following pure virtual functions being generated in the abstract interface that need to be implemented by the service object:

    virtual PipePtr<RRArrayPtr<double>> get_sensordata();
    virtual void set_sensordata(PipePtr<RRArrayPtr<double>> pipe);

Pipes are initialized by the service when the root service object is registered, or after service objects are returned from objref members. The service will call the `set_` accessor function with a pipe server for use by the service. The service object is expected to store a reference to this pipe server, and accept incoming connection requests from clients. The service uses RobotRaconteur::Pipe::SetConnectCallback() to specify a callback function to invoke when clients request pipe connections. Each time a client connects a pipe, the callback is invoked with a RobotRaconteur::PipeEndpointPtr that the service can use to send and/or receive packets with the client. If the service needs to reject the incoming pipe connection, the callback can throw an exception. This exception will abort the connection, and pass the exception back to the client. The service is responsible for maintaining a reference to the RobotRaconteur::PipeEndpointPtr, but the reference is still owned by the pipe. It is recommended that `boost::weak_ptr<RobotRaconteur::PipeEndpoint<T>>` be used to store the endpoint pointer to avoid memory leaks.

Pipes declared `readonly` may only send packets on the service side. Pipes declared `writeonly` may only receive packets on the service side.

There is a helper class RobotRaconteur::PipeBroadcaster that can be used when the service needs to send the same packets to every connected client. It should only be used with pipes declared `readonly`. The pipe broadcaster has optional flow control, that tracks how many packets are "in flight", and compares it to the "maximum backlog". If the number of packets in flight exceeds the maximum backlog, sending packets is paused. (This flow control method only works with reliable pipes.)

The `_default_impl` will automatically create a RobotRaconteur::PipeBroadcaster for `readonly` pipes. The pipe broadcaster is stored in a field `rrvar_` followed by the name of the pipe member.

An example, assuming that the `sensordata` pipe is in `MyObject`, and using `IRRServiceObject` to set the maximum backlog:

    class MyObjectImpl : public virtual MyObject_default_impl, public virtual IRRServiceObject
    {
    public:

        virtual void RRServiceObjectInit(boost::weak_ptr<ServerContext> ctx, const std::string& service_path)
        {
            // Set the maximum backlog to prevent overloading the transport
            rrvar_sensordata->SetMaxBacklog(3);
        }

    protected:

        void SendData(RRArrayPtr<double> data)
        {
            boost::mutex::scoped_lock lock(this_lock);

            // Test to make sure that rrvar_sensordata has been initialized
            if (rrvar_sensordata)
            {
                // Send the packet, don't wait for send completion
                rrvar_sensordata->AsyncSendPacket(data,[]());
            }
        }
    };

`AsyncSendPacket()` is used to prevent the `SendData()` function from blocking the thread.

If the pipe member is not marked `readonly`, the `_default_impl` will store RobotRaconteur::PipePtr in `rrvar_`. Use RobotRaconteur::Pipe::SetConnectCallback() in `RRServiceObjectInit` to set the connect callback function.

### Callback Members {#cpp_service_callback}

Callbacks allow the service to invoke a function on a specific client. The definition is nearly identical to a `function` member, except the keyword is `callback` and generators are not supported. An example callback definition:

    callback double addTwoNumbersOnClient(int32 a, double b)

The callback is managed by an instance of RobotRaconteur::Callback. The example results pure virtual functions being generated in the abstract interface that need to be implemented by the service object:

    virtual CallbackPtr<boost::function<double (int32_t, double)> > get_addTwoNumbersOnClient();
    virtual void set_addTwoNumbersOnClient(CallbackPtr<boost::function<double (int32_t, double)> > callback);

The service object needs to store the RobotRaconteur::CallbackPtr in a field so it can retrieve proxies to client callbacks. The `_default_impl` automatically handles this, and stores the RobotRaconteur::CallbackPtr in a field `rrvar_` followed by the member name.

Service objects retrieve proxies to the client callbacks using RobotRaconteur::Callback::GetClientFunction(). This function takes a `uint32_t` client endpoint ID to select which client to call. This client endpoint ID can be determined using RobotRaconteur::ServerEndpoint::GetCurrentEndpoint()->GetLocalEndpoint() called during a function member or property member request.

An example service definition demonstrating using a callback:

    service experimental.service_example3

    object MyObject
        function void other_function()
        callback double addTwoNumbersOnClient(int32 a, double b)
    end

An implementation of `addTwoNumbersOnClient()` that will call the last client to invoke `other_function()`:

    using namespace ::experimental::service_example3;

    class MyObjectImpl : public virtual MyObject_default_impl
    {
        uint32_t client_id = 0;

    public:
        virtual void other_function()
        {
            // Store the endpoint ID
            boost::mutex::scoped_lock lock(this_lock);
            client_id = ServerEndpoint::GetCurrentEndpoint()->GetLocalEndpoint();
        }

    protected:
        double invoke_add(int32_t a, double b)
        {
            boost::function<double(int32_t,double)> cb;
            {
                boost::mutex::scoped_lock lock(this_lock);
                try
                {
                    // Get a proxy to the client callback
                    cb = rrvar_addTwoNumbersOnClient->GetClientFunction(client_id);
                }
                catch (std::exception&)
                {
                    // If getting the callback failed, set client_id to zero, or invalid
                    client_id = 0;
                    throw InvalidOperationException("Client ID is not valid");
                }
            }
            return cb(a,b);
        }
    };

The above example will invoke the callback on the last function to call `other_function()`. The choice of client which client to use depends completely on the purpose of the callback. The callback can be invoked on any connected client. If the client has not specified a callback for use, a RobotRaconteur::InvalidOperationException is thrown.

### Wire Members {#cpp_service_wire}

Wire members provide a "most recent" values. They are typically used to communicate a real-time signal, such as a robot joint angle. See RobotRaconteur::Wire for a discussion of wires.

An example wire definition:

    wire double[2] currentposition

Results in the following functions pure virtual being generated in the abstract interface:

    virtual WirePtr<RRArrayPtr<double>> get_currentposition();
    virtual void set_currentposition(WirePtr<RRArrayPtr<double>> wire);

These functions must be implemented by the service object.

Implementing wires can be somewhat complicated. The use of the helper classes RobotRaconteur::WireBroadcaster and RobotRaconteur::WireUnicastReceiver are recommended. Using these two helper classes will be discussed first, followed by a discussion of using the wire without helper classes.

Wires can be marked as `readonly` or `writeonly`. If neither is specified, the wire can send values in both directions. Wire memers are usually set to `readonly` or `writeonly` for most service designs. While using a full-duplex wire is possible, the need for full-duplex wires is not typical.  `readonly` wires can only send values from service to client. `writeonly` wires can only send values from client to service.

For `readonly` wires, the service can use the RobotRaconteur::WireBroadcaster to send the same values to all connected wires. The `OutValue` is set on the wire broadcaster, and this value is sent to all connected wires. For `writeonly` wires, the service can use the RobotRaconteur::WireUnicastReceiver. The unicast receiver is designed to provide the `InValue` of the most recent wire connection to connect. This `InValue` is set by the client, providing values from the client to the service. If a client wire connection is already established, it is closed in favor of the more recent connection. Clients locking should be used to prevent other clients from connecting. See \ref cpp_client_object_locking. The RobotRaconteur::WireBroadcaster and RobotRaconteur::WireUnicastReceiver automate most of the functionality of the wire. In most cases the user simply needs to set the `OutValue` of the broadcaster and query the `InValue` of the receiver.

The generated `_default_impl` class implements the accessor functions for the wires, and stores the wire in class fields named `rrvar_` appended with the name of the member. The `_default_impl` has special behavior for `readonly` and `writeonly` members. For `readonly` wire members, the `rrvar_` field will automatically be initialized with a RobotRaconteur::WireBroadcaster. For `writeonly` wire members, the `rrvar_` field will automatically be initialized with a RobotRaconteur::WireUnicastReceiver. (The service can override the `get_` and `set_` accessor functions to override this behavior.)

Wires are typically used with a (soft) real-time control loop, such as a robot feedback loop. The following is a simple example of a first-order discrete-time system y\[n\] = -a\*y\[n-1\] + b\*u\[n\] loop implemented using wires for input and output.

Discrete time loop service definition:

    service experimental.service_example4

    object MyObject
        wire double y [readonly]
        wire double u [writeonly]
    end

The service object implementation of the discrete time system:

    class MyObjectImpl : public virtual MyObject_default_impl, public virtual IRRServiceObject
    {
        double y_n1 = 0;
        double a = 0.1;
        double b = 0.1;
    public:

        virtual void RRServiceObjectInit(boost::weak_ptr<ServerContext> ctx, const std::string& service_path)
        {
            rrvar_u->SetInValueLifespan(250);
        }

        // Run one step of the discrete time system
        void Step()
        {
            boost::mutex::scoped_lock lock(this_lock);

            // If either wire has not been initialized, return
            if (!rrvar_y || !rrvar_u)
            {
                return;
            }

            // Get "u", if not available, use zero
            double u = 0;
            TimeSpec ts;
            uint32_t ep;

            // rrvar_u is initialized to WireUnicastReceiver<double> by MyObject_default_impl
            if (!rrvar_u->TryGetInValue(u,ts,ep))
            {
                // Set u to zero if no input available
                u = 0;
            }

            double y = - a * y_n1 + b * u;

            // rrvar_y is initialized to WireBroadcaster<double> by MyObject_default_impl

            // Set the out value wire
            rrvar_y->SetOutValue(y);

            // Save y for next iteration
            y_n1 = y;
        }
    };


The RobotRaconteur::WireUnicastReceiver::SetInValueLifespan() is used to give the received input value a finite lifespan. If the client disconnects or stops sending data, the in value will expire, preventing stale data from being received. The `Step()` function must be called periodically by the program. This is typically done in a loop in `main()` or from a thread.

For a device like a robot or a senser, the wires would be used to send feedback and receive commands instead of being used with a software discrete time system.

The discussion and examples so far have used the helper classes `WireBroadcaster` and `WireUnicastReceiver`. These classes automatically manage the incoming wire connections, peek requests, and poke requests. If the service does not want to use a helper class, it must implement the `get_` and `set_` accessors in the object, and it must set callbacks for incoming wire connections, peek in value requests, peek out value requests, and poke out value requests. The relevant functions to set the callbacks are RobotRaconteur::Wire::SetWireConnectCallback(), RobotRaconteur::Wire::SetPeekInValueCallback(), RobotRaconteur::Wire::SetPeekOutValueCallback(), and RobotRaconteur::Wire::SetPokeOutValueCallback(). These callbacks are usually configured in the `set_` accessor. The `set_` accessor will only be called once by the service. Manually managing wire connections and peek/poke callbacks is not normally necessary, since the helper classes can be used directly or subclassed to implement wire functionality.

### Memory Members {#cpp_service_memory}

Memories are used to read and write a memory segment on the service. Memories may be numeric arrays, numeric multidimarrays, pod arrays, pod multidimarrays, namedarray arrays, or namedarray multidimarrays. The different types of memories and their corresponding C++ classes are discussed here: \ref cpp_client_memory.

A numeric array memory client and a numeric multidimarray memory client will be used as examples. Pod and namedarray memories are identical, except for the memory class and the value types being utilized.

Example array memory definition:

    memory double[] datahistory

Results in a single pure virtual accessor function being generated in the abstract interface that must be implemented:

    virtual ArrayMemoryPtr<double> get_datahistory()
    {
        // Assume that there is a field storing the data
        RRArrayPtr<double> my_data = self->my_data_;

        // Return an array memory
        return boost::make_shared<ArrayMemory>(my_data);
    }

The service will proxy the read and write requests to the returned memory. The service can return the existing memory C++ classes, however these do not provide any locking or data protection. Is is recommended that the provided C++ classes be extended for the specific needs of the application.

Memory members are a seldomly used feature. They should only be used when a device provides a true shared memory region, such as a ring buffer or a set of registers that must be exposed, or when there is a very large data set that is randomly accessed by clients.

## Service Security {#cpp_service_security}

Services can be secured using a RobotRaconteur::ServiceSecurityPolicy instance. The security policy is passed to RobotRaconteur::RobotRaconteurNode::RegisterService() function when the service is registered. The constructor takes a map of policies, and a pointer to a user authenticator. Currently, the only authenticator available is RobotRaconteur::PasswordFileUserAuthenticator. This authenticator takes a file or string of usernames, passwords, and privileges to authenticate against. See RobotRaconteur::PaswordFileUserAuthenticator for information on the file format. See \ref security for a discussion of Robot Raconteur security.

The following is a typical example of a secured service being initialized:

    // Username, password, and privileges data, one user per line. Passwords md5 hashed
    std::string password_auth_data =
        "user1 79e262a81dd19d40ae008f74eb59edce objectlock" "\n"
        "user2 309825a0951b3cf1f25e27b61cee8243 objectlock" "\n"
        "superuser1 11e5dfc68422e697563a4253ba360615 objectlock,objectlockoverride" "\n";

    // Create the service object
    MyObjectPtr obj = boost::make_shared<MyObjectImpl>();

    std::map<std::string,std::string> policies = {
        {"requirevaliduser", "true"},
        {"allowobjectlock", "true"}
    };

    // Create the password authenticator
    PasswordFileUserAuthenticatorPtr auth = boost::make_shared<PasswordFileUserAuthenticator>(password_auth_data);

    // Create the security policy
    ServiceSecurityPolicyPtr s = boost::make_shared<ServiceSecurityPolicy>(auth,policies);

    // Register the service
    RobotRaconteurNode::s()->RegisterService("my_service", "experimental.service_example5", obj);


The above example has two normal users, "user1" and "user2", and one superuser, "superuser1". The superuser has the "objectlockoverride" privilege, allowing the superuser to unlock any object regardless of which user created the lock. The passwords are stored as md5 hashes. These md5 hashes can be generated using `RobotRaconteurGen`. See \ref robotraconteurgen. The password data should be stored in a file so it can be modified as users are added and removed.

## Object Locking {#cpp_service_locking}

Clients can request object locks to gain exclusive access. There are three types of object locking: user locks, client locks, and monitor locks. See \ref object_locking and \ref cpp_client_object_locking for more information on object lock types.

### User Locks and Client Locks {#cpp_service_locking_user_client}

User locks and client locks only require that the "allowobjectlock" policy is set, that the current client is authenticated, and the authenticated client has the "objectlocking" privilege. Object locking at this point is handled automatically by the service. The service can create and release locks on behalf of clients using RobotRaconteur::ServerContext::RequestObjectLock(), RobotRaconteur::ServerContext::RequestClientObjectLock(), and RobotRaconteur::ServerContext::ReleaseObjectLock(). See each function for more information.

### Monitor Locks {#cpp_service_locking_monitor}

Monitor locks are used to request a thread-exclusive lock. Service objects that wish to be monitor-lockable must extend and implement RobotRaconteur::IRobotRaconteurMonitorObject. This interface contains function to enter the lock, and exit the lock. The simplest implementation will use a `boost::mutex` to implement the lock. The following example uses this method:

    using namespace RobotRaconteur;

    class MyObjectImpl : public virtual MyObjectDefaultImpl,
        public virtual IRobotRaconteurMonitorObject
    {
    public:
        virtual void RobotRaconteurMonitorEnter()
        {
            monitor_lock.lock();
        }

        virtual void RobotRaconteurMonitorEnter(int32_t timeout)
        {
            if (timeout==-1)
            {
                RobotRaconteurMonitorEnter();
            }
            else
            {
                monitor_lock.timed_lock(boost::posix_time::milliseconds(timeout));
            }
        }

        virtual void RobotRaconteurMonitorExit()
        {
            monitor_lock.unlock();
        }

    protected:
        boost::mutex monitor_lock;
    };

The service can also use `monitor_lock` directly, when it needs to prevent clients from accessing a memory region.

**Not that unlike client and user locks, monitor locks are not enforced. The client must voluntarily request monitor locks.**

## Service Attributes {#cpp_service_attributes}

Service attributes are provided by services to help with discovery. The attributes are made available to clients during the discovery process. In C++, the attributes have the type `std::map<std::string,RRValuePtr>`. The attributes follow the same type rules as `varvalue{string}`. The attributes map must not contain any types defined in service definitions, since the client won't be able to unpack these types.

An example of using attributes for a service with root object type `MyRobot`:

    MyRobotPtr robot = boost::make_shared<MyRobot>();
    std::map<std::string,RRValuePtr> attributes =
    {
        { "description", stringToRRArray("My awesome robot!") },
        { "location", stringToRRArray("Robotics lab") }
    };

    ServerContextPtr ctx = RobotRaconteurNode::s()->RegisterService("my_robot", "experimental.my_robot", robot);
    ctx->SetAttributes(attributes);

## Releasing Objects {#cpp_service_release_path}

When service objects are returned from objref members, the service takes ownership of the object. If the service needs to release the object, it must be done explicitly using the RobotRaconteur::RobotRaconteurNode::ReleaseServicePath() function. This function takes the "service path" of the object to be released. See \ref service_paths for more information on service paths. The service path of an object can be determined using RobotRaconteur::IRRServiceObject, or using the function RobotRaconteur::ServerContext::GetCurrentServicePath(). When the service path is released, all connected clients are notified using an event. If the service path contains sensitive data such as a session token, the RobotRaconteur::ServerContext::ReleaseServicePath(boost::string_ref path, const std::vector<uint32_t>& endpoints) overload should be used. This version will only notify the clients specified in the `endpoints` parameter.
