[MUD-Dev] Re: atomic functions

Felix A. Croes felix at xs1.simplex.nl
Sun May 3 01:23:12 New Zealand Standard Time 1998

Shawn Halpenny <malachai at iname.com> wrote:

> On Fri, May 01, 1998 at 03:11:58PM +0200, Felix A. Croes wrote:
> > To transplant the idea of atomic functions to your model, in which
> > functions are already implicitly atomic, make the following change:
> > rather than
> > 
> > 	atomic foo()
> > 	{
> > 	    /* code of foo */
> > 	}
> > 
> > use
> > 
> > 	foo()
> > 	{
> > 	    /* code fragment 1 */
> > 
> > 	    atomic {
> > 		/* code fragment 2, executed atomically */
> > 	    }
> > 
> > 	    /* code fragment 3 */
> > 	}
> So atomic fragments are akin to critical sections?

They are similar, though critical sections are handled differently in
my server.  They are run with "infinite" resources -- that is, the event
will not run out of ticks or stack frames while in the critical section.
Obviously, the use of critical sections cannot be allowed to guest-
programmers on a mud, which is one of my reasons for considering to
add relatively harmless atomic functions/fragments.

> If you are moving toward a lockless DB scheme, will you still require
> atomic fragments?  If you have a 1-to-1 mapping between thread and event,
> do the atomic sections only come into play when multiple events are
> executing the same method?  Currently, I've got each method executing in
> its own stack with local copies of all data.

At present, my server does not have atomic functions/fragments/sections
(I rather like "sections"!) at all.  I mean to add multi-threading
similar to yours: events work on a local copy of data and upon
completion either commit the changes or fail, depending on whether
other events already committed changes to the same data meanwhile.
However, function calls occur within the current event and do not
start a new one, and runtime errors do not cause the current event to

My reasons for considering to add atomic sections as a feature are:

 1) I find them desirable.
 2) after going multi-threaded as outlined above, they will be trivial
    to implement.

> Explicitly defining an atomic function would require more programmer
> work.  In a free user programming environment, I don't want to require
> people to decide whether the function they just wrote to make their
> sword talk needs to be atomic or have atomic sections within it.  For
> now, I'm opting to leave it up to the server to decide the atomicity of
> things (which it does by way of the event and DB models).  An
> experienced programmer can probably outdo the server if given the
> capability to declare atomic blocks, but a newbie would be more
> inclined to either not declare them at all (in which case, I'd have to
> rely on a system like I've already got in mind) or declare them poorly
> and result in performance worse than the server would obtain doing it
> itself.  

Critical code exists, and a programmer may decide to protect it.
To the programmer who makes that decision, atomic sections will be
a lot easier to use and comprehend than the various checks that
would have to be made to ensure that the code will be executed
either as a whole or not at all.  Implementing atomic sections as
atomic functions is done to make this easy (no new code structure
to learn).

Being able to nest atomic sections is important to me.

The performance hit does not bother me.  On a mud with programming
guests, there is no real protection against someone executing an
infinite loop.  Rather, ensure that costly code is actually made
costly to use: double the amount of ticks spent while executing
atomic sections, and implement per-programmer tick quotas.

Can your solution of letting runtime errors cancel the current
event deal with the following case:

	    if B() succeeds then

with the requirement that A() and C() together, or A() and D()
together must be executed atomically?

> > > I would consider each executing
> > > event method an atomic function as you've described them--all of the
> > > effects undone on failed C&C reset the world state for that event to
> > > the new current state.  A runtime error in a function essentially
> > > amounts to a failed C&C, since the end result is the same:  no changes
> > > persist.  However, a failed function will cause the event method in
> > > which it was called to not be rescheduled and thus it will not attempt
> > > to C&C again.  A C&C failure without a corresponding function error is
> > > perfectly acceptable and, in fact, required.  
> > 
> > In this model, atomic code fragments would still be useless, since
> > an error in an atomic fragment would cancel the entire event.  To
> > make them meaningful, you would need a way to (optionally) catch
> > errors in an event.  That way, individual bits of atomic code could
> > fail without the entire event failing.
> What happens if there is an error in an atomic fragment, and the rest of
> the event requires a result out of that fragment?

The event fails to obtain this result.  It may either catch the error
and perform some alternative action, or complete (and eventually commit)
with an error.  I do not consider this to be a problem.  Rather, I
think that events which do not disappear when an error occurs facilitate
debugging. :)

> One different thing about the system I'm describing is that
> events using an intersecting working set don't know that they will fail and
> be rescheduled until they all try and C&C.  This is where atomic fragments
> could be beneficial since the working set modifications could take place
> inside them, waiting on other events as required.  My approach:  if an
> event succeeds C&C, other events with intersecting working sets are
> notified and immediately rescheduled, rather than waiting until they are
> try (and assuredly fail) C&C.  (This has been on the list before, too).
> This way, I'm not redoing operations I've already performed and thrown out
> to the extent I would if the entire event went through its processing
> before finding out it couldn't commit changes.

I am not yet sure whether I want to do this, since finding out which
other still-running events have an intersecting working set may be a
costly operation, and locking would be needed to store the information
in a common spot.

Felix Croes

MUD-Dev: Advancing an unrealised future.

More information about the MUD-Dev mailing list