«« Showdelayers VS.NET Background Compilation Issues Explained »»
blog header image
MVC Part II: Attack of the Mutators

Here's an updated architecture sketch of AudioMan:


(yep, hand drawn again)

I've been thinking a lot about multithreading AudioMan, and here's what I've come up with so far. Note the diagram is different from the old diagram -- it hasn't even been two weeks yet. That's why I don't put a lot of effort into making them look nice: they change too much. If you are lost reading this post, you might want to try reading the old post first -- it may help.

The major multithreaded situation I have right now is when someone wants to browse the collection while a long Include Directory operation is going on the background. My solution to this problem is to temporarily make the repository (dB in diagram, it can be thought of as a database) read-only while I'm updating the UI and then unlock it when I'm done.

Using the numbers in the diagram above, here's a typical scenario:

A1. Include Directory X
A2. Crawling directory X and its subdirectories
A3. Found a track, add it to the repository
A4. Mutator notifies the controller a track was added
A5. Controller notifies the models a track was added
A6. Models notify the UI a track was added; track appears in the view
(return to A2 and repeat an arbitrary number of times...)
B1. User wants a different view; UI asks the controller
B2. Controller locks the repository, making it read only; asks for updated tracks for models for the new view
(now that the repository is locked, the Include Directory operation blocks on A3 and stops)
B3. Controller checks the tracks to ensure they are up to date with their respective files and formatting is correct
B4. Controller makes new models from the tracks
B5. Controller passes the models to the UI; UI loads the new models asynchronously (with asyncExec())
B6. Controller unlocks the repository
(A3 is unblocked and Include Directory resumes)
B7. Controller gives the mutators tracks to update
etc...

A lot of this architecture already exists in AudioMan, I just haven't had a chance to talk about it yet. There are two potential problems that I don't have enough information about which could be issues:

1. When the Include Directory resumes and the controller gives its list of files to update to the mutators, will there be a "collision" of sorts since both threads are using the mutators? I don't think so. The mutators are singletons but they do not contain any instance specific information. They do not have state. So the threads can context switch using the same mutator singleton without any problems as far as I know ... but I am still unsure. I will have to look into this more.

2. After the controller unlocks the repository in B6, the mutators will resume and could notify the models of changes before the models are properly connected to the view and can notify it. This by itself seems to be OK since the models hold onto these updates, so when the UI is ready to load the models (with setInput()) they will be up to date.

However, there could be a short period of time during the connection process where the models have already been connected to the UI but aren't notifying it of changes yet. If that is the case, the view will miss updates. A solution could be to attach the view's model listener first and then load the model into the UI. Of course, this may give the view false updates just before the the new model is connected because it is listening prematurely. However, the view will be cleared when the new model is connected to it anyway and the model has those updates as well. So I believe everything will appear correct in the end.

Any comments? I realise this may be a lot to digest. If I didn't explain anything well enough please let me know.

Posted at March 08, 2004 at 04:12 AM EST
Last updated March 08, 2004 at 04:12 AM EST
Comments

(I only read - but didn't fully digest yet)

I wonder if instead of 'locking' the data, you temporarily disable the connection between the model and view. So, you have acess to the 'stuff' at that particular time without the worry of locking other processes. And maybe if you do permanent damage to the content, you could queue up the events to the mutator.

I am not sure if I like the idea of stopping the import just because i continue to play with the UI.

» Posted by: aforward at March 8, 2004 11:40 PM

The switch only takes a second, so the include will not be stopped long. I doubt that it will even be noticeable.

Queues don't really solve the problem, they just make the components more complex. Right now I just use "event listener" interfaces, which are just method calls. I don't think a queue would help much ... if the stop was longer a queue might be a good idea.

» Posted by: Ryan at March 9, 2004 10:09 AM

I am currently trying to understand the locking aspect of the proposed diagram. When the user request a new view, what is affected by this? I don't understand why the whole repository has to be locked.

» Posted by: at March 10, 2004 05:00 PM

It's because there's another thread including tracks at the same time as the user wants to change the view.

When a track is added with a mutator, the mutator notifies the controller, which notifies the models, which notifies the view. If *at the same time* the controller is changing the model, then problems can occur.

So, if the include thread can't write to the repository because it is "locked" and stops there, then I don't have to worry about it notifying the controller in the middle of changing the model.

If I put in a queue and just let those notifications stack up, that's not that great. I don't know if the notifications in the queue are for the old model or the new one. Which ones do I throw out? If I throw them all out, why bother having a queue? :)

So it's best that while the view is being changed the include thread is temporarily stopped for a short (and I believe hardly noticable to the user) amount of time.

» Posted by: Ryan at March 10, 2004 05:21 PM

Now I understand better. You are only locking during the view update. Does anyone forsee a view update taking a long time?

» Posted by: James at March 10, 2004 06:47 PM

No I don't think so. You can check it out in the current version, the swap is pretty quick. The user won't notice that the background thread is temporarily paused anyway. But if you switch the view a bunch of times during the include, it might take a few seconds longer than if you hadn't.

» Posted by: Ryan at March 10, 2004 06:58 PM
Google
 
Search scope: Web ryanlowe.ca