short ef_type;
short com_uid;
unsigned com_seqno;
+ unsigned com_generation;
time_t com_timestamp;
natid com_owner;
/* end of part matching struct empobj */
short ef_type;
short uid;
unsigned seqno;
+ unsigned generation;
time_t timestamp;
/* end of part matching struct emptypedstr */
natid own; /* valid if EFF_OWNER is in table's flags */
short ef_type;
short uid;
unsigned seqno;
+ unsigned generation;
time_t timestamp;
};
extern struct castr *ef_cadef(int);
extern int ef_read(int, int, void *);
+extern void ef_make_stale(void);
+extern void ef_mark_fresh(int, void *);
extern void *ef_ptr(int, int);
extern char *ef_nameof(int);
extern time_t ef_mtime(int);
short ef_type;
short game_uid;
unsigned game_seqno;
+ unsigned game_generation;
time_t game_timestamp;
/* end of part matching struct empobj */
char game_upd_disable; /* updates disabled? */
short ef_type;
short lnd_uid; /* unit id (land unit) */
unsigned lnd_seqno;
+ unsigned lnd_generation;
time_t lnd_timestamp; /* Last time this unit was touched */
natid lnd_own; /* owner's country num */
coord lnd_x; /* x location in abs coords */
short ef_type;
short l_uid;
unsigned l_seqno;
+ unsigned l_generation;
time_t l_timestamp;
/* end of part matching struct empobj */
natid l_loner; /* loan shark */
short ef_type;
short lost_uid;
unsigned lost_seqno;
+ unsigned lost_generation;
time_t lost_timestamp; /* When it was lost */
natid lost_owner; /* Who lost it */
/* end of part matching struct empobj */
short ef_type;
short r_uid; /* realm table index */
unsigned r_seqno;
+ unsigned r_generation;
time_t r_timestamp; /* Last time this realm was touched */
natid r_cnum; /* country number */
/* end of part matching struct empobj */
short ef_type;
short nat_uid; /* equals nat_cnum */
unsigned nat_seqno;
+ unsigned nat_generation;
time_t nat_timestamp;
natid nat_cnum; /* our country number */
/* end of part matching struct empobj */
short ef_type;
short nws_uid;
unsigned nws_seqno;
+ unsigned nws_generation;
time_t nws_timestamp;
/* end of part matching struct empobj */
natid nws_ano; /* "actor" country # */
short ef_type;
short nuk_uid;
unsigned nuk_seqno;
+ unsigned nuk_generation;
time_t nuk_timestamp; /* Last time this nuke was touched */
natid nuk_own;
coord nuk_x, nuk_y; /* current loc of device */
short ef_type;
short pln_uid; /* plane unit id */
unsigned pln_seqno;
+ unsigned pln_generation;
time_t pln_timestamp; /* Last time this plane was touched */
natid pln_own; /* owning country */
coord pln_x; /* plane x-y */
short ef_type;
short sct_uid; /* equals XYOFFSET(sct_x, sct_y) */
unsigned sct_seqno;
+ unsigned sct_generation;
time_t sct_timestamp; /* Last time this sector was written to */
natid sct_own; /* owner's country num */
coord sct_x; /* x coord of sector */
short ef_type;
short shp_uid; /* unit id (ship #) */
unsigned shp_seqno;
+ unsigned shp_generation;
time_t shp_timestamp; /* Last time this ship was touched. */
natid shp_own; /* owner's country num */
coord shp_x; /* x location in abs coords */
short ef_type;
short trd_uid;
unsigned trd_seqno;
+ unsigned trd_generation;
time_t trd_timestamp;
natid trd_owner;
/* end of part matching struct empobj */
short ef_type;
short trt_uid;
unsigned trt_seqno;
+ unsigned trt_generation;
time_t trt_timestamp;
/* end of part matching struct empobj */
natid trt_cna; /* proposer */
static int do_write(struct empfile *, void *, int, int);
static unsigned get_seqno(struct empfile *, int);
static void new_seqno(struct empfile *, void *);
+static void must_be_fresh(struct empfile *, void *);
static void do_blank(struct empfile *, void *, int, int);
static int ef_check(int);
+static unsigned ef_generation;
+
/*
* Open the file-backed table TYPE (EF_SECTOR, ...).
* HOW are flags to control operation. Naturally, immutable flags are
cachep = ep->cache + (id - ep->baseid) * ep->size;
}
memcpy(into, cachep, ep->size);
+ ef_mark_fresh(type, into);
if (ep->postread)
ep->postread(id, into);
if (ep->onresize && ep->onresize(type) < 0)
return 0;
}
- if (id >= ep->baseid && id < ep->baseid + ep->cids)
+ if (id >= ep->baseid && id < ep->baseid + ep->cids) {
cachep = ep->cache + (id - ep->baseid) * ep->size;
- else
+ if (cachep != from)
+ must_be_fresh(ep, from);
+ } else
cachep = NULL;
if (ep->prewrite)
ep->prewrite(id, cachep, from);
elt->seqno = old_seqno + 1;
}
+void
+ef_make_stale(void)
+{
+ ef_generation++;
+}
+
+void
+ef_mark_fresh(int type, void *buf)
+{
+ struct empfile *ep;
+
+ if (ef_check(type) < 0)
+ return;
+ ep = &empfile[type];
+ if (!(ep->flags & EFF_TYPED))
+ return;
+ ((struct emptypedstr *)buf)->generation = ef_generation;
+}
+
+static void
+must_be_fresh(struct empfile *ep, void *buf)
+{
+ struct emptypedstr *elt = buf;
+
+ if (!(ep->flags & EFF_TYPED))
+ return;
+ CANT_HAPPEN(elt->generation != ef_generation);
+}
+
/*
* Extend table TYPE by COUNT elements.
* Any pointers obtained from ef_ptr() become invalid.
elt = buf;
elt->seqno = get_seqno(ep, elt->uid);
}
+ ef_mark_fresh(type, buf);
}
/*
#include <unistd.h>
#include "empio.h"
#include "empthread.h"
+#include "file.h"
#include "ioqueue.h"
#include "misc.h"
#include "queue.h"
int cc;
int res;
+ if (waitforinput)
+ ef_make_stale();
+
/* Not a read IOP */
if ((iop->flags & IO_READ) == 0) {
errno = EBADF;
int n;
int remain;
+ if (waitforoutput)
+ ef_make_stale();
+
/* If there is no output waiting. */
if (!io_outputwaiting(iop))
return 0;
{
int len;
+ if (doWait)
+ ef_make_stale();
+
if ((iop->flags & IO_WRITE) == 0)
return -1;
ioq_append(iop->output, buf, nbytes);
{
int n;
+ ef_make_stale();
+
/*
* Mustn't block a player thread while update is pending, or else
* a malicous player could delay the update indefinitely
#include <signal.h>
#include <time.h>
#include "empthread.h"
+#include "file.h"
#include "misc.h"
/* Flags that were passed to empth_init() */
{
if (!flags)
flags = empth_flags;
+ ef_make_stale();
return lwpCreate(1, entry, size, flags, name, 0, 0, ud);
}
void
empth_exit(void)
{
+ ef_make_stale();
lwpExit();
}
void
empth_yield(void)
{
+ ef_make_stale();
lwpYield();
}
int
empth_select(int fd, int flags, struct timeval *timeout)
{
+ ef_make_stale();
return lwpSleepFd(fd, flags, timeout);
}
int
empth_sleep(time_t until)
{
+ ef_make_stale();
return lwpSleepUntil(until);
}
int sig, err;
time_t now;
+ ef_make_stale();
sigemptyset(&set);
sigaddset(&set, SIGHUP);
sigaddset(&set, SIGINT);
void
empth_rwlock_wrlock(empth_rwlock_t *rwlock)
{
+ ef_make_stale();
lwp_rwlock_wrlock(rwlock);
}
void
empth_rwlock_rdlock(empth_rwlock_t *rwlock)
{
+ ef_make_stale();
lwp_rwlock_rdlock(rwlock);
}
get_empobj(obj->ef_type, obj->uid, &old);
memcpy(&tobj, obj, sz);
old.gen.timestamp = tobj.gen.timestamp = 0;
- return memcmp(&tobj, &old, sz);
+ old.gen.generation = tobj.gen.generation = 0;
+ if (memcmp(&tobj, &old, sz))
+ return 1;
+ ef_mark_fresh(obj->ef_type, obj);
+ return 0;
}
int