Hanzi Design
Concept close

close · shut

Gate + Talent

Close is transition to sealed state. What was open becomes shut—access terminated, flow stopped, connection severed. Closing is active operation, not passive decay. Files must be closed after writing. Connections must be closed after communication. Transactions must be closed after completion. Failed closure creates resource leaks—the unclosed resource consumes memory, holds locks, occupies connections. Systems track what is open to ensure eventual closing. The close operation releases resources for reuse. It finalizes state changes made during open period. It ensures clean transition from active to inactive. Close is not merely opposite of open but essential cleanup operation. Every open requires corresponding close.

🚪⬅

Resource Release

Closing releases resources for reuse. Open file handle consumes file descriptor. Close returns descriptor to available pool. The release enables subsequent opens.

Resource exhaustion occurs when closing fails. Leaked file descriptors eventually deplete pool. Leaked memory eventually exhausts allocator. Leaked connections eventually saturate server. The leakage is cumulative—each failed close worsens situation.

Disciplined closing prevents exhaustion. Close immediately after use completes. Use try-finally to ensure closing happens even during errors. Automatic resource management (RAII, context managers) enforces closing discipline. The enforcement prevents human error.

Finalization

Closing finalizes state changes. Written data becomes persistent. Transaction commits become durable. The finalization makes temporary changes permanent.

Without finalization, work is lost. Unflushed writes disappear. Uncommitted transactions rollback. The work appeared successful but vanished due to missing close.

Close operations should force finalization. Flush buffers before closing files. Commit transactions before closing connections. The finalization during close ensures work persists.

Graceful vs. Abrupt Close

Graceful closing completes pending operations before sealing. Buffers flush. Messages finish sending. State finalizes properly. The graceful close is clean.

Abrupt closing terminates immediately. Pending operations are cancelled. Unflushed buffers are discarded. State may be inconsistent. The abrupt close is fast but dirty.

The appropriate close type depends on urgency. Normal shutdown uses graceful close. Emergency shutdown accepts abrupt close. The trade-off is completeness versus speed.

Close After Error

What happens when close is attempted after error? Does close succeed, fail, or partially complete? The error handling determines resource fate.

Robust closing attempts cleanup regardless of prior errors. Error during operation doesn't prevent close attempt. The close might partially succeed—some resources released, others stuck. Partial success is better than no cleanup.

Close itself can fail. File close fails if disk full. Connection close fails if network unreachable. The close failure indicates resource remains allocated. The caller must decide: retry close, accept leak, or escalate to process restart.

Idempotent Close

Can you close twice safely? Idempotent close allows multiple calls without error. The second close recognizes already-closed state and returns successfully without action.

Non-idempotent close fails on second attempt. The failure indicates programming error—attempting to close already-closed resource. The error detection catches double-close bugs.

Both approaches have merits. Idempotent close simplifies error recovery—can close without checking state. Non-idempotent close provides error checking—detects double-close bugs. The choice depends on whether bug detection or simplicity matters more.

Automatic vs. Manual Close

Automatic closing uses language features (destructors, defer, with-statements) to ensure close happens. The automatic mechanism reduces error risk.

Manual closing requires explicit close calls. Forgetting to close causes leaks. The manual approach is error-prone but provides precise control over timing.

Prefer automatic closing for safety. Use manual closing only when timing precision matters. The automatic approach prevents most resource leaks.

Close Propagation

Does closing parent close children? Closing database connection might close prepared statements. Closing network connection might close streams. The propagation policy determines what gets closed.

Propagating close simplifies resource management. Close parent and all children close automatically. Single close call cleans up entire resource tree.

Non-propagating close requires manual child cleanup. Must close each resource explicitly. The manual approach is tedious but provides precise control. Sometimes selective closing is needed—close some children but not others.

Close Notification

When resource closes, who needs notification? Dependent components might need to know closure happened. The notification enables coordinated cleanup.

Connection close events notify dependent sessions. Stream close events flush pending writes. The notifications enable orderly shutdown across multiple components.

Notification failures complicate closing. If notification mechanism fails, close might succeed partially. Some components know closure happened; others remain unaware. The partial notification creates inconsistent state.

Reopen Capability

Some resources can reopen after closing. File can close and reopen. Connection can close and reconnect. The reopening restores access after temporary closure.

Other resources cannot reopen. Destructors cannot undo destruction. Committed transactions cannot uncommit. The irreversible close is final.

Distinguishing reopenable from final closure helps set expectations. Reopenable resources support retry patterns. Final closures require complete reinitialization for second attempt.

Close Timeout

How long should close wait for completion? Graceful close might block indefinitely waiting for operations to complete. Timeout prevents hanging close operations.

Timeout-based close starts gracefully but switches to abrupt if timeout expires. The switch ensures close completes eventually. The timeout duration balances cleanup completeness against response time.

Zero timeout is immediate abrupt close. Infinite timeout waits indefinitely for graceful close. Intermediate timeout attempts grace period before forcing closure. The timeout selection depends on shutdown urgency.

Close Detection

How do you detect closure happened? Check closed flag, attempt operation and catch error, or receive close notification? The detection method affects code robustness.

State flag checking is fastest but creates race condition. Check state, then operate—but state might change between check and operation. The TOCTTOU bug.

Exception-based detection is safer. Attempt operation; handle closed exception if thrown. The exception indicates actual closure at operation time. The approach eliminates race condition but uses exceptions for control flow.

Notification-based detection receives async notification when closure happens. The notification is immediate but adds complexity. The listener infrastructure must be maintained.