Next: , Previous: Life Cycle, Up: Specifics

3.4 Sinks

R has a sink mechanism to divert output and messages (messages, warnings, and errors) to connections. By default, output is diverted to the stdout connection and messages are diverted to the stderr connection. The R sink function is used to modify or add output sink connections, and to modify (but not add to) the message connection. Adding or changing sink connections only affect the output generated by the C functions do_writelines (src/main/connections.c), Rvprintf, and REvprintf (src/main/printutils.c).

Internally, sink connections are managed through a collection of static declared variables and functions defined in the file src/main/connections.c. Several statically allocated arrays are delared in order to manage the stack of output sink connections, including SinkCons, SinkConsClose, and R_SinkSplit, each of length NSINKS (a macro currently defined to 21). Two additional integer variables, R_SinkNumber and R_OutputCon store the number of sinks in the output stack, and the number of the output connection at the top of the stack, respectively. Initially, R_SinkNumber is set to zero and R_OutputCon is set to one. The SinkCons array holds the number (index in the Connections array) of each sink connection. The first index of the SinkCons array is reserved for the stdout connection, and this may not be modified. The SinkConsClose array holds an integer value for each sink connection, that determines the action performed when the connection is popped from the sink stack. If a value in SinkConsClose is one or two, the corresponding connection is closed or destroyed, respectively. If the value is zero, no action is performed. The R_SinkSplit array holds the value one for each sink connection where output should also be diverted to the next sink connection on the stack. In this manner, it is possible to divert output to many connections simultaneously.

When a connection is added to the sink stack via the sink function, in turn calling the C-level do_sink function, the associated connection number is assigned to R_OutputCon and appended to the SinkCons array, R_SinkNumber is incremented, and the corresponding members of the SinkConsClose and R_SinkSplit arrays are assigned according to the arguments of the sink function call.

While a connection is in the sink stack, its external pointer is preserved with R_PreserveObject, and released with R_ReleaseObject once the connection is popped from the sink stack. Hence, while a connection is part of the sink stack, it will not be destroyed, even if it becomes unreachable at the R level. In addition when a sink connection is removed from the stack, the action specified by the corresponding member of SinkConsClose is performed, R_SinkNumber is decremented, and R_OutputCon is reassigned to the next value in the SinkCons array.

The connection that recieves R messages is identified by the integer stored in the R_ErrorCon variable, initially set to two, the number of the stderr connection. This variable may be set and reset using the sink function, such that R messages are diverted to other connections. When messages are diverted to a connection, the connection external pointer is preserved using R_PreserveObject. Until recently, the external pointer for a message sink connections were never released. This was problem was fixed by BUG 14331 such that external pointers for message sink connections are released the message sink is reset.