.. 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

TSContCall
**********

Synopsis
========

.. code-block:: cpp

    #include <ts/ts.h>

.. function:: int TSContCall(TSCont contp, TSEvent event, void * edata)

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

Call the continuation :arg:`contp` as if from a hook with the event type :arg:`event` and data of
:arg:`edata`. Presuming :arg:`contp` was created in a manner like::

   TSContCreate(CallbackHandler, TSMutexCreate());

Therefore there is a function::

   int CallbackHandler(TSCont this, TSEvent id, void * data);

As a result :func:`TSContCall` will effectively do::

   return CallbackHandler(contp, event, edata);

If there is a mutex associated with :arg:`contp`, :func:`TSContCall` assumes that mutex is held already.
:func:`TSContCall` will directly call the handler associated with the continuation.  It will return the
value returned by the handler in :arg:`contp`.

If :arg:`contp` has a mutex, the plugin must acquire the lock on the mutex for :arg:`contp` before calling
:func:`TSContCall`. See :func:`TSContMutexGet` and :func:`TSMutexLockTry` for mechanisms for doing this.

The most common case is the code called by :func:`TSContCall` must complete before further code is executed
at the call site. An alternative approach to handling the locking directly would be to split the call site
into two continuations, one of which is signalled (possibly via :func:`TSContCall`) from the original
:func:`TSContCall` target.

Note mutexes returned by :func:`TSMutexCreate` are recursive mutexes, therefore if the lock is
already held on the thread of execution acquiring the lock again is very fast. Mutexes are also
shareable so that the same mutex can be used for multiple continuations.::

   TSMutex mutex = TSMutexCreate();
   TSCont cont1 = TSContCreate(Handler1, mutex);
   TSCont cont2 = TSContCreate(Handler2, mutex);

In this example case, :code:`cont1` can assume the lock for :code:`cont2` is held. This should be
considered carefully because for the same reason any thread protection between the continuations is
removed. This works well for tightly coupled continuations that always operate in a fixed sequence.
