.. Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed
   with this work for additional information regarding copyright
   ownership.  The ASF licenses this file to you under the Apache
   License, Version 2.0 (the "License"); you may not use this file
   except in compliance with the License.  You may obtain a copy of
   the License at

   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied.  See the License for the specific language governing
   permissions and limitations under the License.

.. include:: ../../../common.defs

.. default-domain:: c

TSConfig Functions
******************

Synopsis
========

.. code-block:: cpp

    #include <ts/ts.h>

.. type:: void (*TSConfigDestroyFunc)(void*)
.. function:: unsigned int TSConfigSet(unsigned int id, void * data, TSConfigDestroyFunc funcp)
.. function:: TSConfig TSConfigGet(unsigned int id)
.. function:: void TSConfigRelease(unsigned int id, TSConfig configp)
.. function:: void* TSConfigDataGet(TSConfig configp)

Description
===========

These functions provide a mechanism to safely update configurations for a plugin.

If a plugin stores its configuration in a data structure, updating that structure due to changes in
the configuration file can be dangerous due to the asynchronous nature of plugin callbacks. To avoid
that problem these functions allow a plugin to register a configuration and then later replace it
with another instance without changing the instance in use by plugin callbacks. This works in the
same manner as `shared pointer <https://en.wikipedia.org/wiki/Smart_pointer>`__. When a plugin needs
to access the configuration data, it calls :func:`TSConfigGet` which returns a pointer that will
remain valid until the plugin calls :func:`TSConfigRelease`. The configuration instance is updated
with :func:`TSConfigSet` which will update an internal pointer but will not change any instance in
use via :func:`TSConfigGet`. When the last in use pointer is released, the old configuration is
destructed using the function passed to func:`TSConfigSet`. This handles the overlapping
configuration update case correctly.

Initialization is done with :func:`TSConfigSet`. The :arg:`id` should be zero on the first call.
This will allocate a slot for the configuration, which is returned. Subsequent calls must use this
value. If the :arg:`id` is not zero, that value is returned. In general, the code will look
something like ::

   class Config { ... }; // Configuration data.
   int Config_Id = 0;
   //...
   void ConfigUpdate() {
      Config* cfg = new Config;
      cfg.load(); // load config...
      Config_Id = TSConfigSet(Config_Id, cfg,
         [](void* cfg){delete static_cast<Config*>(config);});
   }
   //...
   PluginInit() {
      // ...
      ConfigUpdate();
      // ...
   }

:code:`Config_Id` is a global variable holding the configuration id, which is updated by the
return value of :func:`TSConfigSet`.

The configuration instance is retrieved with :func:`TSConfigGet`. This returns a wrapper class from
which the configuration can be extracted with :func:`TSConfigDataGet`. The wrapper is used to
release the configuration instance when it is no longer in use. The code in a callback tends to look
like ::

   int callback() {
      auto cfg_ref = TSConfigGet(Config_Id);
      Config* cfg = static_cast<Config*>(TSConfigDataGet(cfg_ref));
      // ... use cfg
      TSConfigRelease(Config_Id, cfg_ref);
   }
