Skip to content

Conversation

@chaokunyang
Copy link
Collaborator

@chaokunyang chaokunyang commented Jan 3, 2026

Why?

C++ serialization needs support for weak pointers to handle circular references in graph-like structures (e.g., parent-child relationships). Unlike std::weak_ptr<T>, we need a wrapper that allows updating the internal pointer during deserialization for forward reference resolution.

What does this PR do?

Adds SharedWeak<T> - a serializable wrapper around std::weak_ptr<T> designed for graph structures with circular references.

Key features:

  1. SharedWeak<T> wrapper class (weak_ptr_serializer.h)

    • Stores std::weak_ptr<T> inside std::shared_ptr<Inner> so all copies share the same internal storage
    • Enables forward reference resolution via callbacks during deserialization
    • Provides from(), upgrade(), update(), expired() methods
  2. Forward reference resolution (ref_resolver.h)

    • Added add_update_callback(ref_id, UpdateCallback) overload to RefReader
    • When deserializing a weak pointer that references an object not yet created, registers a callback to update it later
  3. Serializer implementation (weak_ptr_serializer.h)

    • Handles NULL_FLAG, REF_FLAG, and REF_VALUE_FLAG properly
    • Requires track_ref=true for reference tracking
    • Supports forward reference resolution via callbacks
  4. Type traits

    • is_shared_weak<T> - detection trait
    • requires_ref_metadata<SharedWeak<T>> - always true
    • is_nullable<SharedWeak<T>> - always true

Example usage:

struct Node {
  int32_t value;
  SharedWeak<Node> parent;              // Non-owning back-reference
  std::vector<std::shared_ptr<Node>> children;  // Owning references
};
FORY_STRUCT(Node, value, parent, children);

auto parent = std::make_shared<Node>();
parent->value = 1;

auto child = std::make_shared<Node>();
child->value = 2;
child->parent = SharedWeak<Node>::from(parent);
parent->children.push_back(child);

// Serialize and deserialize
auto bytes = fory.serialize(parent);
auto result = fory.deserialize<std::shared_ptr<Node>>(bytes);

// Parent reference is preserved
assert(result->children[0]->parent.upgrade() == result);

Related issues

#1017
#2906
Closes #2976
Closes #2977

Does this PR introduce any user-facing change?

  • Does this PR introduce any public API change?
    • Adds new SharedWeak<T> class for C++ users
  • Does this PR introduce any binary protocol compatibility change?

Benchmark

N/A - this is a new feature addition.

@chaokunyang chaokunyang changed the title feat(c++): add circualr ref support for c++ feat(c++): add SharedWeak<T> for circular reference support Jan 3, 2026
@chaokunyang chaokunyang merged commit ca2e990 into apache:main Jan 3, 2026
54 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[C++] Align reference tracking for xlang mode [C++] Support circular reference by weak_ptr

2 participants