If I get it right, your issue is that the logged function calls might be in the wrong order. Couldn't you add a timestamp to the call info you are logging? erlang:now() or os:timestamp/0 (faster) return a timestamp up to microseconds, then the only action left to do would be ordering your logs before using them.<div>

<br></div><div>  <br><div class="gmail_quote">2012/5/18 Richard Evans <span dir="ltr"><<a href="mailto:richardprideauxevans@gmail.com" target="_blank">richardprideauxevans@gmail.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

I have a multiplayer simulation game running in erlang, involving<br>
multiple characters making decisions etc. Each game instance uses a<br>
few (currently, 4) erlang processes running concurrently,<br>
communicating with an AI simulator written in C.<br>
<br>
Everything is working well and I am enjoying using erlang.<br>
<br>
But there is one thing I am finding tricky.<br>
<br>
For QA purposes, I want to be able to record the exact sequence of<br>
function-calls, so I can play the game back exactly,<br>
deterministically.<br>
<br>
My current approach is this: I have a global ets table storing a list<br>
of function-calls. Then, whenever I was calling a function I want to<br>
record - instead of calling the function directly - I call a procedure<br>
which adds the function to the list of function-calls, and then calls<br>
it:<br>
<br>
call_and_store(Fun, Args) -><br>
    add_to_script(Fun, Args);<br>
    apply(lobby, Fun, Args).<br>
<br>
add_to_script(Fun, Args) -><br>
    Info = ets:info(script),<br>
    {size, Size} = lists:keyfind(size, 1, Info),<br>
    io:format("Inserting {~p,~p,~p}~n", [Size,Fun,Args]),<br>
    ets:insert(script, {Size, Fun, Args}).<br>
<br>
This approach does not seem to work well because of erlang's<br>
pre-emptive scheduling. If two concurrent processes both invoke<br>
call_and_store, then it is possible (and seems to actually be<br>
happening) that erlang's pre-emptive scheduler may stop processing one<br>
instance of call_and_store between execution of add_to_script and<br>
execution of apply. If this happens, the order of execution and the<br>
order of recorded function-calls will diverge, we don't have an<br>
accurate recording of the set of function-calls, and we won't be able<br>
to deterministically playback.<br>
<br>
So my question is: is there a way to prevent the scheduler from<br>
yielding during a block of code? Some way to insist the block is<br>
called as one unit, like this:<br>
<br>
call_and_store(Fun, Args) -><br>
        !!!prevent_yielding,<br>
    add_to_script(Fun, Args);<br>
    apply(lobby, Fun, Args),<br>
        !!!allow_yielding.<br>
<br>
My guess is: no. This does not seem very erlangy.<br>
<br>
Alternatively, is there a different approach which can produce the<br>
desired list of function-calls? My current approach seems to go<br>
against the erlang grain, involving writing to a shared global table.<br>
Is there a better, more erlangy, way of doing this?<br>
<br>
<br>
<br>
thanks,<br>
~Richard<br>
_______________________________________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>quique<br>
</div>