This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: kmp-darwin-gcd-concurrency-invariant

Kotlin Multiplatform Darwin GCD & ARC Concurrency Invariant

Enforces strict synchronization boundaries, autoreleasepool enclosures, and non-blocking dispatcher handoffs between Kotlin Coroutines and Apple Grand Central Dispatch (GCD). Eliminates thread starvation under Darwin GCD worker pool limits and prevents ARC memory leaks or use-after-free races across the Kotlin/Native and Darwin runtime boundaries.

Prohibited Anti-Pattern: Unconfined Coroutine Dispatching and Blocking Across Darwin GCD Worker Thread Pools

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Kotlin Multiplatform Darwin GCD & ARC Concurrency Invariant - Enforces strict synchronization boundaries, autoreleasepool enclosures, and non-blocking dispatcher handoffs between Kotlin Coroutines and Apple Grand Central Dispatch (GCD). Eliminates thread starvation under Darwin GCD worker pool limits and prevents ARC memory leaks or use-after-free races across the Kotlin/Native and Darwin runtime boundaries.
globs: **/*Darwin*.kt, **/*Ios*.kt, **/iosMain/**/*.kt, **/darwinMain/**/*.kt, **/appleMain/**/*.kt
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/kmp-darwin-gcd-concurrency-invariant"
---

# Kotlin Multiplatform Darwin GCD & ARC Concurrency Invariant

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Unconfined Coroutine Dispatching and Blocking Across Darwin GCD Worker Thread Pools

## System Constraints
You are a Principal Mobile Architect specializing in Kotlin Multiplatform and Apple Darwin runtimes. Enforce strict invariants when bridging Kotlin Coroutines with Grand Central Dispatch (GCD) and Objective-C/Swift ARC memory management. Prevent thread pool exhaustion, deadlocks, and cross-runtime reference retention.

## Strict Guidelines
- Engineers MUST ALWAYS wrap native Darwin object allocations and bridge calls inside kotlinx.cinterop.autoreleasepool { ... } blocks within asynchronous Kotlin Coroutine dispatch loops.
- Engineers MUST NEVER invoke runBlocking or blocking synchronization primitives (such as dispatch_semaphore_wait or pthread_mutex) on Darwin GCD background queues or Dispatchers.Main.
- Engineers MUST ALWAYS use custom limited-parallelism dispatchers or Dispatchers.Default for computationally intensive background tasks to prevent exhausting Darwin's 64-thread global concurrent queue pool limit.
- Code MUST explicitly decouple native Darwin completion handlers from Coroutine continuations using suspendCancellableCoroutine with an explicit invokeOnCancellation cleanup handler.
- Engineers MUST NOT capture raw Kotlin object references across asynchronous GCD blocks without using StableRef or verifying lifecycle scoping to avoid ARC and Kotlin/Native cyclic retention.

## Bad vs Good Implementations
### Bridging Asynchronous Darwin GCD APIs to Coroutines with Autoreleasepool and Cancellation

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Using runBlocking and dispatch_semaphore_wait blocks the calling thread, rapidly starving Darwin's constrained 64-worker-thread GCD pool. Furthermore, Objective-C objects allocated inside the callback lack an autoreleasepool scope, leading to unbounded ARC memory growth on worker threads.
```kotlin
import kotlinx.coroutines.runBlocking
import platform.Foundation.NSURLSession
import platform.Foundation.NSURLRequest
import platform.Foundation.NSURL
import platform.darwin.dispatch_semaphore_create
import platform.darwin.dispatch_semaphore_signal
import platform.darwin.dispatch_semaphore_wait
import platform.darwin.DISPATCH_TIME_FOREVER

fun fetchDarwinPayloadBlocking(urlString: String): String = runBlocking {
    val semaphore = dispatch_semaphore_create(0)
    var result = ""
    val url = NSURL(string = urlString)
    val request = NSURLRequest(uRL = url)
    
    // Anti-pattern: Blocking GCD worker thread via semaphore wait;
    // Captures Objective-C objects outside autoreleasepool across coroutine context;
    // Risks Darwin thread exhaustion and ARC uncollected references.
    NSURLSession.sharedSession.dataTaskWithRequest(request) { data, _, _ ->
        data?.let {
            result = it.base64Encoding()
        }
        dispatch_semaphore_signal(semaphore)
    }.resume()
    
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
    result
}
```

#### Production Standard (Correct)
> **Standard**: Adheres to the Darwin GCD invariant by non-blocking suspension via suspendCancellableCoroutine, wrapping Darwin calls in autoreleasepool to ensure ARC frees temporary allocations promptly, and attaching an invokeOnCancellation handler to preempt orphaned tasks.
```kotlin
import kotlinx.cinterop.autoreleasepool
import kotlinx.coroutines.suspendCancellableCoroutine
import platform.Foundation.NSURL
import platform.Foundation.NSURLRequest
import platform.Foundation.NSURLSession
import platform.Foundation.NSURLSessionDataTask
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

suspend fun fetchDarwinPayload(urlString: String): String = suspendCancellableCoroutine { continuation ->
    autoreleasepool {
        val url = NSURL(string = urlString) ?: run {
            continuation.resumeWithException(IllegalArgumentException("Invalid URL: $urlString"))
            return@autoreleasepool
        }
        val request = NSURLRequest(uRL = url)
        var task: NSURLSessionDataTask? = null
        
        task = NSURLSession.sharedSession.dataTaskWithRequest(request) { data, _, error ->
            autoreleasepool {
                if (error != null) {
                    continuation.resumeWithException(RuntimeException(error.localizedDescription))
                } else {
                    val payload = data?.base64Encoding() ?: ""
                    continuation.resume(payload)
                }
            }
        }
        
        continuation.invokeOnCancellation { 
            task?.cancel()
        }
        
        task.resume()
    }
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Kotlin Multiplatform Darwin GCD & ARC Concurrency Invariant

Kotlin Multiplatform Darwin GCD & ARC Concurrency Invariant defines an industrial-grade behavioral standard for mobile engineering. Enforces strict synchronization boundaries, autoreleasepool enclosures, and non-blocking dispatcher handoffs between Kotlin Coroutines and Apple Grand Central Dispatch (GCD). Eliminates thread starvation under Darwin GCD worker pool limits and prevents ARC memory leaks or use-after-free races across the Kotlin/Native and Darwin runtime boundaries. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Unconfined Coroutine Dispatching and Blocking Across Darwin GCD Worker Thread Pools Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftUnconfined Coroutine Dispatching and Blocking Across Darwin GCD Worker Thread PoolsCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS wrap native Darwin object allocations and bridge calls inside kotlinx.cinterop.autoreleasepool { ... } blocks within asynchronous Kotlin Coroutine dispatch loops.

Engineers MUST ALWAYS wrap native Darwin object allocations and bridge calls inside kotlinx.cinterop.autoreleasepool { ... } blocks within asynchronous Kotlin Coroutine dispatch loops.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NEVER invoke runBlocking or blocking synchronization primitives (such as dispatch_semaphore_wait or pthread_mutex) on Darwin GCD background queues or Dispatchers.Main.

Engineers MUST NEVER invoke runBlocking or blocking synchronization primitives (such as dispatch_semaphore_wait or pthread_mutex) on Darwin GCD background queues or Dispatchers.Main.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST ALWAYS use custom limited-parallelism dispatchers or Dispatchers.Default for computationally intensive background tasks to prevent exhausting Darwin's 64-thread global concurrent queue pool limit.

Engineers MUST ALWAYS use custom limited-parallelism dispatchers or Dispatchers.Default for computationally intensive background tasks to prevent exhausting Darwin's 64-thread global concurrent queue pool limit.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Code MUST explicitly decouple native Darwin completion handlers from Coroutine continuations using suspendCancellableCoroutine with an explicit invokeOnCancellation cleanup handler.

Code MUST explicitly decouple native Darwin completion handlers from Coroutine continuations using suspendCancellableCoroutine with an explicit invokeOnCancellation cleanup handler.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Engineers MUST NOT capture raw Kotlin object references across asynchronous GCD blocks without using StableRef or verifying lifecycle scoping to avoid ARC and Kotlin/Native cyclic retention.

Engineers MUST NOT capture raw Kotlin object references across asynchronous GCD blocks without using StableRef or verifying lifecycle scoping to avoid ARC and Kotlin/Native cyclic retention.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Kotlin Multiplatform Darwin GCD & ARC Concurrency Invariant critical for AI coding assistants?

Enforces strict synchronization boundaries, autoreleasepool enclosures, and non-blocking dispatcher handoffs between Kotlin Coroutines and Apple Grand Central Dispatch (GCD). Eliminates thread starvation under Darwin GCD worker pool limits and prevents ARC memory leaks or use-after-free races across the Kotlin/Native and Darwin runtime boundaries. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Unconfined Coroutine Dispatching and Blocking Across Darwin GCD Worker Thread Pools) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related MOBILE Rules

View all rules →
1 Rule in Stack

Kotlin