C++ Stream API

Stream core

class dyad_stream_core

Core DYAD synchronization state and operations for C++ stream interception.

Wraps a dyad_ctx and exposes the producer/consumer synchronization operations needed by the C++ stream interception layer. Handles context initialization, file locking, path prefix matching, and open/close synchronization hooks.

A single instance is typically embedded in a stream wrapper object. The context may be initialized either from environment variables via init(bool) or from explicit parameters via init(const dyad_params&).

Note

dyad_stream_core does not initialize the DYAD context automatically in its constructor, nor does it tear it down in its destructor. Initialization and teardown are costly operations, and C++ objects may trigger many implicit copy constructions and destructions. The caller is responsible for explicitly calling dyad_stream_core::init() once and managing the context lifetime. stream wrapper classes only performs shallow copy of dyad_stream_core object as deep copying is not only costly but also can be desruptive by running routines that are supposed to run only once during the run.

Public Functions

dyad_stream_core()

Constructs an uninitialized stream core.

~dyad_stream_core()

Finalizes the stream core, releasing the DYAD context.

void init(const bool reinit = false)

Initializes the stream core from environment variables.

Retrieves an existing DYAD context via dyad_ctx_get() or initializes a new one if none exists, if reinit is true, or if the DYAD_REINIT environment variable is set. In case of (re)initialization, it relies on the environment variable-based method, dyad_init_env() which reads configuration from environment variables. The existence of environment variables DYAD_PATH_PRODUCER and DYAD_PATH_CONSUMER limits the potential producer and consumer roles role of the enclosing stream wrapper object. Has no effect if already initialized and neither reinit nor the environment variable DYAD_REINIT is set.

Parameters:

reinit[in] If true, forces re-initialization even if already initialized.

void init(const dyad_params &p)

Initializes the stream core from explicit parameters.

Calls dyad_init() with the settings in p and retrieves the resulting context. Producer and consumer roles are limited based on whether the managed paths in p are empty. Also sets ctx->use_fs_locks based on whether DYAD_HAS_STD_FSTREAM_FD is set at cmake configure time.

Parameters:

p[in] Parameters to initialize DYAD with.

void log_info(const std::string &msg_head) const

Logs the current DYAD configuration at INFO level.

Parameters:

msg_head[in] Header string printed before the configuration.

void finalize()

Releases the DYAD context and resets initialization state.

bool is_dyad_producer() const

Returns true if this instance is configured as a producer.

bool is_dyad_consumer() const

Returns true if this instance is configured as a consumer.

bool open_sync(const char *path)

Ensures a file is ready to read before a stream open.

Calls dyad_consume() if the instance is a consumer and is initialized. Returns true if the file is ready or if no action is needed (not a consumer, or not initialized).

Parameters:

path[in] Path to the file being opened.

Returns:

true on success or no-op, false if dyad_consume() failed.

bool close_sync(const char *path)

Publishes a file after a stream close.

Calls dyad_produce() if the instance is a producer and is initialized. Returns true if the file was published or if no action is needed (not a producer, or not initialized).

Parameters:

path[in] Path to the file being closed.

Returns:

true on success or no-op, false if dyad_produce() failed.

void set_initialized()

Marks the stream core as initialized without calling init().

bool chk_initialized() const

Returns true if the stream core has been initialized.

bool chk_fsync_write() const

Returns true if fsync() on write is enabled in the context.

bool cmp_canonical_path_prefix(bool is_prod, const char *const path)

Checks whether path falls under a DYAD-managed directory.

Delegates to cmp_canonical_path_prefix() and stores the extracted relative path in upath, retrievable via get_upath().

Parameters:
  • is_prod[in] If true, match against the producer-managed path; otherwise match against the consumer-managed path.

  • path[in] Path to check.

Returns:

true if path is under the managed directory.

std::string get_upath() const

Returns the relative path extracted by the last cmp_canonical_path_prefix() call.

int file_lock_exclusive(int fd) const

Acquires an exclusive lock on an open file descriptor.

Parameters:

fd[in] File descriptor to lock.

Returns:

dyad_rc_t return code from dyad_excl_flock().

int file_lock_shared(int fd) const

Acquires a shared lock on an open file descriptor.

Parameters:

fd[in] File descriptor to lock.

Returns:

dyad_rc_t return code from dyad_excl_flock().

int file_unlock(int fd) const

Releases a lock on an open file descriptor.

Parameters:

fd[in] File descriptor to unlock.

Returns:

dyad_rc_t return code from dyad_release_flock().

Input stream

template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
class basic_ifstream_dyad

A drop-in replacement for std::basic_ifstream that integrates DYAD consumer-side synchronization.

Wraps std::basic_ifstream and intercepts open() and close() to call dyad_consume() via the embedded dyad_stream_core, ensuring the file is ready to read before the stream is opened. All other stream operations are delegated to the underlying std::basic_ifstream.

The interface mirrors std::basic_ifstream as closely as possible, including C++11 move semantics, std::string overloads, and (in C++17) std::filesystem::path overloads, conditionally compiled based on the standard version in use.

Template Parameters:
  • _CharT – Character type of the stream.

  • _Traits – Character traits type. Defaults to std::char_traits<_CharT>.

Public Functions

basic_ifstream_dyad(const dyad_stream_core &core)

Constructs a stream with an existing dyad_stream_core.

Copies core into the embedded m_core and allocates the underlying stream without opening it. Does not call m_core.init() since the provided core is assumed to be already initialized.

Parameters:

core[in] Initialized stream core to copy.

basic_ifstream_dyad()

Constructs an unopened stream and initializes the core from environment variables via m_core.init().

explicit basic_ifstream_dyad(const char *filename, ios_base::openmode mode = ios_base::in)

Constructs and opens the stream, triggering consumer synchronization.

Initializes the core from environment variables, calls open_sync() to ensure the file is ready via dyad_consume(), then opens the underlying stream. m_filename is set only if the stream opened successfully.

Parameters:
  • filename[in] Path to the file to open.

  • mode[in] Open mode. Defaults to ios_base::in.

~basic_ifstream_dyad()

Destroys the stream, releasing the underlying basic_ifstream.

In C++03, explicitly deletes the raw pointer. In C++11 and later, resets the unique_ptr. Has no effect if the stream pointer is already nullptr.

void open(const char *filename, ios_base::openmode mode = ios_base::in)

Opens the file, triggering consumer synchronization.

Acquires a shared lock via DYAD_SHARED_LOCK_CPP_IFSTREAM, calls open_sync() to ensure the file is ready via dyad_consume(), then opens the underlying stream. If the stream pointer is nullptr, returns without action. m_filename is set only if the stream opened successfully.

Parameters:
  • filename[in] Path to the file to open.

  • mode[in] Open mode. Defaults to ios_base::in.

bool is_open()

Returns true if the underlying stream is open. Returns false if the stream pointer is nullptr.

void close()

Closes the stream and releases the file lock.

Releases the shared lock before closing the underlying stream. Has no effect if the stream pointer is nullptr.

filebuf *rdbuf() const

Returns the underlying stream buffer, or nullptr if the stream pointer is nullptr.

basic_ifstream &get_stream()

Returns a reference to the underlying std::basic_ifstream.

Warning

If the stream pointer is nullptr, behavior is undefined (TODO: throw).

void init(const dyad_stream_core &core)

Reinitializes the stream core from an existing dyad_stream_core.

Copies core into m_core, marks it as initialized via set_initialized(), and logs the new state via log_info().

Parameters:

core[in] Stream core to copy into this instance.

inline const dyad_stream_core &core() const

Allow read-only access to the embedded dyad_stream_core.

using dyad::ifstream_dyad = basic_ifstream_dyad<char>

basic_ifstream_dyad specialization for char.

using dyad::wifstream_dyad = basic_ifstream_dyad<wchar_t>

basic_ifstream_dyad specialization for wchar_t.

Output stream

template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
class basic_ofstream_dyad

A drop-in replacement for std::basic_ofstream that integrates DYAD producer-side synchronization.

Wraps std::basic_ofstream and intercepts open() and close() to acquire an exclusive file lock and call dyad_produce() via the embedded dyad_stream_core, notifying consumers that the file is ready. If DYAD_HAS_STD_FSTREAM_FD is set, locking is only applied when the file falls under the producer-managed path. Optionally calls fsync() before closing if ctx->fsync_write is enabled.

The interface mirrors std::basic_ofstream as closely as possible, including C++11 move semantics, std::string overloads, and (in C++17) std::filesystem::path overloads, conditionally compiled based on the standard version in use.

Template Parameters:
  • _CharT – Character type of the stream.

  • _Traits – Character traits type. Defaults to std::char_traits<_CharT>.

Public Functions

basic_ofstream_dyad(const dyad_stream_core &core)

Constructs a stream with an existing dyad_stream_core.

Copies core into the embedded m_core and allocates the underlying stream without opening it. Does not call m_core.init() since the provided core is assumed to be already initialized.

Parameters:

core[in] Initialized stream core to copy.

basic_ofstream_dyad()

Constructs an unopened stream and initializes the core from environment variables via m_core.init().

explicit basic_ofstream_dyad(const char *filename, ios_base::openmode mode = ios_base::out)

Constructs and opens the stream, acquiring an exclusive lock if the file is under the producer-managed path.

Initializes the core from environment variables and opens the underlying stream. If DYAD_HAS_STD_FSTREAM_FD is set and the file falls under the producer-managed path, acquires an exclusive lock via DYAD_EXCLUSIVE_LOCK_CPP_OFSTREAM and sets m_filename.

Parameters:
  • filename[in] Path to the file to open.

  • mode[in] Open mode. Defaults to ios_base::out.

~basic_ofstream_dyad()

Destroys the stream, syncing and publishing if still open.

If the stream is still open, optionally calls fsync_ofstream() if ctx->fsync_write is enabled, releases the exclusive lock, resets the stream, then calls close_sync() to publish the file via dyad_produce(). If the stream is already closed, simply resets it.

void open(const char *filename, ios_base::openmode mode = ios_base::out)

Opens the file and acquires an exclusive lock if under the producer-managed path.

Opens the underlying stream, then if DYAD_HAS_STD_FSTREAM_FD is set and the file is under the producer-managed path, acquires an exclusive lock via DYAD_EXCLUSIVE_LOCK_CPP_OFSTREAM and sets m_filename. Has no effect if the stream pointer is nullptr.

Parameters:
  • filename[in] Path to the file to open.

  • mode[in] Open mode. Defaults to ios_base::out.

bool is_open()

Returns true if the underlying stream is open. Returns false if the stream pointer is nullptr.

void close()

Closes the stream, syncing and publishing the file.

Optionally calls fsync_ofstream() if ctx->fsync_write is enabled, releases the exclusive lock via DYAD_UNLOCK_CPP_OFSTREAM, closes the underlying stream, then calls close_sync() to publish the file via dyad_produce(). Has no effect if the stream pointer is nullptr.

filebuf *rdbuf() const

Returns the underlying stream buffer, or nullptr if the stream pointer is nullptr.

basic_ofstream &get_stream()

Returns a reference to the underlying std::basic_ofstream.

void init(const dyad_stream_core &core)

Reinitializes the stream core from an existing dyad_stream_core.

Copies core into m_core, marks it as initialized via set_initialized(), and logs the new state via log_info().

Parameters:

core[in] Stream core to copy into this instance.

inline const dyad_stream_core &core() const

Allow read-only access to the embedded dyad_stream_core.

using dyad::ofstream_dyad = basic_ofstream_dyad<char>

basic_ofstream_dyad specialization for char.

using dyad::wofstream_dyad = basic_ofstream_dyad<wchar_t>

basic_ofstream_dyad specialization for wchar_t.

Bidirectional stream

template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
class basic_fstream_dyad

A drop-in replacement for std::basic_fstream that integrates DYAD producer and consumer-side synchronization.

Wraps std::basic_fstream and intercepts open() and close() to perform both consumer and producer synchronization via the embedded dyad_stream_core. On open, calls open_sync() to ensure the file is ready via dyad_consume(). If the instance is a producer, also acquires an exclusive lock (conditioned on DYAD_HAS_STD_FSTREAM_FD and path prefix matching). On close, if the instance is a producer, optionally calls fsync_fstream() and releases the lock before calling close_sync() to publish the file via dyad_produce().

The interface mirrors std::basic_fstream as closely as possible, including C++11 move semantics, std::string overloads, and (in C++17) std::filesystem::path overloads, conditionally compiled based on the standard version in use.

Template Parameters:
  • _CharT – Character type of the stream.

  • _Traits – Character traits type. Defaults to std::char_traits<_CharT>.

Public Functions

basic_fstream_dyad(const dyad_stream_core &core)

Constructs a stream with an existing dyad_stream_core.

Copies core into the embedded m_core and allocates the underlying stream without opening it. Does not call m_core.init() since the provided core is assumed to be already initialized.

Parameters:

core[in] Initialized stream core to copy.

basic_fstream_dyad()

Constructs an unopened stream and initializes the core from environment variables via m_core.init().

explicit basic_fstream_dyad(const char *filename, ios_base::openmode mode = ios_base::in | ios_base::out)

Constructs and opens the stream with both consumer and producer synchronization.

Initializes the core from environment variables, calls open_sync() to ensure the file is ready via dyad_consume(), then opens the underlying stream. If the instance is a producer and the stream opened successfully, acquires an exclusive lock (conditioned on DYAD_HAS_STD_FSTREAM_FD and path prefix matching in C++03) and sets m_filename.

Parameters:
  • filename[in] Path to the file to open.

  • mode[in] Open mode. Defaults to ios_base::in|out.

~basic_fstream_dyad()

Destroys the stream, syncing and publishing if still open.

If the stream is still open and the instance is a producer, optionally calls fsync_fstream() if ctx->fsync_write is enabled, releases the exclusive lock, resets the stream, then calls close_sync() to publish the file via dyad_produce(). If the stream is already closed, simply resets it.

void open(const char *filename, ios_base::openmode mode = ios_base::in | ios_base::out)

Opens the file with both consumer and producer synchronization.

Calls open_sync() to ensure the file is ready via dyad_consume(), then opens the underlying stream. If the instance is a producer and the stream opened successfully, acquires an exclusive lock (conditioned on DYAD_HAS_STD_FSTREAM_FD and path prefix matching) and sets m_filename. Has no effect if the stream pointer is nullptr.

Parameters:
  • filename[in] Path to the file to open.

  • mode[in] Open mode. Defaults to ios_base::in|out.

bool is_open()

Returns true if the underlying stream is open. Returns false if the stream pointer is nullptr.

void close()

Closes the stream, syncing and publishing the file if a producer.

If the instance is a producer, optionally calls fsync_fstream() if ctx->fsync_write is enabled, releases the exclusive lock via DYAD_UNLOCK_CPP_OFSTREAM, closes the underlying stream, then calls close_sync() to publish the file via dyad_produce(). Has no effect if the stream pointer is nullptr.

filebuf *rdbuf() const

Returns the underlying stream buffer, or nullptr if the stream pointer is nullptr.

basic_fstream &get_stream()

Returns a reference to the underlying std::basic_fstream.

void init(const dyad_stream_core &core)

Reinitializes the stream core from an existing dyad_stream_core.

Copies core into m_core, marks it as initialized via set_initialized(), and logs the new state via log_info().

Parameters:

core[in] Stream core to copy into this instance.

inline const dyad_stream_core &core() const

Allow read-only access to the embedded dyad_stream_core.

using dyad::fstream_dyad = basic_fstream_dyad<char>

basic_fstream_dyad specialization for char.

using dyad::wfstream_dyad = basic_fstream_dyad<wchar_t>

basic_fstream_dyad specialization for wchar_t.