Delphi COM EXE and Threading - delphi

Just want to confirm with the COM/DCOM experts out there...
I have a Delphi COM EXE that is running on a server (threading is Single Apartment) and another copy of that same EXE starts up on the same server
(a server that has say 2 processors with dual core so the task manager shows 4 separate graphs) will they take turns waiting for each other or will they run on separate cores?
I found a post somewhere that said
"If two clients need to use the same object, they have to take turns. With this threading model the instance data is safe, global data must be protected using critical sections or some other form of serialization. Of course, the thread's local variables are reliable across multiple calls."

You've missed the "different objects from the same server" part from the same paragraph. Since you have "Single instancing" you get a separate server for each COM object instance, so calls to those instances can be processed in parallel and COM will not have to provide any mutual exclusion.
Think of it this way. Threading models are there to provide thread safety - synchronized access to data shared between threads of the same process. You have one object per process, so there's no two threads will try to access the same object unless of course you try to pass a pointer to one object into another object method call.

Related

Reusing ADO objects across multiple CoInitializeEx/CoUninitialize cycles

Currently I'm writing a REST server using a framework of a well-known Delphi component developing company. This framework provides the ability to simply write a class whose methods are named like the REST API endpoints.
The REST server fetches data from a MS SQL Server, I use dbGo components for that (what is ADO behind the scenes). There is also available an ORM framework of the same company mentioned above, but I don't want to use it for reasons.
Some of the REST calls work on a bunch of databases at once. In order to increase performance I implemented a connection pool, holding objects that encapsulate TADOConnection instances. When a REST call gets executed, it queries the connection pool if there is already an existing connection for the database(s) used by the call. If not, the required ADO database connection objects are created and handed over to the connection pool in order to be used again for subsequent connections to the same database(s).
I've noticed that the class with the methods named like the REST API endpoints gets instantiated by the framework for every single REST call. When the call is done the instance is freed. Because object instantiation and method calls are executed in the context of the REST server's thread (not in the main thread), I need to call CoInitializeEx in the constructor of the class and CoUninitialize in its destructor to be able to use dbGo's TADOxxx classes. Please note: There is no way to hook the server's thread creation or termination (I know, these would be the correct places to call CoInitializeEx and CoUninitialize, respectively).
The above concluded means that I store TADOConnection objects (encapsulating an ADO ActiveX class) during a certain cycle of CoInitializeEx/CoUninitialize and reuse them in a later cycle, i.e. COM has been uninitialized and gets initialized again between two usages of the same TADOConnection object.
Now my question is: Could that lead to any problems in a production scenario (for example crashes, memory or handle leaks or similar unwanted things) if multiple clients access the REST server? I'm quite unexperienced in dealing with COM and ActiveX respectively, so I need some help.

What's the appropriate place to call CoInitialize/CoUninitialize across DLL's?

I'm implementing a DLL containing a shared ADO Connection by using the ConnectionObject property of TADOConnection and passing it across DLL boundaries into other instances of TADOConnection. I need to make sure COM is initialized, so I need to call CoInitialize / CoUninitialize. Currently it's in the context of a VCL main thread, but could be elsewhere in another thread, which of course requires its own instance of COM. I'm not currently implementing multi-threading.
Where is the appropriate place to call these; inside the DLL (during loading/unloading), outside the DLL (calling process), or both? Considering it's only one thread, shouldn't it be only one time outside the DLL in the original process?
I'm assuming the original calling thread should be solely responsible for this, since COM runs in the context of a thread. Of course calling them on both sides shouldn't hurt any, however it would also create multiple COM instances.
Long story short... Is it "safe to be safe" in this case? Or is it important to only keep one COM instance?
You should not be doing this in the DLL. Make it part of the contract between the DLL and the host that the host is responsible for initializing COM.
The DLL cannot be expected to initialize COM because the host may already have done so. And use a different threading model. Once COM has been initialized then future attempts to initialize will fail if they attempt to change the threading mode.
So, don't initialize COM in your DLL. Require the host to do so.

LoadLibrary, a way to instantiate a class from external dll?

I have written a dll in d-7. It functions correctly. It gets loaded when an application starts and unloaded when it exists.
Now, that dll must also work on the server side of that application, being loaded from the COM+ surrogate (dllhost.exe) as the server is based on com+ technology.
The problem is that one process may have only one handle for loaded library. I cannot have separate handles on each LoadLibrary call.
In com+, one dllhost.exe can serve many clients, which means that if I load an external library it gives the same instance for each clients calls.
So:
1) Is it possible to somehow workaround this problem?
2) Or Is it possible to directly create instance of the class which resides in this dll for each client call?
3) Or How to make a dll thread-safe by instantiating an internal class for each call.
Thanks for suggestions in advance!
Since a DLL uses the local memory of the thread/process that calls it, I'm not sure you're really going to have a "problem". You do not want to have the DLL maintain some global information because that will only lead to threading nightmares.
If you have a function within the DLL return an object reference (effectively a handle) you can also guarantee that each instance gets its own information to play with and not stomp on other processes or threads. Define the function to return your TWhatever object, have the DLL create it ( TWhatever.Create() ) and return it to the calling process. It would then be up to the calling process to free the object. If you need COM+ compatibility then it should be possible to use an interface reference (IWhatever) and return that from your function.
If each thread deals with its own object instance (or interface reference) then you could have the DLL serve as many threads and processes as you wish.
Your question is confusing to me so I'm not sure if I answered it correctly. :p

Keeping separate instances of a DLL's static memory

I'm currently attempting to integrate a DLL (FooEmulation) into an existing project.
The DLL assumes that it will only be used to emulate one Foo at a time, and uses a lot of static globals as a result.
However, I want to be able to manage thousands of Foo instances at once.
I have the source to the original DLL, so I could convert all of the static globals into parameters that would be passed in (whether directly or via a handle), but the DLL is being maintained separately and I'd like to avoid forking/merging if at all possible.
One technique I found was to load multiple dynamically generated copies of the DLL, but that is too resource-heavy for the scale I need.
I also can't afford to create a process or thread for each Foo.
Is it possible to keep multiple copies of the DLL's static memory and restore it per use of the DLL?
How do I locate it? Am I even allowed to touch it?
When you load the DLL multiple times into the same process all the static data is shared, period. You'll have to redesign the library so that all those objects can be created dynamically as you need them during the runtime.
I am assuming you're on windows since there's nothing telling me otherwise..
Take a look here, which is the documentation for DLLMain in Windows.
DLLMain has a parameter that tells you if
A process is attaching (loading your DLL)
A process is detaching (unloading your DLL)
A thread is attaching (loading the per thread parts of your DLL)
A thread is detaching (unloading the per thread parts of your DLL)
If you catch the process or thread events and allocate (attach) / free (detach) a new instance of your statics, I think this would solve your problem. It's a little hacky, but it would work...
You have to be careful what you do in DLLMain as well. Look in the docs for the warnings about blocking in any way in DLLMain.

Session Management in TWebModule

I am using a TWebModule with Apache. If I understand correctly Apache will spawn another instance of my TWebModule object if all previous created objects are busy processing requests. Is this correct?
I have created my own SessionObject and have created a TStringList to store them. The StringList is created in the initialization section at the bottom of my source code file holding the TWebModule object. I am finding initialization can be called multiple times (presumably when Apache has to spawn another process).
Is there a way I could have a global "Sessions" TStringlist to hold all of my session objects? Or is the "Safe", proper method to store session information in a database and retrieve it based on a cookie for each request?
The reason I want this is to cut down on database access and instead hold session information in memory.
Thanks.
As Stijn suggested, using a separate storage to hold the session data really is the best way to go. Even better is to try to write your application so that the web browser contains the state inherently in the design. This will greatly increase the ability to scale your application into the thousands or tens of thousands of concurrent users with much less hardware.
Intraweb is a great option, but suffers from the scale issue in the sense that more concurrent users, even IDLE users, require more hardware to support. It is far better to design from the onset a method of your server running as internally stateless as possible. Of course if you have a fixed number of users and don't expect any growth, then this is less of an issue.
That's odd. If initialization sections get called more than once, it might be because the DLL is loaded in separate process spaces. One option I can think up is to check if the "Sessions" object already exists when you create it on initialization. If the DLL really is loaded in separate processes, this will not help, and then I suggest writing a central Session storage process and use inter-process-communication from within your TWebModule (there are a few methods: messages, named pipes, COM...)
Intraweb in application mode really handles session management and database access very smoothly, and scales well. I've commented on it previously. While this doesn't directly answer the question you asked, when I faced the same issues Intraweb solved them for me.

Resources