Connection Pool -- Locking, Concurrent Access

Sorry for all my previous posts

let me explain the exact problem

There is a singleton object in the shared memory. It conatins a pool of connection objects to a server. (more likely an array of connection objects).
I want to go through the array and find which connection object is free to access.

Then that particular object is locked, used for connection and then unlocked.
The following is the singleton object which encapsulates the connection pool array.

class single
{
private:
~single();
single();
connectionObj[5];
public:
connectionObj & GetConnectionObj() ;
void Lock();
void UnLock();
}

There are at least 8 processes that are simultaneously accessing the singleton object.

I want a synchronization between all these process and want to implement GetconnectionObj() function. How to implement it and where the locks must be used.

Should the locks be while accessing singleton object or while acessing the connection object, or both

please explain me with the help of code

Thanks in advance

Regards
VADAN
I have already explained the answer to this in your previous post.

http://www.cplusplus.com/forum/unices/3769/

I am sorry, but you really need to study multi-threaded development alot more before you try and undertake your current project. There is nothing trivial about developing a multi-threaded application.

Even the implementation of your singleton's Instance/Destroy methods have to be thread-safe.
You need to wrap the locks around the use of the connectionObj's, but you can't put the locks in the GetConnectionObj() method safely. The only way to do it would be something like this

1
2
3
4
5
6
7
8
9
connectionObj &
single::GetConnectionObj(int index)
{
    static connectionObj returnValue;
    Lock();
    returnValue = connectionObj[index];
    Unlock();
    return returnValue;
}

But now you now have an uncontrolled copy of the connectionObj. You can use the returned value but the next thread could change the static return value while you are using it.

What you should do is.....
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void
single::calling_func()
{
    connectionObj my_conn_obj;

    //some initialisation code, don't need connectionObj yet

    . . .

    // Now need ConnectionObj

    Lock();
    my_conn_obj = GetConnectionObj();

    // Use ConnectionObj
    . . .
    // Finished Using ConnectionObj
    UnLock();

    . . .
}


This still has a problem in that you are locking all the objects at once. So you may only be using connectionObj[0] so if another thread wants to use connectionObj[4] it can't. A better idea would be separate locks for each element of connectionObj[5].

I hope this helps

EDIT:

I've just been in and read Zaita's comments on your previous post. I have to say I had underestimated the scale of this question and I support everything he has said.

You need two levels of locks, a global array lock to lock the access to the array and individual locks for each array element once they have been selected. There is a real danger here of creating a deadlock with threads and multiple levels of locking. Be very careful and make sure every path through your code releases the lock(s).
Last edited on
@bnbertha: I am trying to help this guy =\ I really am.

But now you now have an uncontrolled copy of the connectionObj. You can use the returned value but the next thread could change the static return value while you are using it.


2 ways to fix this issue.
1) use a scoped lock within the code. _OR_
2) use thread-specific storage for the static variable.

e.g
1
2
3
4
connectionObj &single::GetConnectionObj(int index) {
    ScopedLock();    
    return &connectionObj[index];
}

Last edited on
@ zaita

I can see what you're saying, I posted before seeing your reply. I have to say what he is trying to do is not simple, doable but not simple.
To add to my post above, that's a thread safe way to access the array for a read. You still need to lock it when writing to the array.

You also need to implement locks within ConnectionObj incase 2 threads get the same one.
One trick I have found in the past is the autolock, not sure if this is the same as Zaita's scopeLock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class autolock
{
   autolock(void)
   {
      //get lock 
   }
   ~autolock(void)
   {
      // release lock
   }
};

. . .

connectionObj &single::GetConnectionObj(int index)
{
    autolock lock_obj;    
    return &connectionObj[index];
    // autolock destructor called
}
Last edited on
Same thing :) a Scoped Lock. Good, especially when you can go

1
2
3
4
5
6
if (true) {
 scopedlock lk(mylock);
 doSomething();
}

do something else
Yes exactly, have another constructor that accepts an external lock object and make the destructor intelligent enough to know whether the lock object is external (don't destroy it) or not.
Yep. All n All, there is alot you have to consider, and re-consider when writing multi-threaded code. I speak from experience.
@Zaita
Yes, likewise

Hey congrats...... 1000 posts :)
err I know =\
Topic archived. No new replies allowed.