TSCONTCALL(3ts)

πŸ“¦
version 9.2.5 Β· 4 versions
, in ubuntu noble, ubuntu questing

πŸ’– TSCONTCALL πŸ’–

okay bestie so this is TSContCall, an API function from the Apache Traffic Server manual (section 3ts, we're fancy like that). if you're writing plugins and you need to summon a continuation handler directly, this is the page for you. buckle up πŸŽ€


✨ NAME ✨

TSContCall β€” literally the TSContCall API function, that's the whole name, she's simple and she's iconic πŸ’…


πŸ¦‹ SYNOPSIS πŸ¦‹

#include <ts/ts.h>

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

yes ma'am, one include and one function. no cap. 🌸


πŸ‘‘ DESCRIPTION πŸ‘‘

So what does it do? It calls the continuation contp as if from a hook β€” with the event type event and data of edata. It's giving "pretend this hook fired, but make it DIY." ✨

Say you made your continuation like this:

TSContCreate(CallbackHandler, TSMutexCreate());

Then bestie, you've got yourself a function:

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

And as a result, TSContCall() will effectively do:

return CallbackHandler(contp, event, edata);

Periodt. That's the whole trick. πŸ’–


Now, the important part, and I mean the important part πŸ”₯ β€” if there is a mutex associated with contp, TSContCall() assumes that mutex is held already. It doesn't lock anything for you. She trusts you. She believes in you. Do not betray her. 😭

TSContCall() will directly call the handler associated with the continuation, and it will return the value returned by the handler in contp. No middleman, no queue, no scheduling, just straight up calling.

⚠️ If contp has a mutex, the plugin must acquire the lock on the mutex for contp before calling TSContCall(). That's on you, bestie, not on her. Go look at TSContMutexGet() and TSMutexLockTry() for mechanisms for doing this. 🫢

The most common case is that the code called by TSContCall() must complete before further code is executed at the call site. Like, it's synchronous, it blocks, it's right there. If you don't want to deal with handling the locking directly, an alternative approach would be to split the call site into two continuations, one of which is signalled (possibly via TSContCall()) from the original TSContCall() target. Different vibe, same goal. 🌈


Okay so here's a cute little fact that changes everything: mutexes returned by TSMutexCreate() are recursive mutexes. So if the lock is already held on the thread of execution, acquiring the lock again is very fast. Like, no drama, instant, slay. ⭐

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, cont1 can assume the lock for cont2 is held. 🧚

But β€” and this is the part where you gotta be careful, bestie β€” this should be considered carefully, because for the same reason, any thread protection between the continuations is removed. It's giving "we're sharing a locker but there's no lock on the locker." 😭 This works well for tightly coupled continuations that always operate in a fixed sequence. If that's your situation, go off queen. If it's not… maybe don't. πŸ’€


2026, dev@trafficserver.apache.org


and that's the tea πŸ“ this has been Apache Traffic Server manual, version 9.2, dated Feb 12, 2026 β€” stay locked, stay recursive, stay iconic. mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from