Add some notes about coding conventions do the docs.
This deserves to be greatly expanded and improved, but it's a start. Discussion: 20150827145219.GI2435@awork2.anarazel.de
This commit is contained in:
parent
84ae1af8f4
commit
d9cb34abb4
@ -851,4 +851,109 @@ BETTER: unrecognized node type: 42
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="source-conventions">
|
||||
<title>Miscellaneous Coding Conventions</title>
|
||||
|
||||
<simplesect>
|
||||
<title>C Standard</title>
|
||||
<para>
|
||||
Code in <productname>PostgreSQL</> should only rely on language
|
||||
features available in the C89 standard. That means a conforming
|
||||
C89 compiler has to be able to compile postgres, at least aside
|
||||
from a few platform dependant pieces. Features from later
|
||||
revision of the C standard or compiler specific features can be
|
||||
used, if a fallback is provided.
|
||||
</para>
|
||||
<para>
|
||||
For example <literal>static inline</> and
|
||||
<literal>_StaticAssert()</literal> are currently used, even
|
||||
though they are from newer revisions of the C standard. If not
|
||||
available we respectively fall back to defining the functions
|
||||
without inline, and to using a C89 compatible replacement that
|
||||
performs the same checks, but emits rather cryptic messages.
|
||||
</para>
|
||||
</simplesect>
|
||||
|
||||
<simplesect>
|
||||
<title>Function-Like Macros and Inline Functions</title>
|
||||
<para>
|
||||
Both, macros with arguments and <literal>static inline</>
|
||||
functions, may be used. The latter are preferable if there are
|
||||
multiple-evaluation hazards when written as a macro, as e.g. the
|
||||
case with
|
||||
<programlisting>
|
||||
#define Max(x, y) ((x) > (y) ? (x) : (y))
|
||||
</programlisting>
|
||||
or when the macro would be very long. In other cases it's only
|
||||
possible to use macros, or at least easier. For example because
|
||||
expressions of various types need to be passed to the macro.
|
||||
</para>
|
||||
<para>
|
||||
When the definition an inline function references symbols
|
||||
(i.e. variables, functions) that are only available as part of the
|
||||
backend, the function may not be visible when included from frontend
|
||||
code.
|
||||
<programlisting>
|
||||
#ifndef FRONTEND
|
||||
static inline MemoryContext
|
||||
MemoryContextSwitchTo(MemoryContext context)
|
||||
{
|
||||
MemoryContext old = CurrentMemoryContext;
|
||||
|
||||
CurrentMemoryContext = context;
|
||||
return old;
|
||||
}
|
||||
#endif /* FRONTEND */
|
||||
</programlisting>
|
||||
In this example <literal>CurrentMemoryContext</>, which is only
|
||||
available in the backend, is referenced and the function thus
|
||||
hidden with a <literal>#ifndef FRONTEND</literal>. This rule
|
||||
exists because some compilers emit references to symbols
|
||||
contained in inline functions even if the function is not used.
|
||||
</para>
|
||||
</simplesect>
|
||||
|
||||
<simplesect>
|
||||
<title>Writing Signal Handlers</title>
|
||||
<para>
|
||||
To be suitable to run inside a signal handler code has to be
|
||||
written very carefully. The fundamental problem is that, unless
|
||||
blocked, a signal handler can interrupt code at any time. If code
|
||||
inside the signal handler uses the same state as code outside
|
||||
chaos may ensue. As an example consider what happens if a signal
|
||||
handler tries to acquire a lock that's already held in the
|
||||
interrupted code.
|
||||
</para>
|
||||
<para>
|
||||
Barring special arrangements code in signal handlers may only
|
||||
call async-signal safe functions (as defined in posix) and access
|
||||
variables of type <literal>volatile sig_atomic_t</literal>. A few
|
||||
functions in postgres are also deemed signal safe, importantly
|
||||
<literal>SetLatch()</literal>.
|
||||
</para>
|
||||
<para>
|
||||
In most cases signal handlers should do nothing more than note
|
||||
that a signal has arrived, and wake up code running outside of
|
||||
the handler using a latch. An example of such a handler is the
|
||||
following:
|
||||
<programlisting>
|
||||
static void
|
||||
handle_sighup(SIGNAL_ARGS)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
got_SIGHUP = true;
|
||||
SetLatch(MyLatch);
|
||||
|
||||
errno = save_errno;
|
||||
}
|
||||
</programlisting>
|
||||
<literal>errno</> is safed and restored because
|
||||
<literal>SetLatch()</> might change it. If that were not done
|
||||
interrupted code that's currently inspecting errno might see the wrong
|
||||
value.
|
||||
</para>
|
||||
</simplesect>
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
Loading…
x
Reference in New Issue
Block a user