Shared db pool
Alex Khmara
alex.khmara at gmail.com
Mon Mar 18 12:55:01 PDT 2013
It seems that I was little bit inaccurate in my question.
More correctly, code is this (int template param is just a hack, I plan to do more correct version later):
//************************************
class Pool(T, U = int) {
this() {
mutex = new Mutex;
}
struct PoolRef(T) {
T* member;
Pool!T *pool;
alias member this;
~this() {
pool.free(member);
}
};
synchronized PoolRef!T get() {
if (!mutex) {
init();
}
if (firstFree >= items.length) {
if (items.length < maxMembers) {
items ~= T();
static if (!is(U == int)) {
initLambda(items[$]);
}
free ~= true;
} else {
throw new Exception("Too many requests to pool");
}
}
free[firstFree] = false;
for (; firstFree < items.length && !free[firstFree]; ++firstFree)
{}
PoolRef pr;
pr.member = items[$];
pr.pool = this;
return pr;
}
private:
U initLambda;
class Mutex {};
T*[] items;
bool[] free;
int firstFree;
int maxMembers;
shared Mutex mutex;
}
shared Pool!Mysql pool;
//************************************
This compiles (and simplified example wit big sleeps in get and debug output seems to work correctly),
but I am not sure about thread-safety.
If after that I will have no no shared-related overhead in call to Mysql methods than
things are good - pool will not give Mysql instance to second thread until it will be relased by first thread.
On Mon, 18 Mar 2013 08:28:41 +0100, Benjamin Thaut wrote:
> Am 17.03.2013 22:21, schrieb Alex Khmara:
>> My task involves many worker threads, each of them uses Curl instance
>> to do one or several requests and one Mysql connection instance to
>> store data and do some aggregations. ALso sometimes these threads do
>> other work that don't require these resources.
>>
>> So I want to make two pools (one for Curl and one for Mysql
>> connections),
>> so that number of DB connections (or Curl instances) will be lower than
>> number of threads, so I cannot just use
>> DataPool.WorkerLocalStorageRange.
>>
>> So I'm trying to create shared pool. And there arises question:
>>
>> if I have this code:
>>
>>
>> class SharedPool {
>>
>> ...
>> Mysql* get() {
>> ...
>> return cast(Mysql*) connections[freeIndex];
>> }
>> ...
>> Mysql*[] connections;
>> }
>>
>> shared SharedPool pool;
>>
>>
>> when I will get syncronization overhead: only on access to SharedPool
>> or on every access to Mysql instance?
>>
>> What I really want - is to NOT have any shared-related code after
>> getting some Mysql instance and before returning it to pool, so Mysql
>> instances must be essentially non-shared. Is it possible?
>>
>>
> Your current code will not work at all, because you can not call get()
> from shared instance of the class (because get is not a shared method).
> Also your current code does not have any synchroization overhead. Just
> adding shared to something does not mean that there will be any
> synchronization added automatically (at least not yet). You need to add
> synchronization yourself for example by using a "synchronized(this) {
> ... }" block.
>
> Kind Regards Benjamin Thaut
More information about the Digitalmars-d-learn
mailing list