What does atomic mean or do?

A function can be declared to be atomic:

Example 4-1. An atomic function

atomic void foo()
{
    ...
}

Atomic functions treat errors in a special way. If an error occurs, every change made by this function is undone, including changes made in functions called by this function.

It is illegal to use file or directory changing kfuns from atomically executed code:

Atomically executed code uses twice as many ticks as normal code.

An example given by Dworkin on the mailing-list:

The 2.4.5 mudlib for DGD contains the following code in /dgd/lib/inventory.c:

private void move(object obj, object from, object dest)
{
    int light;

    light = query_light(obj);
    if (from != 0) {
        from->_F_rm_inv(obj, light);
    }
    obj->_F_move(dest);
    dest->_F_add_inv(obj, light);
}

This code is called from the move_object() efun to do the actual movement. If it were to fail halfway through, this would result in an inconsistency. For example, if the inventory array of `dest' already has the maximum size, adding the object `obj' to the inventory of `dest' will result in an error; this will leave the environment of `obj' set to `dest' while `obj' is not actually in the inventory of `dest'.

Furthermore, there are some errors that can happen in almost any code: running out of ticks, or out of stack space for nested function calls. (It so happens that this particular code snippet is safe from those errors.)

Now if the function were made atomic, it would either succeed normally, or fail without making any change at all. The object is either moved or not moved -- it cannot get stuck in an intermediate state where it is half moved.

Using atomic is not the only solution. It may be possible to check for all possible error conditions in advance, and only execute the code if it's safe. Alternatively, an error occurring halfway through could be caught, and the already-performed actions could be undone explicitly. However, using atomic is always the most simple solution, often the cheapest, and sometimes the only possible one.

There is a lot of code out there that doesn't check for errors at all, of course. The atomic function feature could be used to guard such code from inconsistencies with only minimal rewriting.