.TH MPU_UNLOCKED 3 "August 2026" "libmpuio" "LIBMPUIO Programmer's Manual" .SH NAME mpu_unlocked \- LIBMPUIO operations that omit implicit stream locking .SH LIBRARY LIBMPUIO companion library for LIBMPU. .SH SYNOPSIS .nf #include int mpu_fgetc_unlocked( mpu_FILE *stream ); int mpu_getc_unlocked( mpu_FILE *stream ); int mpu_getchar_unlocked( void ); int mpu_fputc_unlocked( __mpu_char16_t c, mpu_FILE *stream ); int mpu_putc_unlocked( __mpu_char16_t c, mpu_FILE *stream ); int mpu_putchar_unlocked( __mpu_char16_t c ); __mpu_char16_t *mpu_fgets_unlocked( __mpu_char16_t *s, int n, mpu_FILE *stream ); int mpu_fputs_unlocked( const __mpu_char16_t *s, mpu_FILE *stream ); ssize_t mpu_getdelim_unlocked( __mpu_char16_t **lineptr, size_t *n, __mpu_char16_t delimiter, mpu_FILE *stream ); ssize_t mpu_getline_unlocked( __mpu_char16_t **lineptr, size_t *n, mpu_FILE *stream ); size_t mpu_fread_unlocked( void *ptr, size_t size, size_t nmemb, mpu_FILE *stream ); size_t mpu_fwrite_unlocked( const void *ptr, size_t size, size_t nmemb, mpu_FILE *stream ); int mpu_fflush_unlocked( mpu_FILE *stream ); int mpu_fpurge_unlocked( mpu_FILE *stream ); int mpu_vfprintf_unlocked( mpu_FILE *stream, const __mpu_char16_t *format, va_list args ); int mpu_fprintf_unlocked( mpu_FILE *stream, const __mpu_char16_t *format, ... ); int mpu_vprintf_unlocked( const __mpu_char16_t *format, va_list args ); int mpu_printf_unlocked( const __mpu_char16_t *format, ... ); int mpu_vfscanf_unlocked( mpu_FILE *stream, const __mpu_char16_t *format, va_list args ); int mpu_fscanf_unlocked( mpu_FILE *stream, const __mpu_char16_t *format, ... ); int mpu_vscanf_unlocked( const __mpu_char16_t *format, va_list args ); int mpu_scanf_unlocked( const __mpu_char16_t *format, ... ); int mpu_fileno_unlocked( mpu_FILE *stream ); int mpu_feof_unlocked( mpu_FILE *stream ); int mpu_ferror_unlocked( mpu_FILE *stream ); void mpu_clearerr_unlocked( mpu_FILE *stream ); .fi .SH DESCRIPTION Every function listed here performs the same logical operation as its ordinary counterpart but does not acquire or release the stream mutex. .PP This is analogous to the unlocked stdio family in libc. It is primarily useful for batching multiple operations under one explicit lock, avoiding repeated lock/unlock overhead while preserving atomicity with respect to other users of the same stream. .SH LOCKED VERSUS UNLOCKED .TS allbox tab(:); l l l. Operation:Locked form:Unlocked form character input:mpu_fgetc/mpu_getc/mpu_getchar:mpu_fgetc_unlocked/mpu_getc_unlocked/mpu_getchar_unlocked character output:mpu_fputc/mpu_putc/mpu_putchar:mpu_fputc_unlocked/mpu_putc_unlocked/mpu_putchar_unlocked string input/output:mpu_fgets/mpu_fputs:mpu_fgets_unlocked/mpu_fputs_unlocked raw binary:mpu_fread/mpu_fwrite:mpu_fread_unlocked/mpu_fwrite_unlocked flush:mpu_fflush:mpu_fflush_unlocked purge:mpu_fpurge:mpu_fpurge_unlocked formatted output:mpu_fprintf/mpu_printf + va_list forms:corresponding _unlocked forms formatted input:mpu_fscanf/mpu_scanf + va_list forms:corresponding _unlocked forms descriptor/status:mpu_fileno/mpu_feof/mpu_ferror:corresponding _unlocked forms clear error:mpu_clearerr:mpu_clearerr_unlocked .TE .PP There is intentionally no unlocked variant for operations such as .BR mpu_fopen (), .BR mpu_fdopen (), .BR mpu_fclose (), positioning, buffering configuration, or .BR mpu_ungetc (). Those APIs perform stream lifetime/state transitions for which the public API provides only the synchronized form. .PP .BR mpu_sprintf (), .BR mpu_snprintf (), .BR mpu_sscanf () and their va_list forms operate on caller-owned UCS-2 memory rather than an .B mpu_FILE stream, so a stream-unlocked variant is unnecessary. .SH REQUIRED CALLER DISCIPLINE An unlocked call is safe only when no other thread can concurrently access the same stream, or when the caller already owns the stream lock. .PP The normal pattern is: .nf mpu_flockfile( fp ); mpu_fputs_unlocked( text, fp ); mpu_fputc_unlocked( '\n', fp ); mpu_fflush_unlocked( fp ); mpu_funlockfile( fp ); .fi .PP The stream mutex is recursive, so calling an ordinary locked operation while holding an explicit flock is valid, although using the unlocked counterpart is usually the point of the explicit lock. .SH IMPORTANT DIFFERENCES .B mpu_fflush_unlocked() requires a non-NULL stream and flushes only that stream. .B mpu_fflush(NULL) is the synchronized all-streams operation; NULL has no all-streams meaning for the unlocked form. .PP .B mpu_fpurge_unlocked() has exactly the same discard semantics as mpu_fpurge(), but assumes that the caller already owns the stream lock or otherwise has exclusive access. .PP Unlocked formatted functions use exactly the same format grammar, MPU size rules, count semantics, locale behavior, rollback rules, and errors as their locked counterparts. They differ only in implicit stream locking. .PP Unlocked raw I/O remains byte-oriented. Unlocked text I/O remains strict UCS-2 internally and UTF-8 at real-file boundaries. .PP The ordinary mpu_fileno() entry point acquires the stream mutex; mpu_fileno_unlocked() reads the same descriptor state without acquiring it. .SH RETURN VALUE Exactly as documented for the corresponding ordinary function. .SH ERRORS Exactly as documented for the corresponding ordinary function. The unlocked property does not suppress validation or backend errors. .SH THREAD SAFETY Ordinary stream calls are internally synchronized. Unlocked calls are not safe for concurrent access to the same stream unless the application supplies external synchronization. Concurrent use of an unlocked operation and .BR mpu_fclose () on the same stream without application synchronization is invalid. .SH SEE ALSO .BR libmpuio (3), .BR mpu_flockfile (3), .BR mpu_fgetc (3), .BR mpu_fread (3), .BR mpu_fpurge (3), .BR mpu_printf (3), .BR mpu_scanf (3) .SH DYNAMIC LINE INPUT .BR mpu_getline_unlocked () and .BR mpu_getdelim_unlocked () have the same allocation, delimiter, EOF, UCS-2 validation, and return-value semantics as their locked forms. Only implicit acquisition of the stream mutex is omitted. The caller remains responsible for free(3) of the resulting buffer.