While this seems logical from a human perspective, it is illogical from a programming perspective since arrays start at 0. Most things of this nature also start at 0.

Agreed, I've been used to zero-based-index arrays for years. But the I/O connectors on the FusionBrain are labeled starting at 1. The 'right' fix might be to silkscreen the labels starting from 0 on the board, but that's out of my control. So to curb the gut-twisting frustration I look for another solution...

Agreed, I've been used to zero-based-index arrays for years. But the I/O connectors on the FusionBrain are labeled starting at 1. The 'right' fix might be to silkscreen the labels starting from 0 on the board, but that's out of my control. So to curb the gut-twisting frustration I look for another solution...

j

I think the fusion bran software that comes with it has the UI labeled as starting at 1, and hides the 0 based index below layers of abstraction. fbd does not, that's up to the end-application developer.

"stop with the REINSTALLS, what do you think we got some lame-o installer!!!" - mitchjs
RevFEMy Shop

Good idea. If you can prepare a patch, i'll apply it to the mainline fbd.

Will do, probably this weekend.

Originally Posted by tripzero

What about a byte array or an array of (int/double)? dbus supports those types and it's a bit more specific than a string to the app requesting it.

Byte array sounds like a reasonable answer. (int/double would work, but since they're boolean values that feels like a waste) I've got it working right now returning a 16-digit binary rep of the state as a string. I might end up with both.

Originally Posted by tripzero

PaulF: Can you describe the multi-threading problem in more detail. i can't think of why it wouldn't "just work" off the top of my head...

I might be able to clarify: Say we fire two "setSingleOutput()" methods at essentially the same time, and the FB initially has NO outputs on. First one reads the current output states (all off), sets the selected output flag to on, and writes the altered array back out to the FB. Meanwhile, the second invocation reads the current state (possibly still all off, depends on timing etc) sets the second selected output flag to on, and writes THAT array back out to the FB, so the net change is ONLY the second one.

If both method invocations initialize by reading the 'all off' state, then whichever one finishes last will effectively turn the first one back off.

I might be able to clarify: Say we fire two "setSingleOutput()" methods at essentially the same time, and the FB initially has NO outputs on. First one reads the current output states (all off), sets the selected output flag to on, and writes the altered array back out to the FB. Meanwhile, the second invocation reads the current state (possibly still all off, depends on timing etc) sets the second selected output flag to on, and writes THAT array back out to the FB, so the net change is ONLY the second one.

If both method invocations initialize by reading the 'all off' state, then whichever one finishes last will effectively turn the first one back off.

j

The actual fusion brain class library is NOT thread safe. Calling two instances of setSingleOutput from two different threads (as you discovered) can cause undefined results.

A simple mutex would fix that

"stop with the REINSTALLS, what do you think we got some lame-o installer!!!" - mitchjs
RevFEMy Shop

PaulF: Can you describe the multi-threading problem in more detail. i can't think of why it wouldn't "just work" off the top of my head...

In my application, I have quite a bit of fusion brain i/o going on. The application is built in python and consists of its own logic for turning certain things on and off depending on different sensors, and it also has two web servers built in. One is for communication across the web and one is for communication from the in-car computer. I used the HTTP protocol rather than sockets because it requires much less thinking as all the necessary classes are built in to both python and c# so development was nearly instant.

With all these things built in, at a given time, over 3 different things can be controlling the FB. To remedy this, I've multi-threaded the crap out of the python application so that nothing will block anything else ever.

All that explanation was just so you don't say "why the heck are you doing this?" haha

THE REAL PROBLEM:

So in my application, I have a method called turnOnOutput(x) with x being the output's number.
The method, turnOnOutput, then launches a new thread and that thread hits FBD on the DBUS. This allows turnOnOutput to return instantly so that the http request won't time out, or even just take annoyingly long.

However since this is receiving communication from all sides, the DBUS gets quite busy. So I just went through the application and if a few conditions are met at the same time which is quite feasible when the car is first being turned on, turnOnOutput will get called 10 times one right after the other. This sets off 10 threads that attack the FBD on the dbus 10 times. All while sensors are continuing to be read ever few milliseconds.

Now from what I can gather from what newkirk has said it seems like FBD is requesting the ports that are on from the fusion brain, receiving that request, and then actually telling it whether to turn the port on/off. So now lets say things get a bit out of order...

Now, newkirk has explained the race condition fairly well in post

Originally Posted by newkirk

The problem you're encountering is caused because setSingleOutput() actually reads the state of all 16 outputs into an array, alters the state for the single selected output, then sets all 16 outputs to what is in the array. If you fire off multiple setSingleOutput()s close together, then you have a problem arise where the last one reads current state (which doesn't always include the other changes still running) and alters only its own selected output. I've not yet seen a simple solution that would avoid the race condition you're encountering, given multiple near-simultaneous set commands. (apart from using my new setMaskedOutput and ensuring that you do NOT have multiple near-simultaneous commands)

Now I have a question...
Why the heck does it need to read in 16 output statuses to set one output?
Why does it even need to read ONE output status to set an output?
Why can't efficiency and reliability just be saved by actually just going ahead setting the output?

Now I have a question...
Why the heck does it need to read in 16 output statuses to set one output?
Why does it even need to read ONE output status to set an output?
Why can't efficiency and reliability just be saved by actually just going ahead setting the output?

It has to read the entire state before setting anything, that's how the fusion brain operates. Take that issue up with 2k1toaster. I could have set outputs blindly (Keeping a local record of the output states, and setting that every time), and that's actually what I did initially, but that lead to reliability issues with setting outputs so it's really not an optimum way to do it.

"stop with the REINSTALLS, what do you think we got some lame-o installer!!!" - mitchjs
RevFEMy Shop

It has to read the entire state before setting anything, that's how the fusion brain operates. Take that issue up with 2k1toaster.

So is this happening on the fusion brains microcontroller, or in FBD?

Originally Posted by malcom2073

I could have set outputs blindly (Keeping a local record of the output states, and setting that every time), and that's actually what I did initially, but that lead to reliability issues with setting outputs so it's really not an optimum way to do it.

This is how the fusion brain operates, so this is how FBD talks to it. Full read, then full write. rinse and repeat.

Originally Posted by PaulF

What caused it to become unreliable?

I misunderstood how the fusion brain operates, so it has to write-read-write-read to get any output to set correctly. I intended to fix it uh... a year ago? I just never did. I never tested the reliability using the proper method for setting outputs, but regardless it's safer to read everything so you don't accidentally miss a state, and it takes on the order of a couple hundred microseconds at most... so if you're THAT concerned about performance... yeah.

I'll get around to fixing the reliability issue soon, and that might fix the other issue

"stop with the REINSTALLS, what do you think we got some lame-o installer!!!" - mitchjs
RevFEMy Shop

Good idea. If you can prepare a patch, i'll apply it to the mainline fbd.

Take a look at the attached diff. It does three things, applied to the svn sourcecode: It provides GetSingleOutputState(int ionum), GetAllOutputState(), and SetMaskedOutput(int low, int high, int lowmask, int highmask). GetSingleOutputState() returns an int, GetAllOutputState() returns a QByteArray.

I just scanned this discussion as I have been away for a few days. If you have multiple processes/threads trying to updated the FB, you'd be better off queuing the updates and having a single thread that waits for updates on the queue and services them (although I guess you can use dbus as the queue??). If there are multiple updates on the queue, have it do some kind of merge or just take the most recent. Either way, with only one thread writing, the results should be consistent.

Sadly I have not had the time to play with my FB beyond the initial brief dabbling (nor any carputer stuff in general).