<function>init_callback</function> callback function is sufficient to
avoid race conditions.
</para>
<para>
Finally, each backend using the <literal>tranche_id</literal> should
associate it with a <literal>tranche_name</literal> by calling:
<programlisting>
void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
</programlisting>
</para>
<para>
A complete usage example of <function>LWLockNewTrancheId</function>,
<function>LWLockInitialize</function>, and
<function>LWLockRegisterTranche</function> can be found in
<filename>contrib/pg_prewarm/autoprewarm.c</filename> in the
<productname>PostgreSQL</productname> source tree.
</para>
</sect3>
</sect2>
<sect2 id="xfunc-addin-wait-events">
<title>Custom Wait Events</title>
<para>
Add-ins can define custom wait events under the wait event type
<literal>Extension</literal> by calling:
<programlisting>
uint32 WaitEventExtensionNew(const char *wait_event_name)
</programlisting>
The wait event is associated to a user-facing custom string.
An example can be found in <filename>src/test/modules/worker_spi</filename>
in the PostgreSQL source tree.
</para>
<para>
Custom wait events can be viewed in
<link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>:
<screen>
=# SELECT wait_event_type, wait_event FROM pg_stat_activity
WHERE backend_type ~ 'worker_spi';
wait_event_type | wait_event
-----------------+---------------
Extension | WorkerSpiMain
(1 row)
</screen>
</para>
</sect2>
<sect2 id="xfunc-addin-injection-points">
<title>Injection Points</title>
<para>
An injection point with a given <literal>name</literal> is declared using
macro:
<programlisting>
INJECTION_POINT(name, arg);
</programlisting>
There are a few injection points already declared at strategic points
within the server code. After adding a new injection point the code needs
to be compiled in order for that injection point to be available in the
binary. Add-ins written in C-language can declare injection points in
their own code using the same macro. The injection point names should use
lower-case characters, with terms separated by
dashes. <literal>arg</literal> is an optional argument value given to the
callback at run-time.
</para>
<para>
Executing an injection point can require allocating a small amount of
memory, which can fail. If you need to have an injection point in a
critical section where dynamic allocations are not allowed, you can use
a two-step approach with the following macros:
<programlisting>
INJECTION_POINT_LOAD(name);
INJECTION_POINT_CACHED(name, arg);
</programlisting>
Before entering the critical section,
call <function>INJECTION_POINT_LOAD</function>. It checks the shared
memory state, and loads the callback into backend-private memory if it is
active. Inside the critical section, use
<function>INJECTION_POINT_CACHED</function> to execute the callback.
</para>
<para>
Add-ins can attach callbacks to an already-declared injection point by
calling:
<programlisting>
extern void InjectionPointAttach(const char *name,
const char *library,
const char *function,
const void *private_data,
int private_data_size);
</programlisting>
<literal>name</literal> is the name of the injection point, which when
reached during execution will execute the <literal>function</literal>
loaded from <literal>library</literal>. <literal>private_data</literal>
is a private area of data of size <literal>private_data_size</literal>
given as argument to the callback when executed.
</para>
<para>
Here is an example of callback