5

Few months back, I had come across this interesting scenario asked by a guy (on orkut). Though, I've come up with a "non-portable" solution to this problem (have tested it with small code), but still would like to know what you guys have to say and suggest.

Suppose, I created a DLL, exporting some functionalities, written in C++, for single threaded client. This DLL declares lots of global variables, some maybe const variables (read-only) and others are modifiable.

Anyway, later things changed and now I want the same DLL to work with multi-threaded application (without modifying the DLL); that means, several threads access the functions and global variables from the DLL, and modify them.. and so on. All these may cause global variables to hold inconsistent values.

So the question is,

Can we do something in the client code to prevent multi-access of the DLL, and at the same time, ensuring that each thread runs in it's own context (meaning, when it gets access to the DLL, the DLL's global values are same as it was before)?

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • If you are allowed at least to rebuild the dll you could add __declspec(threadlocal) to all your global definions. I strongly suspect that will fail on any static scoped class objects with constructors or destructors. – Chris Becke Nov 30 '10 at 12:30
  • Chris... no, we cannot add __declspec(threadlocal) to the globals, since modifying the source code is not allowed. :-) – Nawaz Nov 30 '10 at 14:05

2 Answers2

2

Sure, you can always create a wrapper-layer handling multi-threading specific tasks such as locking. You could even do so in a second DLL that links with the original one, and then have the final project link with that new DLL.

Be aware that no matter how you implement it, this won't be an easy task. You have to know exactly which thread is able to modify which value at what time, who is able to read what and when etc. unless you want to run into problems like deadlocks or race conditions.

If you're solution allows it, it's often best to assign a single thread to modify any data, and have all others just read and never write, as concurrent reading access is always easier to implement than concurrent writing access (Boost provides all basic functionality to do so, for example shared_mutex).

Mephane
  • 1,984
  • 11
  • 18
  • Mephane, your last paragraph makes sense and in fact I did something similar in my solution, but without using Boost API. thanks for your response by the way. :-) – Nawaz Nov 30 '10 at 14:09
  • By the way, do you realize the values of globals most likely will be different for different threads, and so whenever one thread gets access to DLL (while locking other threads from entering), it should have the same values of globals as it was before, means this current thread must run from the same point/state. – Nawaz Nov 30 '10 at 14:23
  • Sorry, I forgot to ask you, do Boost APIs handles the case (different values for different threads and all), explained in the previous comment? – Nawaz Nov 30 '10 at 14:55
  • 1
    @Nawaz: this complicates the picture, isn't it? If your dll is *statefull*, your task seems quite impossible to achieve without modifying the code. You either need per-thread storage or to modify the interface so that it supports per client sessions. – davka Nov 30 '10 at 15:06
  • 1
    @Nawaz: Why should the values of global be different, unless some thread modifies them? And if you want each thread to get a 'pristine' copy of that data, you could always launch all threads with a copy of that original, unchanged data anyway. The issue at hand however arises when you want exactly that - multiple threads accessing the same data in terms of identity, not value equality. Or did I misunderstand your question? – Mephane Nov 30 '10 at 16:28
  • @Mephane....No. You probably understood me correctly. I want multiple threads to access the same globals, however their values will be different for different thread. As you put it, "same data in terms of identity, not value equality". – Nawaz Nov 30 '10 at 17:03
  • No, if you are accessing the identical global variables, the values will (can) not be "different for a different thread". They will be "different than before, but the same new values for everyone as soon as anyone modifies them". Their values will specifically not be different depending on who is accessing them, but depending on whether they have been changed at all, regardless of when and by whom that change occurred. – Mephane Dec 01 '10 at 08:28
1

Can we do something in the client code to prevent multi-access of the DLL, and at the same time, ensuring that each thread runs in it's own context (meaning, when it gets access to the DLL, the DLL's global values are same as it was before)?

This is the hard part. I think the only way top do this would be to create a wrapper around teh existing DLL. When it is called, it would restore the state (global variables) for the current thread, and save them when the call to the DLL returns. You would need to know all of the state variables in the DLL, and be able to read/write them.

If performance is not an issue, a single lock for the entire DLL would suffice, and be the easiest to implement correctly. That would ensure that only one thread was accessing (reading or writing) the DLL at one time.

KeithB
  • 16,577
  • 3
  • 41
  • 45