docs: update CHANGELOG and README for v1.0.0-pre.3
This commit is contained in:
+19
-1
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.0.0-pre.3] - 2026-03-07
|
||||
|
||||
### Added
|
||||
- `STK_MOD_DEP_LOG_BUFFER` (2048) added to `stk.h`
|
||||
|
||||
### Changed
|
||||
- Dependency failure logging now emits a single line per module listing all unmet deps with their reason: `not found` or `requires <constraint>, have <version>`
|
||||
- `Deferring 'test_mod_dep': unmet deps: test_mod (not found)`
|
||||
- `Unloading 'test_mod_dep': unmet deps: test_mod (not found), renderer (requires ^2.0.0, have 1.3.0)`
|
||||
- Silent defer at `stk_init` and vague `"unmet dependencies"` cascade log in `stk_poll` replaced with `stk_log_dependency_failures()`
|
||||
- Kahn topological sort refactored into generic `stk_kahn_sort()` accepting a `has_dep` callback and an `on_cycle` callback, decoupling it from `stk_modules`. `stk_topo_sort()` is now a thin wrapper. `stk_sort_load_order()` uses the same core via `stk_batch_has_dep()`, inspecting tmp files so simultaneous load events are processed dependency-first without a retry cycle
|
||||
- `stk_module_load()` split into `stk_module_preload()`, `stk_module_activate()`, `stk_module_discard()`, and `stk_validate_dependencies_single()`. Init is not called if deps are unmet
|
||||
- On UNLOAD events in `stk_poll()`, the unload set is expanded to include all transitively dependent modules via `stk_collect_dependents()`, sorted dependents-first via `stk_sort_unload_order()`. Modules unloaded due to expansion are queued to pending
|
||||
- On LOAD events with unmet dependencies, the tmp path is added to the pending queue instead of being dropped
|
||||
- `stk_pending_retry()` now skips already-loaded entries and prunes entries whose file no longer exists
|
||||
- `free_poll` label moved above `stk_pending_retry()` so retry always runs regardless of exit path
|
||||
|
||||
## [1.0.0-pre.2] - 2026-03-06
|
||||
|
||||
### Fixed
|
||||
@@ -145,7 +162,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Dependency management and versioning not yet implemented
|
||||
- API is unstable and subject to change in future releases
|
||||
|
||||
[Unreleased]: https://github.com/anth64/stk/compare/v1.0.0-pre.2...HEAD
|
||||
[Unreleased]: https://github.com/anth64/stk/compare/v1.0.0-pre.3...HEAD
|
||||
[1.0.0-pre.3]: https://github.com/anth64/stk/compare/v1.0.0-pre.2...v1.0.0-pre.3
|
||||
[1.0.0-pre.2]: https://github.com/anth64/stk/compare/v1.0.0-pre.1...v1.0.0-pre.2
|
||||
[1.0.0-pre.1]: https://github.com/anth64/stk/compare/v0.1.3...v1.0.0-pre.1
|
||||
[0.1.3]: https://github.com/anth64/stk/releases/tag/v0.1.3
|
||||
|
||||
@@ -234,7 +234,7 @@ stk_init();
|
||||
|
||||
## Project Status
|
||||
|
||||
**Current Version:** 1.0.0-pre.1
|
||||
**Current Version:** 1.0.0-pre.3
|
||||
|
||||
### What Works
|
||||
- Cross-platform module loading and hot-reloading
|
||||
@@ -244,6 +244,7 @@ stk_init();
|
||||
- Runtime-configurable logging behavior
|
||||
- Optional module metadata (name, version, description)
|
||||
- Dependency declaration, validation, and versioning
|
||||
- Detailed dependency failure logging (missing ids, version mismatches)
|
||||
- Cascade unload when dependencies are removed
|
||||
- Pending queue with automatic retry when deps become available
|
||||
- Topological sort with cycle detection
|
||||
|
||||
+3
-39
@@ -206,18 +206,8 @@ unsigned char stk_validate_dependencies(size_t count)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* has_dep(i, j, ctx): return 1 if node i depends on node j, 0 otherwise.
|
||||
* Used by stk_kahn_sort to abstract over loaded modules vs incoming batch.
|
||||
*/
|
||||
typedef int (*stk_dep_query_fn)(size_t i, size_t j, void *ctx);
|
||||
|
||||
/*
|
||||
* Core Kahn's topological sort. Produces dependencies-first ordering.
|
||||
* on_cycle is called for each node not reachable (i.e. in a cycle).
|
||||
* Returns STK_MOD_INIT_SUCCESS or STK_MOD_DEP_CIRCULAR_ERROR /
|
||||
* STK_MOD_REALLOC_FAILURE.
|
||||
*/
|
||||
static unsigned char stk_kahn_sort(size_t count, size_t *order,
|
||||
stk_dep_query_fn has_dep, void *ctx,
|
||||
void (*on_cycle)(size_t i))
|
||||
@@ -722,11 +712,6 @@ static int stk_batch_has_dep(size_t i, size_t j, void *ctx)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort file_indices[] (length n) so that within the batch, modules whose ids
|
||||
* appear as dependencies of others come first. Uses already-copied tmp files
|
||||
* to read dep symbols. Falls back to original order if sort fails.
|
||||
*/
|
||||
void stk_sort_load_order(int *file_indices, size_t n,
|
||||
char (*file_names)[STK_PATH_MAX], const char *tmp_dir)
|
||||
{
|
||||
@@ -761,12 +746,6 @@ cleanup:
|
||||
free(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand indices[0..]*in_count to include all loaded modules that transitively
|
||||
* depend on any module already in the set. Writes the expanded set back into
|
||||
* indices[] and updates *out_count. indices[] must have capacity module_count.
|
||||
* Returns 1 if any new dependents were added, 0 otherwise.
|
||||
*/
|
||||
void stk_collect_dependents(size_t *indices, size_t *count)
|
||||
{
|
||||
size_t i, d;
|
||||
@@ -775,7 +754,6 @@ void stk_collect_dependents(size_t *indices, size_t *count)
|
||||
do {
|
||||
changed = 0;
|
||||
for (i = 0; i < module_count; i++) {
|
||||
/* skip if already in the set */
|
||||
in_set = 0;
|
||||
{
|
||||
size_t k;
|
||||
@@ -789,17 +767,16 @@ void stk_collect_dependents(size_t *indices, size_t *count)
|
||||
if (in_set)
|
||||
continue;
|
||||
|
||||
/* check if any of its deps are in the set */
|
||||
for (d = 0; d < stk_modules[i].dep_count; d++) {
|
||||
int dep_idx =
|
||||
int dep_index =
|
||||
is_mod_loaded(stk_modules[i].deps[d].id);
|
||||
if (dep_idx < 0)
|
||||
if (dep_index < 0)
|
||||
continue;
|
||||
{
|
||||
size_t k;
|
||||
for (k = 0; k < *count; k++) {
|
||||
if (indices[k] ==
|
||||
(size_t)dep_idx) {
|
||||
(size_t)dep_index) {
|
||||
indices[(*count)++] = i;
|
||||
changed = 1;
|
||||
goto next_module;
|
||||
@@ -812,11 +789,6 @@ void stk_collect_dependents(size_t *indices, size_t *count)
|
||||
} while (changed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort indices[] (length n) so that dependents come before their dependencies.
|
||||
* This is the reverse of topological order. indices[] is sorted in-place.
|
||||
* Falls back to reverse-index order if topo sort fails or alloc fails.
|
||||
*/
|
||||
void stk_sort_unload_order(size_t *indices, size_t n)
|
||||
{
|
||||
size_t *topo = NULL;
|
||||
@@ -836,10 +808,6 @@ void stk_sort_unload_order(size_t *indices, size_t n)
|
||||
if (stk_topo_sort(module_count, topo) != STK_MOD_INIT_SUCCESS)
|
||||
goto fallback;
|
||||
|
||||
/*
|
||||
* topo[] is dependencies-first. Walk it in reverse to get
|
||||
* dependents-first, picking only indices that are in our set.
|
||||
*/
|
||||
k = 0;
|
||||
for (i = module_count; i > 0; --i) {
|
||||
size_t mod = topo[i - 1];
|
||||
@@ -866,7 +834,6 @@ void stk_sort_unload_order(size_t *indices, size_t n)
|
||||
fallback:
|
||||
free(topo);
|
||||
free(result);
|
||||
/* reverse index order: higher indices (dependents) first */
|
||||
for (i = 0; i < n / 2; i++) {
|
||||
size_t tmp = indices[i];
|
||||
indices[i] = indices[n - 1 - i];
|
||||
@@ -891,7 +858,6 @@ void stk_module_unload_all(void)
|
||||
stk_module_unload(order[i]);
|
||||
free(order);
|
||||
} else {
|
||||
/* fallback: reverse index order */
|
||||
for (i = module_count; i > 0; --i)
|
||||
stk_module_unload(i - 1);
|
||||
}
|
||||
@@ -943,7 +909,6 @@ void stk_pending_add_batch(const char (*paths)[STK_PATH_MAX_OS], size_t count)
|
||||
if (!paths || count == 0)
|
||||
return;
|
||||
|
||||
/* First pass: overwrite existing entries and count truly new ones */
|
||||
new_count = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
int found = 0;
|
||||
@@ -979,7 +944,6 @@ void stk_pending_add_batch(const char (*paths)[STK_PATH_MAX_OS], size_t count)
|
||||
free(stk_pending);
|
||||
stk_pending = new_pending;
|
||||
|
||||
/* Second pass: append only the truly new ones */
|
||||
for (i = 0; i < count; i++) {
|
||||
int found = 0;
|
||||
extract_module_id(paths[i], incoming_id);
|
||||
|
||||
Reference in New Issue
Block a user