Question

I am writing a small agent-based interaction simulation in a discrete simulator and am beginning to write some code that looks like the following. I have not some event-driven programming before but did not really observe this situation. I am wondering if the following piece of code will lead to a race condition while updating the value of msgRcvd.

// Following is the event-loop per-se
Controller {
    if (...) {
       SendMessage(currentTime() + 5, i,j)
       SendMessage(currentTime() + 5, i,k)
    }
    print currentTime(), msgsRcvd
    Schedule(currentTime()+1, Controller)
}

// The following function is called when an 
// agent receives a message
Receive(Agent agent) {
    if (...) {
       msgsRcvd++ // <-- this is a global variable
    }
}

My understanding is that at currentTime() + 5 both the agents receive the message at the same time because both the events are happening at the same logical time so I should see the number of messages to be 2? Or will I see some strange race condition happening and the value is dependent on the scheduler (i.e. it could end up printing 1 or 2)? Any suggestions?

Was it helpful?

Solution

The answer depends on the implementation of your event transport and is not language agnostic in that sense.

In all systems I have worked with, each message would be placed separately into an event queue and the receiving agent would take events off of that queue in order. Assuming you have one thread generating messages and one event taking messages off of the queue, I don't see an opportunity for a race condition.

If your event queue has some intelligence that attempts to consolidate events based on the timestamp, you would only see one event in the receiving agent. I'm not aware of a common system that does that (though some UI systems may for example consolidate two rapid mouse clicks to a double click... but that's specific behavior of a specific event system and not language/platform agnostic).

OTHER TIPS

No, even though the agent code is highly suspect and looks dangerous, I don't see that in this case it produces a race condition: msgsRcvd should always end up with the correct total. Even if the scheduler interrupts agent1 just before the increment, it seems to me that control will always come back to let that increment complete. If the controller gets control, then it might be that it will report the inaccurate contents of MsgsRcvd, but so what? MsgsRcvd quickly gets back in phase.

It sure is a scary-looking piece of code, though. When I'm looking at this kind of code, I always want to move the increment of MsgsRcvd up into the controller, exposing a function there that will do the increment. But that would only make me feel better in this case; it wouldn't change the logic and it wouldn't solve the "problem" (if it is one) of MsgsRcvd being temporarily inaccurate once in a while.

Originally was going to mention that there is no language/platform agnostic way to answer this question, but Eric J. has that covered.

In C++ that code as written will not be safe unless your platform guarantees that the callbacks will be serialized. The reason is the increment operator is not atomic and if two threads are concurrently trying to update the value, any number of things could happen depending on the order of the fetch, add, and store.

If this platform was truly designed with concurrency in mind, then there should be an "interlocked/atomic" api that provides the feature you need.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top