CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
Protected Blocks

Macros

#define pblock
 
#define pblockUnwind(num)   _pblockUnwind((void*)_pblock_unwind_top, (num))
 
#define PBLOCK_AFTER
 

Detailed Description

Advanced Feature: Protected blocks with multi-level stack unwinding capabilities.

Protected blocks provide stack unwinding through setjmp/longjmp, allowing early exit from nested blocks with guaranteed cleanup. They are the foundation for the exception handling system but can be used independently.

Performance Warning:

Protected blocks are heavyweight operations with significant costs:

When to Use:

When NOT to Use:

For most resource management needs, use blkWrap() from Block Wrapping instead.

Example:

// Complex operations with multiple potential exit points
if (error1) pblockUnwind(1); // Exit this block
// Nested protected block
if (error2) pblockUnwind(2); // Exit both blocks
// Cleanup for inner block - always runs
}
// Cleanup for outer block - always runs
}
#define pblock
Definition pblock.h:124
#define pblockUnwind(num)
Definition pblock.h:182
#define PBLOCK_AFTER
Definition pblock.h:214

Macro Definition Documentation

◆ pblock

#define pblock

pblock { }

Advanced Feature: Declares a protected block with stack unwinding capability.

A protected block sets up a setjmp buffer for stack unwinding that can be jumped to using pblockUnwind(). Protected blocks can be nested, and an arbitrary number of layers can be unwound in a single operation.

Cleanup with PBLOCK_AFTER:

A protected block can optionally end with a PBLOCK_AFTER: pseudo-label. Code after this label executes when exiting the block normally OR when unwinding through it, providing guaranteed cleanup similar to a finally clause.

Performance Implications:

  • Setjmp adds measurable overhead on every entry
  • Inhibits compiler optimizations (inlining, register allocation, etc.)
  • Consumes significant stack space (~200+ bytes per nested level)
  • Use only when simpler alternatives are insufficient
Note
return statements are not allowed within protected blocks (compile error in debug builds)
This is the foundation for ptTry/ptCatch, but can be used independently

Example:

resource1 = acquire1();
if (!resource1) pblockUnwind(1);
resource2 = acquire2();
if (!resource2) pblockUnwind(1);
// Use resources
// Cleanup runs even if we unwind early
if (resource2) release2(resource2);
if (resource1) release1(resource1);
}
Warning
Prefer blkWrap() for simple resource management - it's much lighter weight
See also
pblockUnwind(), PBLOCK_AFTER, blkWrap()

Definition at line 124 of file pblock.h.

◆ PBLOCK_AFTER

#define PBLOCK_AFTER
Value:
if (0) { \
/* Even though this case 1 label is placed into the user-defined block, it technically exists within \
* the switch statement at the end of the pblock macro. \
* When the user provides a PBLOCK_AFTER target, it defines this case 1 which overrides the default \
* case label (the one that's hidden in the if(0) after the case 2:) and comes here instead. */ \
case 1: \
_pblock_target = _pblock_unwind_top[0].target; \
_pblock_unwind = !!_pblock_target; \
/* Execution falls through to the statement below. */ \
} \
/* This odd looking construct exists to swallow the ':' after the fake PBLOCK_AFTER label. */ \
switch(0) case 0

PBLOCK_AFTER:

Pseudo-label marking the cleanup section of a protected block.

Code after this label is guaranteed to execute before control flow leaves the protected block, similar to a finally clause in exception handling. This occurs both during normal exit and during unwinding.

The cleanup code runs:

  • When the block completes normally
  • When pblockUnwind() is called from within the block
  • When unwinding through this block from a nested pblockUnwind()
  • When an exception propagates through this block (if using ptTry)

Example:

file = fopen("data.txt", "r");
if (!file) pblockUnwind(1);
processFile(file);
// This ALWAYS runs, even if we unwind early
if (file) fclose(file);
}
Note
Not affected by abnormal control flow from outside (longjmp, signals, etc.)
See also
pblock, pblockUnwind()

Definition at line 214 of file pblock.h.

◆ pblockUnwind

#define pblockUnwind (   num)    _pblockUnwind((void*)_pblock_unwind_top, (num))

pblockUnwind(num)

Exits the current protected block early via stack unwinding.

Triggers unwinding of one or more nested protected blocks, jumping to the appropriate PBLOCK_AFTER cleanup section if one exists, then continuing to outer blocks if needed.

Parameters
numNumber of nested blocks to exit:
  • 1 - Exit only the current protected block
  • 2 - Exit current and one outer block
  • -1 - Exit all protected blocks, returning to the outermost level

Example:

pblock { // Outer
pblock { // Inner
if (error) pblockUnwind(1); // Exit inner only
if (fatal) pblockUnwind(2); // Exit both
if (abort) pblockUnwind(-1); // Exit all
// Cleanup inner
}
// Cleanup outer
}
Note
All PBLOCK_AFTER sections are executed during unwinding
See also
pblock, PBLOCK_AFTER

Definition at line 182 of file pblock.h.