Re: Circlemud design issues

From: James Turner (turnerjh@XTN.NET)
Date: 04/20/98

George <greerga@CIRCLEMUD.ORG> writes:

> Imagine throwing out all of the state stuff, dumping the current game_loop,
> and running a huge amount of mobs every half second without lag.  You could
> do as much as you wanted and there would be no lag in cycling back to the
> person.  Sort of like having two processors to handle more processes, we'd
> have more threads to handle more people seemingly at the same time.

The problem in this though is that you have incredibly annoying
synchronization issues.  Moreover, you can never guarantee, short of
using huge mutex locks all over the code, than a valid target on line
X will be valid on line Y.  Also, synchronization of fights is an
issue.  And unless some kind of slowdown is put on command execution,
players with faster links will be able to do more commands than those
with slower (as opposed to the current one command per player per pass
in the main loop).

> pthreads is all I'd support.  If you don't have POSIX threads, tough, use
> the non-threaded version which would be included in the same base and also
> supported.

It's messy.  It would fundamentally change the code; supporting two
versions wouldn't be nearly as easy as now, and just about every
snippet would need a threads version and a non threads version.

> #define GET_NAME(ch)    getName(ch)
> char *getName(struct char_data *ch)
> {
>    [blah]
> }
> Of course, now 'GET_NAME(ch) = NULL;' doesn't work.
> But it wouldn't work with your non-macro version either.  This is of
> course, avoiding C++.

Things like GET_NAME(ch) = p, GET_STR(ch) = 10, etc., are bad as-is.
There is no assurance that data assigned is valid.  setName,
setStrength, etc would be better ways to assign these.

> >Not true, as I showed in a different post.  We can use weak
> >inheritance to get the same effect as macros.  Further, we get
> But we're not using C++.

Weak inheritance is what I referred to in one of my previous posts,
with the three structures.

> >That was my point -- inlining every function won't work.  We should
> >help the compiler pick what functions to inline instead of relying on
> >its own algorithms.  That's what the inline keyword is for.
> There is also a reason the compiler picks functions to inline.  I've heard
> GCC will inline things very liberally, some up to 200 lines of code.

gcc is picky, and stubborn, and somewhat obstinate sometimes, and
inlining is one.  It is rather ad hoc about it.

> >> >ones stock has now) and derived abilities (say we want an ability
> >> >based partially on strength and endurance).
> >>
> >> #define GET_STR(ch)     ((GET_DEX(ch) + GET_CON(ch)) / 2)
> >
> >What if it involves a table lookup?
> #define GET_STR(ch)     (str_app_index[ch->str].tohit)
> Or you layer further down, just like functions do.

There's no check to see if ch's str is valid, or if ch is a valid
pointer, etc etc etc.  Macros are bad.

> Contrived example, in your case you'd either use a function or make a
> smarter macro.

From a previous response,

#define MAX(a, b) ((a) > (b) ? (a) : (b))

top = MAX(x++, 4);

Problems like this sneak into code, and make diagnosis sometimes

> >and the con of the one after that.  Contrived example somewhat, but
> >macros have their limits, George.  They are headaches to maintain and
> As I just said, but macros are not evil and functions are not god.

Certainly macros are not evil.  But the current use in Circle is
excessive and dangerous ;)

> >them that a memory reference to NULL took place.  If GET_NAME were a
> >function, the seg violation would occur at the right place inside that
> >function -- or better yet, in an assert() statement).
> Um, if you see something that crashed on a line:
>   strcmp(GET_NAME(ch), "bob")
> and 'ch' is NULL, what is the difference?

If this line crashes, ch could be null, or ch->name could be NULL.
There's no way to tell without checking data explicitly with a print
statement in gdb.

> >Three-line macros, strung together with && and || are a headache to
> >maintain and deal with.  There is absolutely no need in modern
> So are those kinds of 'if' statements, but you don't seem against those.

You've not asked ;)  Stringing logic statements together can be
annoying to maintain and painful to read.  Whether it be in a macro or
an if statement.

> >computing in these cases.  Circle is a mud, not a compiler, or runtime
> >interpreter.  Speed is important, but we're not exactly burning CPU
> >time as-is.  We can afford to spend a few more cycles for a more
> >robust, reliable codebase.
> The way you imply we'd be doing redundancy checks upon redundancy checks.

Redundancy can be good.  Error checking is better.  I'd rather my
player files not get corrupt by errant pointers or whatnot.  NULL
pointers won't do this, but invalid pointers can.  It is dangerous to
always assume pointers are valid (and non-null pointers can be checked
for validity with, say, magic bytes).

Using assert() and defining DEBUG and such would take care of the
performance issue on production builds.

James Turner     

     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     | |

This archive was generated by hypermail 2b30 : 12/15/00 PST