contract ThisExternalAssembly {
    uint public numcalls;
    uint public numcallsinternal;
    uint public numfails;
    uint public numsuccesses;
    
    address owner;

    event logCall(uint indexed _numcalls, uint indexed _numcallsinternal);
    
    modifier onlyOwner { if (msg.sender != owner) throw; _ }
    modifier onlyThis { if (msg.sender != address(this)) throw; _ }

    // constructor
    function ThisExternalAssembly() {
        owner = msg.sender;
    }

    function failSend() external onlyThis returns (bool) {
        // storage change + nested external call
        numcallsinternal++;
        owner.send(42);

        // placeholder for state checks
        if (true) throw;

        // never happens in this case
        return true;
    }
    
    function doCall(uint _gas) onlyOwner {
        numcalls++;

        address addr = address(this);
        bytes4 sig = bytes4(sha3("failSend()"));

        bool ret;

        // work around `solc` safeguards for throws in external calls
        // https://ethereum.stackexchange.com/questions/6354/
        assembly {
            let x := mload(0x40) // read "empty memory" pointer
            mstore(x,sig)

            ret := call(
                _gas, // gas amount
                addr, // recipient account
                0,    // value (no need to pass)
                x,    // input start location
                0x4,  // input size - just the sig
                x,    // output start location
                0x1)  // output size (bool - 1 byte)

            //ret := mload(x) // no return value ever written :/
            mstore(0x40,add(x,0x4)) // just in case, roll the tape
        }

        if (ret) { numsuccesses++; }
        else { numfails++; }

        // mostly helps with function identification if disassembled
        logCall(numcalls, numcallsinternal);
    }

    // will clean-up :)
    function selfDestruct() onlyOwner { selfdestruct(owner); }
    
    function() { throw; }
}