say there is a call to a subroutine Multiply. while the main function has called the subroutine and we are in the middle of the sub routine's execution an external interrupt occurs which also calls the same subroutine multiply. what will happen in that case?
When an interrupt occurs, the information about the running program is saved away and then the interrupt handler is started. This handler runs on a stack that is separate from the one that the interrupted program uses, so if the handler calls multiply it will have separate parameters, local variables, and return addresses from what the program had.
Related
It is possible to pass a VBA class (COM object) from one hosted VBA process to another (e.g. one instance of Excel.exe to another) using the Application.Run method. That means the second process (thread 2) will have access to code defined in the first process (thread 1).
It is therefore possible that the second thread would invoke a method on the object from thread 1 which runs using the first thread's interpreter, so thread 1's interpreter is being invoked from thread 1 and thread 2 simultaneously.
That's probably not surprising to anyone, but it was to me, since VBA is implemented as a single threaded language (it all runs in the host application's UI thread!) and doesn't give you syntax to write multithreaded code. Based on that I thought surely the VBA interpreter wouldn't be thread safe and would not allow execution from other threads. But apparently you can, and I've also passed VBA objects to python libraries in the past (which I imagine run on a separate thread with the python interpreter).
So how is it done, does VBA have a GIL like Python - meaning the interpreter can only ever be run by a single thread at a time, or is there something else going on? Is there any way to check?
To control what threads can access methods on a COM Object (thread affinity), COM uses apartments. An apartment is a place for objects having the same thread affinity. Apartments are specific to a single process.
VBA Objects have high thread affinity and they “live” in an STA (single threaded apartment). They will receive calls from a single thread which is always the same thread. In VBA there is one and only one thread in the STA. STA is designed to protect objects against concurrency. A hidden window is created when a thread enters an STA (CoInitializeEx is called). When a call to an object living in the STA is made, a window message is posted to the hidden window which then makes the thread in the apartment to execute the call. If two threads call methods on an object living in an STA, then the hidden window will receive two messages and only one will be handled at a time meaning that the second is blocked until the first call has completed. In short, objects living in an STA do not have concurrency.
A call from another process is not a direct call. Different apartments and threads. COM simulates a synchronous call instead. The call in the calling process is paused and then replayed in the process where the actual object lives. COM is designed to work with objects even from different computers. The simulation (or interception) involves a proxy and a stub and the COM transport.
For example, if a VBA thread (T1) in process 1 uses an object created in a VBA thread in process 2 (T2), then the object’s interface is exported from the apartment of T2 to the apartment of T1 (the interface is marshalled). When COM marshals the interface, it creates a stub living in the apartment of T2. The stub represents the calling side - T1. The marshalled information is transported and then used to create (unmarshall) the object’s interface (the proxy) in the apartment of T1. Communication is set between the proxy and the stub. So, T1 receives a proxy, not the true object (which lives in a totally different memory space). When T1 calls a method on the proxy, COM forwards the call to the real object via the stub, waits until the call is done and returns the result.
I have a static object that needs to initialize an imaging API. The allocated resources of this imaging API need to be released by the same thread.
So I'm starting a thread in my static object that initializes everything and then waits for a counter to reach zero. When this happens the thread cleans all up and finishes.
This is an unmanaged class inside a managed library, so I can't use System::Threading::Thread (needs a managed static member function) or std::thread (compiler error, not supported with /clr).
So I have to start my thread like:
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&Initialize, this, 0, 0);
All works fine, the init is done and the API functions work. But when I close the application I see that the usage counter of my static object reaches zero but the clean up function is never called by the thread, as if the thread was killed. Is there a way to make sure the thread will continue to exist and execute until its end?
After turning this around in all possible ways and adding events etc I guess this is not possible so I'll have to change the structure of my code and encapsulate the non managed class inside a managed class, and add the thread to the managed class.
I think you could proceed in one of two ways:
Wrap the resources in RAII-style classes, and refactor to have the objects' lifetimes be on the stack of your created thread, ensuring their destructors get called when the thread loop exits without having to call any additional cleanup. If there is no issue with the thread returning correctly when your counter reaches 0, this should be the simplest and cleanest way of addressing this.
I'm thinking you could intercept the WM_CLOSE message using window procedures, process necessary cleanup and then pass the message on, effectively "stalling" it until you are ready to close. Note that even though you are in a DLL you can still set up a window procedure and message pump system, you don't need a GUI to do that. I am however not 100% sure on whether you'll receive the WM_CLOSE message that concerns the application that "owns" your DLL, it's not something I've tried out yet.
You will have to implement some form of messaging through events within your thread's loop however, as the WindowProc will be called on a different thread, so you know when to call the cleanup procedure.
I also am not very familiar with CLR, so there might be a simpler way of interacting with those APIs than with raw C++ calls and handles.
I was going through some tutorial on SystemC and there was a mention that we cant put wait in SC_METHOD, it didn't explain why.
That is because SC_METHOD does not have its own thread of execution. Every time an event on an SC_METHOD sensitivity list is triggered, the SC_METHOD's code is (ideally) entirely executed. In other words, calling wait() in an SC_METHOD would freeze the simulation itself.
In contrast, an SC_THREAD has its own thread of execution and its activity is generally modeled inside a loop containing or not wait() statements, which pauses the execution of the thread. Whenever an event (of the sensitivity list) is triggered, the execution is resumed at the command that follows the previously issued wait().
Its a feature of the language. SC_METHOD is meant to executed to completion without being deferred or losing context, unlike SC_THREAD.
If I have a background thread doing some network stuff, and some of the background methods make 'performSelectorOnMainThread' calls, will/can these calls interrupt execution of the current code block (which is being executed on the main thread)?
No, they will and can not. The performSelector group of methods schedule actions on the run loop. Only after your current code block returns to the run loop, these actions will be performed. (Assuming with "the current code block" you mean your code running on the main thread)
If waitUntilDone is set to YES, then absolutely it will definitely interrupt execution of the code calling performSelectorOnMainThread. If it's set to NO then it will queue the selector to be performed on the main thread.
If the caller of performSelectorOnMainThread is not the main thread, then whether or not the selector gets run before your "current code block" finishes will depend entirely upon the state the CPU is in. There might be more than one CPU so you might have 2 of your threads scheduled at the same time, or just the OS might have decided to schedule the main thread instead of your current thread after some time.
So basically, yes, these calls can interrupt execution of the current code block, just in the same way as you should be familiar with from multi-threaded programming.
[By "current code block" I am assuming you mean the caller of performSelectorOnMainThread]
Update:
Ah, right, you mean "Can it interrupt the code which is currently being executed on the main thread?". The answer to that, is definitely not. It is scheduled on the main thread's run loop to run next time round the loop.
Is there a way for me to hook the exit of managed threads (i.e. run some code on a thread, just before it exits?)
I've developed a mechanism for hooking thread exit that works for some threads. Step 1: develop a 'hook' STA COM class that takes a callback function and calls it in its destructor. Step 2: create a ThreadStatic instance of this object on the thread I want to hook, and pass the object a managed delegate converted to an unmanaged function pointer. The delegate then gets called on thread exit (since the CLR calls IUnknown::Release on all STA COM RCWs as part of thread exit).
This mechanism works on, for example, worker threads that I create in code using the Thread class.
However, it doesn't seem to work for the application's main thread (be it a console or windows app). The 'hook' COM object seems to be deleted too late in the shutdown process and the attempt to call the delegate fails.
(The reason I want to implement this facility is so I can run some native COM code on the exiting thread that works with STA COM objects that were created on the thread, before it's 'too late' (i.e. before the thread has exited, and it's no longer possible to work with STA COM objects on that thread.))
Do you control thread creation? It's probably simplest to simply wrap the thread's code in a try...finally clause, and put your code in the finally.
Note that when the AppDomain shuts down, you can never be sure that your code will be called since the shutdown may be less than graceful.
When you say "Destructor" I presume you mean a C++/CLI destructor - i.e. the .Dispose() method?
If you need to support hooking before the process exits, you could try the AppDomain.CurrentDomain.ProcessExit event - which doesn't seem to fire on an unhandled exception, or AppDomain.CurrentDomain.UnhandledException which seems to fire only on an unhandled exception.
None of this looks particularly robust, mind you...