Skip to content

Add ForeignPointer for C/FFI handle ownership#1

Draft
Copilot wants to merge 8 commits into
mainfrom
copilot/add-foreign-pointer-implementation
Draft

Add ForeignPointer for C/FFI handle ownership#1
Copilot wants to merge 8 commits into
mainfrom
copilot/add-foreign-pointer-implementation

Conversation

Copilot AI commented Jan 22, 2026

Copy link
Copy Markdown

Extends safety framework with ForeignPointer<T, Deleter> to replace std::unique_ptr for C/FFI/GPU/OS handles, keeping all ownership abstractions within the framework.

Implementation

  • safety/foreign_pointer.h: RAII wrapper with custom deleter support, no-throw semantics, move-only. Includes self-assignment protection in reset() to prevent double-free (safer than std::unique_ptr's UB).

  • .clang-tidy: Added safety-foreignpointer-for-c-api enforcement rule alongside existing safety-smartpointer-in-try.

  • README.md: Updated ownership model to 4 patterns. Documents that ForeignPointer is required for foreign handles and forbids std::unique_ptr/SafePointer/SmartPointer for C APIs.

  • main.cpp: Demonstrates proper usage with FILE* and C API contexts, including NULL checking pattern.

Usage

struct FileDeleter {
    void operator()(FILE* f) const noexcept {
        if (f) fclose(f);
    }
};

FILE* raw = fopen("data.txt", "r");
if (raw) {
    safety::ForeignPointer<FILE, FileDeleter> file(raw);
    // Automatic cleanup on scope exit
}

Ownership Rules

  • Application objects: SafePointer, SafeResultPointer
  • Startup/throwing: SmartPointer (inside try/catch only)
  • C/FFI/GPU/OS handles: ForeignPointer (this PR)
  • Forbidden: std::unique_ptr for foreign handles, raw owning pointers
Original prompt

Add a clang tidy rule and implement following, update readme accordingly.
IMPORTANT SAFETY FRAMEWORK EXTENSION – DO NOT DEVIATE

We are extending our existing safety framework with a new ownership type
called safety::ForeignPointer.

GOAL:

Replace std::unique_ptr usage for owned C / FFI handles
Keep all ownership inside our safety framework
Do NOT use SafePointer or SmartPointer for C API handles
RULES:

Do NOT introduce raw owning pointers (T*).
Application-level ownership must use:
safety::SafePointer
safety::SafeResultPointer
Throwing ownership is ONLY allowed via:
safety::SmartPointer (inside try/catch at startup boundaries)
C / FFI / GPU / OS handles MUST use:
safety::ForeignPointer<T, Deleter>
Do NOT use std::unique_ptr for C API ownership.
Do NOT add safety::SafeBoundary except at true entry points.
Worker threads MUST begin with safety::SafeScope.
No exceptions may escape worker threads.
IMPLEMENTATION REQUIRED
Create a new file:
safety/foreign_pointer.h

WITH THIS EXACT IMPLEMENTATION:

#pragma once
#include

namespace safety {

template <typename T, typename Deleter>
class ForeignPointer {
public:
ForeignPointer() noexcept : ptr_(nullptr), deleter_() {}

explicit ForeignPointer(T* ptr, Deleter deleter = Deleter{}) noexcept
    : ptr_(ptr), deleter_(deleter) {}

~ForeignPointer() noexcept {
    reset();
}

ForeignPointer(const ForeignPointer&) = delete;
ForeignPointer& operator=(const ForeignPointer&) = delete;

ForeignPointer(ForeignPointer&& other) noexcept
    : ptr_(other.ptr_), deleter_(std::move(other.deleter_)) {
    other.ptr_ = nullptr;
}

ForeignPointer& operator=(ForeignPointer&& other) noexcept {
    if (this != &other) {
        reset();
        ptr_ = other.ptr_;
        deleter_ = std::move(other.deleter_);
        other.ptr_ = nullptr;
    }
    return *this;
}

T* get() const noexcept { return ptr_; }
explicit operator bool() const noexcept { return ptr_ != nullptr; }

void reset(T* ptr = nullptr) noexcept {
    if (ptr_) {
        deleter_(ptr_);
    }
    ptr_ = ptr;
}

private:
T* ptr_;
Deleter deleter_;
};

} // namespace safety
REFactor REQUIRED
Refactor STTService to:

Remove std::unique_ptr<whisper_context>

Use safety::ForeignPointer<whisper_context, WhisperDeleter>

Example:

cpp
Copy code
struct WhisperDeleter {
void operator()(whisper_context* ctx) const noexcept {
whisper_free(ctx);
}
};

safety::ForeignPointer<whisper_context, WhisperDeleter> ctx_;
Replace all ctx_.get() usage accordingly.

DOCUMENTATION
Update README.md to include:

ForeignPointer is REQUIRED for owned C / FFI / GPU / OS handles

SafePointer is for application objects only

SmartPointer is startup-only and throwing

Raw owning pointers are forbidden

CONSTRAINTS
Do NOT introduce new pointer abstractions

Do NOT change existing SafePointer semantics

Do NOT weaken exception safety

All code must compile with clang++ 19


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 7 commits January 22, 2026 02:43
Co-authored-by: scriptmaster <544175+scriptmaster@users.noreply.github.com>
Co-authored-by: scriptmaster <544175+scriptmaster@users.noreply.github.com>
Co-authored-by: scriptmaster <544175+scriptmaster@users.noreply.github.com>
Co-authored-by: scriptmaster <544175+scriptmaster@users.noreply.github.com>
Co-authored-by: scriptmaster <544175+scriptmaster@users.noreply.github.com>
Co-authored-by: scriptmaster <544175+scriptmaster@users.noreply.github.com>
Copilot AI changed the title [WIP] Add safety::ForeignPointer ownership type Add ForeignPointer for C/FFI handle ownership Jan 22, 2026
Copilot AI requested a review from scriptmaster January 22, 2026 02:50
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.

2 participants