# Version and Settings

The knobs that control how facil.io identifies itself and behaves at compile time.

For core types and everyday helpers, see [`./000 core.md`](https://facil.io/0.8.x/facil-io-stl-core/). This page covers version macros and core behavioral defaults; for per-inclusion hooks such as allocator routing and pointer tagging, see [`./001 header.h`](https://facil.io/0.8.x/api/001-header/).

## Version Macros

facil.io follows [semantic versioning](https://semver.org). These macros are defined in [`./000 core.h`](https://facil.io/0.8.x/api/000-core/) and can be used to detect the library version at compile time.

- **`FIO_VERSION_MAJOR`** — Major version. API/ABI breaking changes bump this.  
  Default: `0`
- **`FIO_VERSION_MINOR`** — Minor version. Significant features or deprecations. May break ABI.  
  Default: `8`
- **`FIO_VERSION_PATCH`** — Patch version. Bug fixes and small additions.  
  Default: `0`
- **`FIO_VERSION_BUILD`** — Optional build metadata, such as `"rc.02"`.  
  Default: `"rc.02"`
- **`FIO_VERSION_STRING`** — Full version as a string literal, built from the macros above. The guard is `#ifdef FIO_VERSION_BUILD`, so the build metadata is included whenever `FIO_VERSION_BUILD` is defined, including when defined as an empty string: `"0.8.0-rc.02"`. If `FIO_VERSION_BUILD` is undefined, the string reads `"0.8.0"`.  
  Because [`./000 core.h`](https://facil.io/0.8.x/api/000-core/) unconditionally `#define`s `FIO_VERSION_BUILD "rc.02"` before the `#ifdef` guard, omitting the suffix requires `#undef FIO_VERSION_BUILD` before inclusion, not merely leaving it undefined.

Override these only when you are vendoring a fork or need to report a custom build string.

## Compile-Time Behavioral Defaults

Most defaults are guarded with `#ifndef`; define them before including the header to override the default. `FIO_NO_LOG` and `DEBUG` are presence flags rather than `#ifndef` defaults.

### Memory and Safety

- **`FIO_LEAK_COUNTER`** — Enables memory-leak counting. When enabled, the leak counter tracks allocations made through facil.io allocators and prints a summary at exit.  
  Default: `1` (enabled).  
  Set to `0` to disable counting and the exit report.  
  Note: this conflicts with `FIO_NO_LOG`, because the leak report uses the logging layer.
- **`FIO_LEAK_COUNTER_SKIP_EXIT`** — Skip the automatic leak report at exit when leak counting is enabled.  
  Default: `0` (report at exit).
- **`FIO_LEAK_COUNTER_DEF(name)`** — Declares a named leak counter.
- **`FIO_LEAK_COUNTER_ON_ALLOC(name)`** — Records an allocation against the named counter.
- **`FIO_LEAK_COUNTER_ON_FREE(name)`** — Records a free against the named counter.
- **`FIO_LEAK_COUNTER_COUNT(name)`** — Returns the current value of the named counter.
- **`FIO_MEMORY_INITIALIZE_ALLOCATIONS_DEFAULT`** — When non-zero, facil.io allocators zero-initialize returned memory by default.  
  Default: `1` (secure by default).  
  Set to `0` if you want raw allocations and prefer to do your own initialization.
- **`FIO_MEM_PAGE_SIZE_LOG`** — Log₂ of the OS memory page size. The memory allocator uses this to round allocations and map memory efficiently.  
  Default: `12` (4096-byte pages).  
  Change it if you are targeting a system with a different page size.
- **`FIO_STATIC_ALLOC_SAFE_CONCURRENCY_MAX`** — Default slot count for selected internal `FIO_STATIC_ALLOC_DEF` invocations (default: `256`). The macro does not use this setting implicitly; pass it explicitly as the fourth argument where appropriate.

### Concurrency

- **`FIO_USE_THREAD_MUTEX`** — Choose the locking primitive used by thread-safe modules.  
  Default: `0` (use facil.io spinlocks).  
  Set to `1` to use OS native mutexes (`pthread_mutex_t` on POSIX) instead.  
  If you need this decision to apply to only a single `#include`, use `FIO_USE_THREAD_MUTEX_TMP` in [`./001 header.h`](https://facil.io/0.8.x/api/001-header/) instead.

### Performance and Alignment

- **`FIO_UNALIGNED_ACCESS`** — Allows facil.io to attempt unaligned memory access on CPUs that support it. When enabled, the library may use faster paths in helpers such as `fio_buf2uXX`.  
  Default: `1` (attempt detection).  
  Set to `0` on strict-alignment architectures or if you want to forbid unaligned access entirely. The actual capability is reflected by `FIO_UNALIGNED_MEMORY_ACCESS_ENABLED`, which is derived at compile time.
- **`FIO_LIMIT_INTRINSIC_BUFFER`** — Limits register pressure in some pseudo-intrinsic loops by processing smaller batches and looping more.  
  Default: `1`.  
  Set to `0` if you prefer larger unrolled buffers and do not mind the extra register use.

### Maps

- **`FIO_MAP_WARNING_BITSIZE`** — Bit size at which hash-map allocations trigger an internal warning threshold in the `imap`/`map` templates.  
  Default: `24`.  
  Raise or lower it to tune when the library starts worrying about map size during growth.

### Logging

- **`FIO_NO_LOG`** — Define this to remove all logging output. Cannot be combined with `FIO_LEAK_COUNTER`; the two are mutually exclusive.
- **`FIO_LOG2STDERR`** — Low-level sink used by the logging macros.  
  Default: no-op.  
  Override to print to `stderr` or route messages to a custom destination.
- **`FIO_LOG_LENGTH_LIMIT`** — Approximate cap on a single formatted log message, limiting stack memory use.  
  Default: `1024`.
- **`DEBUG`** — Define this to enable debug-only log macros (`FIO_LOG_D*`) and active `FIO_ASSERT_DEBUG` checks. Also disables SIMD/Neon intrinsics in [`./000 core.h`](https://facil.io/0.8.x/api/000-core/).

### Memory allocator routing

These macros are defined in [`./001 header.h`](https://facil.io/0.8.x/api/001-header/) and are re-evaluated on every inclusion cycle. Define them before the first fio-stl include to replace memory routing globally.

- **`FIO_MEM_REALLOC(ptr, old_size, new_size, copy_len)`** — Reallocate a block, copying at least `copy_len` bytes if a move is required. Defaults to the system `realloc` unless the facil.io allocator is available, in which case it routes to `fio_realloc2`. Override to plug in a custom allocator.
- **`FIO_MEM_FREE(ptr, size)`** — Free a block. Defaults to the system `free` or `fio_free`. Override alongside `FIO_MEM_REALLOC`.
- **`FIO_MEMORY_DISABLE`** — Define to disable all custom facil.io allocators and force system `malloc`/`free` for temporary allocations.
- **`FIO_MALLOC_TMP_USE_SYSTEM`** — Force the recursive allocator variant to use the system `realloc`/`free`. Useful when a custom `FIO_MEM_REALLOC` needs an allocation path that will not recurse back into facil.io.
- **`FIO_MEM_REALLOC_` / `FIO_MEM_FREE_`** — Recursive-safe copies of `FIO_MEM_REALLOC`/`FIO_MEM_FREE`. Override these when the custom allocator itself needs to allocate or free memory without re-entering the override.
- **`FIO_MEM_REALLOC_ALIGNED(ptr, old_size, new_size, copy_len, alignment)`** — Reallocate with a minimum pointer alignment, **assigning** the result to `ptr` (save a copy first if failure must be recoverable). `alignment` of `0` selects the allocator default; non power-of-2 values are rounded down to a power of 2; effective alignment never drops below the current alignment of `ptr` nor below the allocator default. Routes to `fio_realloc_aligned` when the facil.io allocator is available, or to the system backends (`_aligned_realloc` on Windows, `posix_memalign`-based emulation on POSIX).
- **`FIO_MEM_FREE_ALIGNED(ptr, size)`** — Free a block obtained through `FIO_MEM_REALLOC_ALIGNED`. With the facil.io allocator this is simply `fio_free` (which accepts interior pointers); with the system backends it routes to `_aligned_free` on Windows or `free` on POSIX. Custom allocators that stash alignment bookkeeping near the returned pointer should override this pair together.
- **`FIO_MEM_ALLOC_SIZE(size)`** — The usable bytes the allocator reserves for a `size` request (`fio_alloc_size`, or the identity function with the system allocator).
- **`FIO_MEM_REALLOC_ALIGNED_` / `FIO_MEM_FREE_ALIGNED_`** — Recursive-safe copies of the aligned pair, mirroring `FIO_MEM_REALLOC_` / `FIO_MEM_FREE_`.

### Pointer tagging

These macros are defined in [`./001 header.h`](https://facil.io/0.8.x/api/001-header/) and let included types store a small marker in the unused low bits of aligned pointers.

- **`FIO_PTR_TAG(p)`** — Apply the tag to a pointer. Default is the identity function.
- **`FIO_PTR_UNTAG(p)`** — Remove the tag from a pointer. Default is the identity function.
- **`FIO_PTR_TAG_TYPE`** — If defined, functions returning a type's pointer return this type instead.
- **`FIO_PTR_TAG_VALIDATE(ptr)`** — Returns a true value if the tagged pointer is valid. Default checks for non-`NULL`.
- **`FIO_PTR_TAG_VALID_OR_RETURN(tagged_ptr, value)`** — Validates the tagged pointer and returns `value` if it fails validation.
- **`FIO_PTR_TAG_VALID_OR_RETURN_VOID(tagged_ptr)`** — Validates the tagged pointer and returns `void` if it fails validation.
- **`FIO_PTR_TAG_VALID_OR_GOTO(tagged_ptr, label)`** — Validates the tagged pointer and jumps to `label` if it fails validation.
- **`FIO_PTR_TAG_GET_UNTAGGED(untagged_type, tagged_ptr)`** — Cast the untagged pointer to `untagged_type *`.

Pointer tagging is used by dynamic-type wrappers (for example, FIOBJ) to distinguish object kinds without a separate type field.

## See Also

- [`./000 core.md`](https://facil.io/0.8.x/facil-io-stl-core/) — documentation for core types and helpers.
- [`./000 core.h`](https://facil.io/0.8.x/api/000-core/) — the source of truth for version macros and the defaults above.
- [`./001 header.h`](https://facil.io/0.8.x/api/001-header/) — per-inclusion overrides such as `FIO_USE_THREAD_MUTEX_TMP` and allocator routing macros.
