comparison doc/manual.tex @ 1329:9be9da2df74b

Clarifying some C FFI details in manual
author Adam Chlipala <adam@chlipala.net>
date Sat, 11 Dec 2010 11:00:05 -0500
parents c5799b1e4c58
children a6427d1eda6f
comparison
equal deleted inserted replaced
1328:c5799b1e4c58 1329:9be9da2df74b
2122 \item \begin{verbatim} 2122 \item \begin{verbatim}
2123 void uw_error(uw_context, failure_kind, const char *fmt, ...); 2123 void uw_error(uw_context, failure_kind, const char *fmt, ...);
2124 \end{verbatim} 2124 \end{verbatim}
2125 Abort the current request processing, giving a \texttt{printf}-style format string and arguments for generating an error message. The \texttt{failure\_kind} argument can be \texttt{FATAL}, to abort the whole execution; \texttt{BOUNDED\_RETRY}, to try processing the request again from the beginning, but failing if this happens too many times; or \texttt{UNLIMITED\_RETRY}, to repeat processing, with no cap on how many times this can recur. 2125 Abort the current request processing, giving a \texttt{printf}-style format string and arguments for generating an error message. The \texttt{failure\_kind} argument can be \texttt{FATAL}, to abort the whole execution; \texttt{BOUNDED\_RETRY}, to try processing the request again from the beginning, but failing if this happens too many times; or \texttt{UNLIMITED\_RETRY}, to repeat processing, with no cap on how many times this can recur.
2126 2126
2127 All pointers to the context-local heap (see description below of \texttt{uw\_malloc()}) become invalid at the start and end of any execution of a main entry point function of an application. For example, if the request handler is restarted because of a \texttt{uw\_error()} call with \texttt{BOUNDED\_RETRY} or for any other reason, it is unsafe to access any local heap pointers that may have been stashed somewhere beforehand.
2128
2127 \item \begin{verbatim} 2129 \item \begin{verbatim}
2128 void uw_push_cleanup(uw_context, void (*func)(void *), void *arg); 2130 void uw_push_cleanup(uw_context, void (*func)(void *), void *arg);
2129 void uw_pop_cleanup(uw_context); 2131 void uw_pop_cleanup(uw_context);
2130 \end{verbatim} 2132 \end{verbatim}
2131 Manipulate a stack of actions that should be taken if any kind of error condition arises. Calling the ``pop'' function both removes an action from the stack and executes it. 2133 Manipulate a stack of actions that should be taken if any kind of error condition arises. Calling the ``pop'' function both removes an action from the stack and executes it. It is a bug to let a page request handler finish successfully with unpopped cleanup actions.
2134
2135 Pending cleanup actions aren't intended to have any complex relationship amongst themselves, so, upon request handler abort, pending actions are executed in first-in-first-out order.
2132 2136
2133 \item \begin{verbatim} 2137 \item \begin{verbatim}
2134 void *uw_malloc(uw_context, size_t); 2138 void *uw_malloc(uw_context, size_t);
2135 \end{verbatim} 2139 \end{verbatim}
2136 A version of \texttt{malloc()} that allocates memory inside a context's heap, which is managed with region allocation. Thus, there is no \texttt{uw\_free()}, but you need to be careful not to keep ad-hoc C pointers to this area of memory. 2140 A version of \texttt{malloc()} that allocates memory inside a context's heap, which is managed with region allocation. Thus, there is no \texttt{uw\_free()}, but you need to be careful not to keep ad-hoc C pointers to this area of memory. In general, \texttt{uw\_malloc()}ed memory should only be used in ways compatible with the computation model of pure Ur. This means it is fine to allocate and return a value that could just as well have been built with core Ur code. In contrast, it is almost never safe to store \texttt{uw\_malloc()}ed pointers in global variables, including when the storage happens implicitly by registering a callback that would take the pointer as an argument.
2137 2141
2138 For performance and correctness reasons, it is usually preferable to use \texttt{uw\_malloc()} instead of \texttt{malloc()}. The former manipulates a local heap that can be kept allocated across page requests, while the latter uses global data structures that may face contention during concurrent execution. 2142 For performance and correctness reasons, it is usually preferable to use \texttt{uw\_malloc()} instead of \texttt{malloc()}. The former manipulates a local heap that can be kept allocated across page requests, while the latter uses global data structures that may face contention during concurrent execution. However, we emphasize again that \texttt{uw\_malloc()} should never be used to implement some logic that couldn't be implemented trivially by a constant-valued expression in Ur.
2139 2143
2140 \item \begin{verbatim} 2144 \item \begin{verbatim}
2141 typedef void (*uw_callback)(void *); 2145 typedef void (*uw_callback)(void *);
2142 typedef void (*uw_callback_with_retry)(void *, int will_retry); 2146 typedef void (*uw_callback_with_retry)(void *, int will_retry);
2143 void uw_register_transactional(uw_context, void *data, uw_callback commit, 2147 void uw_register_transactional(uw_context, void *data, uw_callback commit,
2145 \end{verbatim} 2149 \end{verbatim}
2146 All side effects in Ur/Web programs need to be compatible with transactions, such that any set of actions can be undone at any time. Thus, you should not perform actions with non-local side effects directly; instead, register handlers to be called when the current transaction is committed or rolled back. The arguments here give an arbitary piece of data to be passed to callbacks, a function to call on commit, a function to call on rollback, and a function to call afterward in either case to clean up any allocated resources. A rollback handler may be called after the associated commit handler has already been called, if some later part of the commit process fails. A free handler is told whether the runtime system expects to retry the current page request after rollback finishes. 2150 All side effects in Ur/Web programs need to be compatible with transactions, such that any set of actions can be undone at any time. Thus, you should not perform actions with non-local side effects directly; instead, register handlers to be called when the current transaction is committed or rolled back. The arguments here give an arbitary piece of data to be passed to callbacks, a function to call on commit, a function to call on rollback, and a function to call afterward in either case to clean up any allocated resources. A rollback handler may be called after the associated commit handler has already been called, if some later part of the commit process fails. A free handler is told whether the runtime system expects to retry the current page request after rollback finishes.
2147 2151
2148 Any of the callbacks may be \texttt{NULL}. To accommodate some stubbornly non-transactional real-world actions like sending an e-mail message, Ur/Web treats \texttt{NULL} \texttt{rollback} callbacks specially. When a transaction commits, all \texttt{commit} actions that have non-\texttt{NULL} rollback actions are tried before any \texttt{commit} actions that have \texttt{NULL} rollback actions. Thus, if a single execution uses only one non-transactional action, and if that action never fails partway through its execution while still causing an observable side effect, then Ur/Web can maintain the transactional abstraction. 2152 Any of the callbacks may be \texttt{NULL}. To accommodate some stubbornly non-transactional real-world actions like sending an e-mail message, Ur/Web treats \texttt{NULL} \texttt{rollback} callbacks specially. When a transaction commits, all \texttt{commit} actions that have non-\texttt{NULL} rollback actions are tried before any \texttt{commit} actions that have \texttt{NULL} rollback actions. Thus, if a single execution uses only one non-transactional action, and if that action never fails partway through its execution while still causing an observable side effect, then Ur/Web can maintain the transactional abstraction.
2149 2153
2154 When a request handler ends with multiple pending transactional actions, their handlers are run in a first-in-last-out stack-like order, wherever the order would otherwise be ambiguous.
2155
2156 It is not safe for any of these handlers to access a context-local heap through a pointer returned previously by \texttt{uw\_malloc()}, nor should any new calls to that function be made. Think of the context-local heap as meant for use by the Ur/Web code itself, while transactional handlers execute after the Ur/Web code has finished.
2157
2150 \item \begin{verbatim} 2158 \item \begin{verbatim}
2151 void *uw_get_global(uw_context, char *name); 2159 void *uw_get_global(uw_context, char *name);
2152 void uw_set_global(uw_context, char *name, void *data, uw_callback free); 2160 void uw_set_global(uw_context, char *name, void *data, uw_callback free);
2153 \end{verbatim} 2161 \end{verbatim}
2154 Different FFI-based extensions may want to associate their own pieces of data with contexts. The global interface provides a way of doing that, where each extension must come up with its own unique key. The \texttt{free} argument to \texttt{uw\_set\_global()} explains how to deallocate the saved data. 2162 Different FFI-based extensions may want to associate their own pieces of data with contexts. The global interface provides a way of doing that, where each extension must come up with its own unique key. The \texttt{free} argument to \texttt{uw\_set\_global()} explains how to deallocate the saved data. It is never safe to store \texttt{uw\_malloc()}ed pointers in global variable slots.
2155 2163
2156 \end{itemize} 2164 \end{itemize}
2157 2165
2158 \subsection{Writing JavaScript FFI Code} 2166 \subsection{Writing JavaScript FFI Code}
2159 2167