I've been developing concurrent
systems for several years now, and I
have a pretty good grasp on the
subject despite my lack of formal
training (i.e. no degree).
Many of best programmers I know didn't finish the University.
As for me I studied Philosophy.
C/C++, C#, Java, etc.). In particular,
it can be near impossible to recreate
conditions that happen readily on one
system in your development
environment.
yes
How do you figure out what can be made concurrent vs. what has to be
sequential?
we usually start with a 1000 miles high metaphor to clarify our architecture to ourselves (firstly) and to others (secondly).
When we faced that problem, we always found a way to limiting the visibility of concurrent objects to non concurrent ones.
Lately I discovered Actors in scala and I saw that my old solutions were a kind of "miniactors", much less powerful than scala ones. So my suggestion is to start from there.
Another suggestion is to skip as many problems as possible: for example we use centralised cache (terracotta) instead of keeping maps in memory, using inner class callbacks instead of synchronised methods, sending messages instead of writing shared memory etc.
With scala it's all much easier anyway.
How do you reproduce error conditions and view what is happening
as the application executes?
No real answer here. We have some unit test for concurrency and we have a load test suite to stress the application as much as we can.
How do you visualize the interactions between the different
concurrent parts of the application?
Again no real answer: we design our Metaphor on the whiteboard and we try to make sure there are no conflicts on the architectural side.
For Arch here I mean the Neal Ford's definition: Sw Architecture is everything that will be very hard to change later.
programming leads me to believe you
need a different mindset than you do
with sequential programming.
Maybe but for me it's simply impossible to think in a parallel way, so better design our software in a way that doesn't require parallel thinking and with clear guardrails to avoid crashes between concurrency lanes.
Finally we found a solution :
- When you start dragging an object, the view sends a "drag" signal to it's controller. The controller gets the model object and puts a pointer to it in a shared "DragandDrop-board" (think of it as a clipboard)
- When you drop, the view sends a "drop" signal to it's controller. The controller gets the object from the drag and drop board, and updates the model accordingly.
If you use a kind of a smart pointer that's quite easy to make sure the pointer is still valid after the drop .
Best Answer
It varies slightly with the architecture, but the important points apply nearly universally:
Interrupt servicing causes the CPU state (including registers) to be saved to memory before running the ISR, and restored as the ISR exits.
If an interrupt service routine swaps the content of the memory location where those registers are saved, it can perform a context switch. Every thread has a memory region where its registers are saved when the thread isn't running.
The context switch is controlled by a thread scheduler which takes into account whether a thread is waiting for I/O, synchronization, what its priority is, signal delivery, etc. Often there's a suspend count which is factored in.
The debugger can increment the suspend count, which guarantees the thread isn't runnable. Then it can inspect (and change) the thread's saved copy of registers.