# Function Template `close`

Description
When is `close` invoked?
Headers
Reference

## Description

The two overloads of the function template `close` are invoked automatically by the Iostreams library to indicate to Filters and Devices that a sequence of data is about to end. This gives Filters and Devices an opportunity to free resources or to reset their states in preparation for a new character sequence. Filters and Devices which perform output can use the opportunity to write additional data to the end of a stream.

The details regarding when and how `close` is invoked are a bit messy:

## When is `close` invoked?

#### `stream_buffer` and `stream`

When an instance of `stream_buffer` or `stream` based on a Device `d` is closed using member function `close`, the following sequence of functions calls is made:

        boost::iostreams::close(d, std::ios_base::in);
        boost::iostreams::close(d, std::ios_base::out);

The effect, if `D` is Closable and controls a single sequence, is as follows:

        d.close();

If `D` is Closable and controls separate input and output sequences, the effect is as follows:

        d.close(std::ios_base::in);
        d.close(std::ios_base::out);

(See the semantics of `close` for Device types, below.)

#### `filtering_streambuf` and `filtering_stream`

A `filtering_streambuf` or `filtering_stream` is considered to be closed if its lifetime ends while its chain is complete or if its terminal Device is removed using `pop` or `reset`. When this occurs, the following sequence of calls is made, assuming that the underlying sequence of Filters and Devices is `f1`, `f1`, ..., `fn-1`, `d` and the corresponding sequence of stream buffers is `buf1`, `buf2`, ..., `bufn-1`, `bufn`:[1]

        using namespace std;

        // Close each input sequence, in reverse order:
        boost::iostreams::close(d,n-1, bufn-1 ios_base::in);
        boost::iostreams::close(fn-1, bufn,-1 ios_base::in);
        boost::iostreams::close(fn-2, bufn-1, ios_base::in);
        ...
        boost::iostreams::close(f1,n- buf2,n- ios_base::in);

        // Close each output sequence, in order:
        boost::iostreams::close(f1,n- buf2,n- ios_base::out);
        boost::iostreams::close(f2,n- buf3,n- ios_base::out);
        ...
        boost::iostreams::close(fn-1, bufn,n- ios_base::out);
        boost::iostreams::close(d,n-1, bufn-1 ios_base::out);

The effect is that with input streams, the elements of a chain are closed in reverse order; with output streams, they are closed in forward order; and with streams controlling separate input and output sequences, each element receives two closure notifications, the first with argument `ios_base::in` and the second with argument `ios_base::out`. (See the semantics of `close` for Filter and Device types, below.)

## Headers

`<boost/iostreams/close.hpp>`
`<boost/iostreams/operations.hpp>`

## Reference

### Synopsis

    namespace boost { namespace iostreams {

    template<typename T>
    void close(T& t, std::ios_base::openmode which);

    template<typename T, typename Device>
    void close(T& t, Device& next, std::ios_base::openmode which);

    } } // End namespace boost::io

### Function Template `close` — Device Types

#### Template Parameters

T | - | A model of one of the Device concepts.

#### Semantics

    template<typename T>
    void close(T& t, std::ios_base::openmode which);

The semantics of `close` for a Device type `T` depends on its category as follows:

`category<T>::type` | semantics
--- | ---
not convertible to `closable_tag` | no-op
convertible to `closable_tag` and to `bidirectional` | calls `t.close(which)`
convertible to `closable_tag` and to `input` but not to `output` | calls `t.close()` if `(which & ios_base::in) != 0`
convertible to `closable_tag` and to `output` but not to `bidirectional` | calls `t.close()` if `(which & ios_base::out) != 0`

In short:

- If `T` is not Closable, `close` does nothing.
- If `T` is Closable and controls two separate sequences, `close` delegates to a member function `close` taking a single `openmode` parameter.
- Otherwise, `close` delegates to a member function `close` taking no parameters, but only if its `openmode` parameter is consistent with the mode of `T`.

The last condition prevents a Device controlling a single sequence from being closed twice in succession.

### Function Template `close` — Filter Types

#### Template Parameters

T | - | A model of one of the Filter concepts
Device | - | A Blocking Device whose mode refines that of `T`.

#### Semantics

    template<typename T, typename Device>
    void close(T& t, Device& next, std::ios_base::openmode which);

The semantics of `close` for a Filter type `T` depends on its category as follows:

`category<T>::type` | semantics
--- | ---
not convertible to `closable_tag` | no-op
convertible to `closable_tag` and to `bidirectional` | calls `t.close(next, which)`
convertible to `closable_tag` and to `input` but not to `output` | calls `t.close(next)` if `(which & ios_base::in) != 0`
convertible to `closable_tag` and to `output` but not to `bidirectional` | calls `t.close(next)` if `(which & ios_base::out) != 0`

In short:

- If `T` is not Closable, `close` does nothing.
- If `T` is Closable and controls two separate sequences, `close` delegates to a member function `close` taking `openmode` and stream buffer parameters.
- Otherwise, `close` delegates to a member function `close` taking a single stream buffer parameter, but only if its `openmode` parameter is consistent with the mode of `T`.

The last condition prevents a Filter controlling a single sequence from being closed twice in succession.

[1]This behavior can be disabled in the case of `pop` by calling member function `set_auto_close` with the argument `false`. See, e.g., `filtering_stream::set_auto_close`.

Revised 20 May, 2004

© Copyright Jonathan Turkanis, 2004

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)