For the complete documentation index, see llms.txt. This page is also available as Markdown.

Deferred Execution

Where Parallel Tasks Join

Consider the following example contracts. They demonstrate another key feature called deferred execution, where the scheduler moves transactions to the next generation to create a custom aggregation point after parallel execution.

Example1

VisitCounterWithDeferred uses U256Cumulative for parallel-safe increments and adds a deferred join step: all visit() calls in a generation run in parallel, with one promoted to the next generation to emit the aggregated result after the generation boundary.

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0;

import "@arcologynetwork/concurrentlib/lib/commutative/U256Cum.sol"; 
import "@arcologynetwork/concurrentlib/lib/runtime/Runtime.sol"; 

// This counter supports commutative updates, allowing safe aggregation
// of increments from multiple transactions in parallel.
contract VisitCounterWithDeferred { 
    // A cumulative counter instance that allows concurrent increments
    // from multiple transactions without conflicts.   
    U256Cumulative totalVisit; 
    
    event CounterQuery(uint256 value);

    constructor()  {
        // Initialize the cumulative counter with a starting value of 0
        // and an upper limit of 1,000,000. Any attempt to exceed the
        // range will cause the transaction to revert.
        totalVisit = new U256Cumulative(0, 1000000);

        // Inform the scheduler when there are multiple transaction 
        // calling visit(), one of them will be executed in the
        // deferred transaction. Each call to visit() is charged an 
        // extra 2,000 gas to fund the deferred join step run later
        // in the block. If the deferred transaction fails, 
        // the unused gas is refunded.
        Runtime.defer("visit()", 2000);
    }

    // Increments the visit counter by 1.
    // Multiple invocations in the same generation can be executed in parallel
    // and will be merged deterministically by Arcology at commit time.
    function visit() public {
        // The line below adds 1 to the visit counter, which will executed anyway.
        totalVisit.add(1);

        // If the transaction is in a deferred generation, emit the counter value.
        // The code is executed in the deferred transaction only.
        if (Runtime.isInDeferred()) {
            emit CounterQuery(totalVisit.get());
        }
    }
}

Example 2

Last updated