View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000477 | LDMud 3.3 | Efuns | public | 2006-06-28 10:59 | 2009-01-17 10:12 |
Reporter | fufu | Assigned To | fufu | ||
Priority | normal | Severity | feature | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Fixed in Version | 3.3.719 | ||||
Summary | 0000477: add get_eval_number() efun | ||||
Description | int get_eval_number() Return the current evaluation number. It's incremented for each top-level call. [...] The intended purpose of this function is to find out if something has already been done for the current command, heart_beat, call_out or whatever. Control flow in mudlibs is often complicated and adding the necessary infrastructure to a mudlib to answer this question is error-prone and tedious. In the driver it's just a few lines of code. | ||||
Additional Information | patch attached. The documentation assumes that the patch in 0000476 has been applied. | ||||
Tags | No tags attached. | ||||
Attached Files | get_eval_number.patch (2,838 bytes)
Index: doc/efun/get_eval_number =================================================================== --- doc/efun/get_eval_number (revision 0) +++ doc/efun/get_eval_number (revision 0) @@ -0,0 +1,17 @@ +SYNOPSIS + int get_eval_number() + +DESCRIPTION + Return the current evaluation number. It's incremented for each + top-level call. These are: commands, calls to heart_beat, reset, + or clean_up, and calls generated by call_out or input_to, master + applies triggered by external events, send_erq callbacks and the + calls to logon on player login. + + The counter is a 32 bits counter so it can overflow occasionally. + +HISTORY + Since ldmud 3.3.372 + +SEE ALSO + get_eval_cost() Index: src/efuns.c =================================================================== --- src/efuns.c (revision 2306) +++ src/efuns.c (working copy) @@ -8702,5 +8702,23 @@ return sp; } /* f_utime() */ +/*-------------------------------------------------------------------------*/ +svalue_t * +f_get_eval_number (svalue_t *sp) + +/* EFUN get_eval_number() + * + * Return the current evaluation number. It's incremented for each + * top-level call. These are: commands, calls to heart_beat, reset, + * or clean_up, and calls generated by call_out or input_to. + * + * The counter is a 32 bits counter so it will overflow occasionally. + */ + +{ + push_number(sp, eval_number); + return sp; +} /* f_get_eval_number */ + /***************************************************************************/ Index: src/func_spec =================================================================== --- src/func_spec (revision 2306) +++ src/func_spec (working copy) @@ -772,6 +772,7 @@ int set_is_wizard(object, int default: F_CONST1); #endif +int get_eval_number(); /* Obsolete and deprecated functions */ Index: src/interpret.c =================================================================== --- src/interpret.c (revision 2306) +++ src/interpret.c (working copy) @@ -697,7 +697,8 @@ #endif - unsigned long total_evalcost; +unsigned long eval_number; /* evaluation number. 32 bits - will overflow */ +unsigned long total_evalcost; static struct timeval eval_begin; /* Current total evalcost counter, and start of the evaluation. */ @@ -772,6 +773,7 @@ */ { + eval_number++; total_evalcost = 0; if (gettimeofday(&eval_begin, NULL)) { Index: src/interpret.h =================================================================== --- src/interpret.h (revision 2306) +++ src/interpret.h (working copy) @@ -116,6 +116,7 @@ extern p_int apply_cache_miss; #endif +extern unsigned long eval_number; extern unsigned long total_evalcost; extern unsigned long last_total_evalcost; extern struct timeval last_eval_duration; | ||||
|
Should be nonintrusive enough for 3.3, I believe. Is it considered useful by anybody else? |
|
I didn't have any need for such a number yet, but I don't object. |
|
Same for me, as yet I don't have a real need, but I can imagine to use it at some point in the future. BTW: We have to keep in mind the overflow of the counter (see other statistics overflow bugs). |
|
Can this go into 3.3.719? (I need it for 0000535.) |
|
The counter in the current patch is an unsigned long. The comments and documentation speak about a 32bit integer. I think we should be more precise in the code and use uint32(_t) or change the documentation. Or maybe even better use the to-be-created statistic counter type, see 0000521. The number is stored in an svalue so the LPC side sees negative numbers (probably no problem). But depending on the exact type we use it may lead to a host-system dependent behaviour in LPC. |
|
As this counter also (or primarily) goes to LPC it should be of the same type as the LPC int (but maybe only using the positive range). I don't see a problem with overflows. They will happen, but this number is used to distinguish between threads in one cycle, so that it is improbable to get the same number for different threads. To distinguish over a longer period you should remember the time() too. (To make that clear we could reset the eval number at each cycle?) |
|
Actually, the idea of resetting it in each cycle occurred to me as well because then I (wizard) don't have to bother about checking for the overflow (when the number gets actually smaller). But I was not sure, if the application may need it to increase over a longer period than a cycle. Concerning using p_int: yes, you are probably right. |
|
My original intended use case was to detect whether a function is called twice in the same evaluation. Having false positives with a /very/ low probability would be acceptable. Resetting the counter on each cycle would increase that probability dramatically, so I'd like to avoid it. I also intended the counters to be compared for equality only. Ordering events (which would make < and <= useful) wasn't an application I had in mind originally. But timestamps can be implemented fairly easily even in the presence of overflows with an sefun: int last; /* last value from get_eval_number() */ int overflows; /* number of overflows seen by timestamp */ /* assumption: get_eval_timestamp() gets called at least once per __INT_MAX__ top level evaluations */ mixed get_eval_timestamp() { int stamp = get_eval_number(); if (stamp < last) overflows++; last = stamp; return ({ overflows, stamp }); } or, if you want to include the current time: int then; /* last seen time() */ int last; /* last seen eval number */ /* assumption: fewer than __INT_MAX__ top level evaluations per backend cycle */ mixed get_eval_timestamp() { int stamp = get_eval_number() & __INT_MAX__; int now = time(); if (now != then) { then = now; last = stamp; } stamp = (stamp - last) & __INT_MAX__; return ({ now, stamp }); } As for the type, yes, p_int seems to be the right one. |
|
Agreed. |
|
I am just a bit confused. Isn't impossible that two function calls are in the same top-level evaluation if it is not the same backend cycle? Or better: what do I miss? ;-) |
|
Fuchur wants to compare the eval_number only (without regard to time()), and without time() you don't know wether you are in the same backend cycle. |
|
Ok, right. I had in my mind a check like if (debug_info(DINFO_DATA,DID_STATUS,DID_ST_HBEAT_CALLS_TOTAL) && last_eval_no != get_eval_number()) |
|
Done in svn rev 2501. |
|
Zesstra pointed out that in light of 0000596, querying the counter should be done with debug_info instead of a new efun. I've changed this in svn rev 2505. The new interface is debug_info(DINFO_EVAL_NUMBER) |
Date Modified | Username | Field | Change |
---|---|---|---|
2006-06-28 10:59 | fufu | New Issue | |
2006-06-28 10:59 | fufu | File Added: get_eval_number.patch | |
2008-07-02 02:30 | fufu | Status | new => assigned |
2008-07-02 02:30 | fufu | Assigned To | => fufu |
2008-07-02 02:31 | fufu | Note Added: 0000650 | |
2008-07-02 02:33 | fufu | Relationship added | parent of 0000476 |
2008-07-02 02:50 | Gnomi | Note Added: 0000652 | |
2008-07-02 02:57 | zesstra | Note Added: 0000653 | |
2008-07-11 03:52 | Gnomi | Relationship added | related to 0000535 |
2009-01-13 07:06 | Gnomi | Note Added: 0000877 | |
2009-01-13 07:32 | zesstra | Note Added: 0000878 | |
2009-01-13 13:32 | Gnomi | Note Added: 0000879 | |
2009-01-13 14:26 | zesstra | Note Added: 0000881 | |
2009-01-13 15:40 | fufu | Note Added: 0000882 | |
2009-01-13 15:45 | Gnomi | Note Added: 0000883 | |
2009-01-13 15:53 | zesstra | Note Added: 0000884 | |
2009-01-13 15:56 | Gnomi | Note Added: 0000885 | |
2009-01-13 16:08 | zesstra | Note Added: 0000886 | |
2009-01-17 07:40 | fufu | Note Added: 0000915 | |
2009-01-17 07:40 | fufu | Status | assigned => resolved |
2009-01-17 07:40 | fufu | Fixed in Version | => 3.3.719 |
2009-01-17 07:40 | fufu | Resolution | open => fixed |
2009-01-17 10:12 | fufu | Note Added: 0000918 |