C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

A way to manage globals in multithreading environments?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
gianguz
Guest





PostPosted: Tue Dec 14, 2004 3:28 am    Post subject: A way to manage globals in multithreading environments? Reply with quote



In the following example Global is able to create and manage access
to objects of any kind (even in a multithreading environment) with
and index value attached to. So a Global<0, string> is a unique
string instance object allocated into the system that can be accessed
from any point into the program simply 'creating' another instance of
Global<int, T> with the same id and type.Like globals, destruction
of these objects is delegated until the lifetime expiration of the
program.

Here is the example:

static FakeSemaphore _semaphore;

template<class LOCK> class FakeGuard {

private:

FakeSemaphore* sem;

FakeGuard();

public:

FakeGuard(FakeSemaphore* s) { sem = s; sem->lock(); }

~FakeGuard() { sem->unlock(); }
};

template<int I,class T> class Global {

public:

static const int Index = I;

typedef T Type;

Global() { }

Global(const T& t) { _set(t); }

const Global& operator =(const T& t) { _set(t); return *this; }

operator T&() { return _get(); }

~Global() { }

private:

static T& _get() {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T Value;

return Value;
}

static void _set(const T& t) {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T& Value = _get();

Value = t;

return;
}
};


int main() {

typedef Global<0, string> Global0;
typedef Global<1, string> Global1;

Global0 a;
Global1 b;

a = "I'm A";

b = "I'm B";

cout << (string&)a << " " << (string&)b << endl;

a = b;

cout << (string&)a << " " << (string&)b << endl;

typedef Global
Global2 c;

c = "I'm C";

cout << (string&)a << " " << (string&)b << endl;
}

Question is:
it can be useful? using globals instances of any kind in multithreading
is always an
untouchable argument, but what about to rediscuss this?
Thanks,

Gianguglielmo


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Tue Dec 14, 2004 8:34 pm    Post subject: Re: A way to manage globals in multithreading environments? Reply with quote



gianguz wrote:

Quote:
In the following example Global is able to create and manage access
to
objects of any kind (even in a multithreading environment) with and
index value attached to. So a Global<0, string> is a unique string
instance object allocated into the system that can be accessed from
any point into the program simply 'creating' another instance of
Global<int, T> with the same id and type.Like globals, destruction of
these objects is delegated until the lifetime expiration of the
program.

Several questions/comments:

Quote:
Here is the example:

static FakeSemaphore _semaphore;

template<class LOCK> class FakeGuard {

Why is this a template? You don't use LOCK anywhere, so there is no
dependent code.

Quote:
private:

FakeSemaphore* sem;

FakeGuard();

Why do you declare this function? You never define it, and never use
it.

Quote:
public:

FakeGuard(FakeSemaphore* s) { sem = s; sem->lock(); }

Wouldn't member initialization be more appropriate?

And of course, the function signature indicates to me that a NULL
pointer would be an acceptable argument. why aren't use using a
reference?

Quote:
~FakeGuard() { sem->unlock(); }
};

Is this class copiable? Technically, there is a copy constructor and
an
assignment operator (furnished by the compiler) which work, but the
resulting semantics seem like a sure guarantee of missing locks and/or
deadlocks to me.

Quote:
template<int I,class T> class Global {

public:

static const int Index = I;

typedef T Type;

Global() { }

Global(const T& t) { _set(t); }

const Global& operator =(const T& t) { _set(t); return *this; }

operator T&() { return _get(); }

~Global() { }

private:

static T& _get() {

Symbol names beginning with an _ are generally not a good idea.

Quote:
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T Value;

return Value;

Attention here: you're returning a reference which will allow
unprotected access to the variable.

Quote:
}

static void _set(const T& t) {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T& Value = _get();

You grab the lock here, then try to grab it again in _get(). A
deadlock
with many, if not most, mutex implementations. (Of course, you don't
show us what you are actually using for locking, so it is hard to tell.
But Posix mutex's aren't recursive by default, and I don't think that
those of Windows are either. So unless you've added extra code to make
them recursive, you have a 100% guranteed dead-lock.)

Quote:
Question is:
it can be useful?

The real question is: can it be made to work? In the form you seem to
be trying to use, I don't think so. I have once or twice used
singletons in which the instance function returned a smart pointer,
using reference counting. The instance function also grabbed a lock
which was released when the reference count returned to 0. That can be
useful in special cases, but it isn't a general solution either.

And of course, even if it could be made to work, identifying variables,
especially global variables, by number simply won't fly.

Quote:
using globals instances of any kind in multithreading is always an
untouchable argument, but what about to rediscuss this?

Most of my multi-threaded work uses a few globals: an instance of
Configuration, for example, or Log -- getting the latter to work
efficiently in a multi-threaded environment can be a real challenge,
especially if you want to be able to modify the logging configuration
dynamically. I think that there is a fairly large consensus that some
things have to be global, multi-threading or no. But something like
you
are suggesting won't do the trick.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
GianGuz
Guest





PostPosted: Wed Dec 15, 2004 1:04 pm    Post subject: Re: A way to manage globals in multithreading environments? Reply with quote



[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
Quote:
Why is this a template? You don't use LOCK anywhere, so there is no
dependent code.


I think you should read better what is written into an article before
commenting it. Anyway, here is where is used.

static T& _get() {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T Value;

return Value;
}

static void _set(const T& t) {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T& Value = _get();

Value = t;

return;
}

Quote:
private:

FakeSemaphore* sem;

FakeGuard();

Why do you declare this function? You never define it, and never use
it.

Ah, ok, FakeGuard() { }...I noticed that the name Fake... ,that should
suggest
it is only a piece of support code to understand better the real
discussion point) is not so clear. Maybe, is not so clear for you.
Quote:

public:

FakeGuard(FakeSemaphore* s) { sem = s; sem->lock(); }

Wouldn't member initialization be more appropriate?

Mmmm...look at the comment before
Quote:

And of course, the function signature indicates to me that a NULL
pointer would be an acceptable argument. why aren't use using a
reference?

~FakeGuard() { sem->unlock(); }
};

Is this class copiable? Technically, there is a copy constructor and
an
assignment operator (furnished by the compiler) which work, but the
resulting semantics seem like a sure guarantee of missing locks
and/or
deadlocks to me.

template<int I,class T> class Global {

public:

static const int Index = I;

typedef T Type;

Global() { }

Global(const T& t) { _set(t); }

const Global& operator =(const T& t) { _set(t); return *this; }

operator T&() { return _get(); }

~Global() { }

private:

static T& _get() {

Symbol names beginning with an _ are generally not a good idea.

FakeGuard<FakeSemaphore> guard(&_semaphore);
static T Value;

return Value;

Attention here: you're returning a reference which will allow
unprotected access to the variable.


This is what i want to do.

Quote:
}

static void _set(const T& t) {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T& Value = _get();

You grab the lock here, then try to grab it again in _get(). A
deadlock
with many, if not most, mutex implementations. (Of course, you don't
show us what you are actually using for locking, so it is hard to
tell.
But Posix mutex's aren't recursive by default, and I don't think that
those of Windows are either. So unless you've added extra code to
make
them recursive, you have a 100% guranteed dead-lock.)


static void _set(const T& t) {
static T& Value = _get();
FakeGuard<FakeSemaphore> guard(&_semaphore);

I understand, the next time i have to explain something i have to post
it togheter with the implementation of the O/S i used, to make yourself
able
to understand what i want to do.

Quote:
Question is:
it can be useful?

The real question is: can it be made to work? In the form you seem
to
be trying to use, I don't think so. I have once or twice used
singletons in which the instance function returned a smart pointer,
using reference counting. The instance function also grabbed a lock
which was released when the reference count returned to 0. That can
be
useful in special cases, but it isn't a general solution either.

And of course, even if it could be made to work, identifying
variables,
especially global variables, by number simply won't fly.

using globals instances of any kind in multithreading is always an
untouchable argument, but what about to rediscuss this?

Most of my multi-threaded work uses a few globals: an instance of
Configuration, for example, or Log -- getting the latter to work
efficiently in a multi-threaded environment can be a real challenge,
especially if you want to be able to modify the logging configuration
dynamically. I think that there is a fairly large consensus that
some
things have to be global, multi-threading or no. But something like
you are suggesting won't do the trick.

I do the trick all the time and works very well.
Thanks, your comments were absolutely useless.

Quote:

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Daniel Krügler (ne Spange
Guest





PostPosted: Wed Dec 15, 2004 4:50 pm    Post subject: Re: A way to manage globals in multithreading environments? Reply with quote

Hello GianGuz,

GianGuz schrieb:

Quote:
kanze (AT) gabi-soft (DOT) fr wrote:


Why is this a template? You don't use LOCK anywhere, so there is no
dependent code.



I think you should read better what is written into an article before
commenting it.

That **is** really strong tobacco!


First, your comment is wrong, absolutely wrong, because I can tell you,
that James Kanzes
comments are **all** appropriate and well thought-out!

Second, actually what you say here, **is** indeed a sign, that **you**
didn't read James Kanzes
comments carefully, because I doubt that you will find many experts in
C++ like him, who combine
the high art of

- Explanational simplicity ("Everyone can understand it")
- Knowledge in the broad sense and knowledge in the detail.
- Think first, answer second. Its quite easy to give a quick short
answer solving immediate problems,
but taking the time to find a solution, which works not only tomorrow
but also for the next 3 years, is
seldomly done.
- Offering you his personal time w/o getting a single cent from you.

I can tell you that I would have been proud if my problem is interesting
enough for persons like
him to give some valuable comments.

Though this (my) answer does not contain any C++ contributions, I do try
to sent it, because

- Your reply to James Kanze doesn't either.
- There are times were an advice concerning basic newsgroup behaviour
seems appropriate.

I would like to add, that this contribution is not written,

- to flame the original poster, but only to provide a basic protection
of the helpful assistance of the
first reply to the OP (To my opinion the last reply shouldn't have been
accepted by the mods - but
they also can't find everything)
- to unfairly raise the reputation of a special person compared to
others. I think we have a high
density of very cute experts here who provide us **all** with their
valuable experience.

Others will comment, I am sure, the errornous assertions, you made...

Sincerily,

Daniel Krügler



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
GianGuz
Guest





PostPosted: Thu Dec 16, 2004 1:56 pm    Post subject: Re: A way to manage globals in multithreading environments? Reply with quote

Daniel Krügler (ne Spangenberg) wrote:
Quote:
Hello GianGuz,

GianGuz schrieb:

[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:


Why is this a template? You don't use LOCK anywhere, so there is
no
dependent code.



I think you should read better what is written into an article
before
commenting it.

That **is** really strong tobacco!

First, your comment is wrong, absolutely wrong, because I can tell
you,
that James Kanzes
comments are **all** appropriate and well thought-out!

Second, actually what you say here, **is** indeed a sign, that
**you**
didn't read James Kanzes
comments carefully, because I doubt that you will find many experts
in
C++ like him, who combine
the high art of

- Explanational simplicity ("Everyone can understand it")
- Knowledge in the broad sense and knowledge in the detail.
- Think first, answer second. Its quite easy to give a quick short
answer solving immediate problems,
but taking the time to find a solution, which works not only tomorrow

but also for the next 3 years, is
seldomly done.
- Offering you his personal time w/o getting a single cent from you.

I can tell you that I would have been proud if my problem is
interesting
enough for persons like
him to give some valuable comments.

Though this (my) answer does not contain any C++ contributions, I do
try
to sent it, because

- Your reply to James Kanze doesn't either.
- There are times were an advice concerning basic newsgroup behaviour

seems appropriate.

I would like to add, that this contribution is not written,

- to flame the original poster, but only to provide a basic
protection
of the helpful assistance of the
first reply to the OP (To my opinion the last reply shouldn't have
been
accepted by the mods - but
they also can't find everything)
- to unfairly raise the reputation of a special person compared to
others. I think we have a high
density of very cute experts here who provide us **all** with their
valuable experience.

Others will comment, I am sure, the errornous assertions, you made...



I apologize for my too coloured sentences, but the way an answer was
given can change a lot the meaning of you want to say.

The problem is that answers are not focused on the problem i submitted.
I can made mistake submitting a -not so well formed code- sometimes but

in the above example seems to me clear that considerations to do
concerns the
model of managing these globals and not the support code used to show
that.

By the way an assertion like :
"I think that there is a fairly large consensus that some
things have to be global, multi-threading or no. But something like
you are suggesting won't do the trick."

shown that I was the first that was not taken into consideration as a
person
suited with intelligence.

I will look at others that could arise critics on what I said,
critics are always useful and I'm happy to be criticized,but
I don't admit to be considered as an idiot.

I hope this discussion will be closed soon due to the fact that
everybody here is interested in talking about C++ and not of personals
matters.


Best regards,

Gianguglielmo


It'll need more memory,more speed,more power,more data
.... but ... at the end ... Akira will live!

Dr Gianguglielmo Calvi - Research Area
[ n o z e S.r.l. ] www.noze.it
[ I.S.T.C. / CNR-Roma ] www.istc.cnr.it
[ AKIRA Project ] www.akira-project.org


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Thu Dec 16, 2004 2:05 pm    Post subject: Re: A way to manage globals in multithreading environments? Reply with quote

GianGuz wrote:
Quote:
kanze (AT) gabi-soft (DOT) fr wrote:
Why is this a template? You don't use LOCK anywhere, so
there is no dependent code.

I think you should read better what is written into an article
before commenting it. Anyway, here is where is used.

static T& _get() {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T Value;

return Value;
}

Well, I still don't see the reason for a template, but that
really wasn't one of my main point.

Quote:
static void _set(const T& t) {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T& Value = _get();

This was. You use the same guard in _get. You don't show us
the actual implementation of FakeSemaphore and FakeGuard, but I
suppose, based on the names, that it is a placeholder for
somthing along the lines of boost::mutex and
boost::mutex::scoped_lock.

On my machine (Sun Sparc, Solaris 2.Cool, using boost::mutex and
boost::mutex::scoped_lock, the above code deadlocks. Every
time. In order for it to work, you must use some sort of
recursive locking mechanism; this may be the default on your
platform, but it isn't on mine, and an implementation of
recursive locking (we use it here in some applications) has
significant runtime overhead -- you wouldn't want to use it for
every access to a primitive type.

At the very least, if you present such an idea, you should
specify that it requires some sort of recursive locking
mechanism, but such mechanisms are NOT the default.

Quote:
Value = t;

return;
}

private:

FakeSemaphore* sem;

FakeGuard();

Why do you declare this function? You never define it, and
never use it.

Ah, ok, FakeGuard() { }...I noticed that the name
Fake... ,that should suggest it is only a piece of support
code to understand better the real discussion point) is not so
clear. Maybe, is not so clear for you.

Which doesn't address my question: I imagined FakeGuard to be
something like boost::mutex::scoped_lock.
Boost::mutex::scoped_lock does NOT have a default constructor,
because it makes no sense to define an object of this type
without a parameter specifying the mutex (FakeSemaphore) to be
used. Presumably, if you include it, you do so for a reason.
So I simply ask, why? It's something I don't understand in your
code.

[...]
Quote:
static T& _get() {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T Value;

return Value;

Attention here: you're returning a reference which will allow
unprotected access to the variable.

This is what i want to do.

So why bother with the class then. A simple "T value;" will
allow unprotected access to the variable.

As it stands, your class has basically two functions, _set and
_get. The first one deadlocks immediately when it is called,
and the second does nothing. I'm having a lot of trouble
understanding the utility of such a class.

Quote:
}

static void _set(const T& t) {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T& Value = _get();

You grab the lock here, then try to grab it again in _get().
A deadlock with many, if not most, mutex implementations.
(Of course, you don't show us what you are actually using
for locking, so it is hard to tell. But Posix mutex's
aren't recursive by default, and I don't think that those of
Windows are either. So unless you've added extra code to
make them recursive, you have a 100% guranteed dead-lock.)

static void _set(const T& t) {
static T& Value = _get();
FakeGuard<FakeSemaphore> guard(&_semaphore);

I understand, the next time i have to explain something i have
to post it togheter with the implementation of the O/S i used,
to make yourself able to understand what i want to do.

If you make critical assumptions that don't usually hold, like
recursive mutexes, yes, you have to state them.

Quote:
Question is: it can be useful?

The real question is: can it be made to work? In the form
you seem to be trying to use, I don't think so. I have once
or twice used singletons in which the instance function
returned a smart pointer, using reference counting. The
instance function also grabbed a lock which was released
when the reference count returned to 0. That can be useful
in special cases, but it isn't a general solution either.

It can, of course, be made to work using proxies. I probably
should have mentionned this in my earlier posting.

Quote:
And of course, even if it could be made to work, identifying
variables, especially global variables, by number simply
won't fly.

using globals instances of any kind in multithreading is
always an untouchable argument, but what about to
rediscuss this?

Most of my multi-threaded work uses a few globals: an
instance of Configuration, for example, or Log -- getting
the latter to work efficiently in a multi-threaded
environment can be a real challenge, especially if you want
to be able to modify the logging configuration dynamically.
I think that there is a fairly large consensus that some
things have to be global, multi-threading or no. But
something like you are suggesting won't do the trick.

I do the trick all the time and works very well.

Prove it. I suspect rather that your code is not thread safe,
and that you've just been lucky so far. (The fact that code
doesn't crash immediately doesn't prove that it works.) If your
system supports recursive mutexes, and you never use the results
of _get outside of _set, or you never use the class some
additional synchronization, it will work. But if you need
additional synchronization, then I fail to see any utility in
the class.

Quote:
Thanks, your comments were absolutely useless.

Maybe for you. They might prevent someone else from wasting
their time trying to use it.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
GianGuz
Guest





PostPosted: Thu Dec 16, 2004 6:19 pm    Post subject: Re: A way to manage globals in multithreading environments? Reply with quote

[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
Quote:
GianGuz wrote:
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
Why is this a template? You don't use LOCK anywhere, so
there is no dependent code.

I think you should read better what is written into an article
before commenting it. Anyway, here is where is used.

static T& _get() {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T Value;

return Value;
}

Well, I still don't see the reason for a template, but that
really wasn't one of my main point.

static void _set(const T& t) {
FakeGuard<FakeSemaphore> guard(&_semaphore);
static T& Value = _get();

This was. You use the same guard in _get. You don't show us
the actual implementation of FakeSemaphore and FakeGuard, but I
suppose, based on the names, that it is a placeholder for
somthing along the lines of boost::mutex and
boost::mutex::scoped_lock.

On my machine (Sun Sparc, Solaris 2.Cool, using boost::mutex and
boost::mutex::scoped_lock, the above code deadlocks. Every
time. In order for it to work, you must use some sort of
recursive locking mechanism; this may be the default on your
platform, but it isn't on mine, and an implementation of
recursive locking (we use it here in some applications) has
significant runtime overhead -- you wouldn't want to use it for
every access to a primitive type.

At the very least, if you present such an idea, you should
specify that it requires some sort of recursive locking
mechanism, but such mechanisms are NOT the default.


You are right. Examples should be clear and should work.
I modified it. I also follow your suggestions. The mutual exclusion
policy is
managed by a semaphore but any kind of mutex (or recursive mutex) could
be
used.
Let's see the code:

#include <zthread/Thread.h>
#include <zthread/Guard.h>
#include <zthread/Semaphore.h>
#include <zthread/ThreadedExecutor.h>
#include <string>
#include <iostream>

extern "C" {

#include <stdlib.h>
#include <time.h>
}

using namespace std;
using namespace ZThread;

#define AVAILABLE_SEMAPHORES 10

static Semaphore* semaphore[AVAILABLE_SEMAPHORES];

template<int I,class T> class Global {

public:

static const int Index = I;

typedef T Type;

Global() {

//cout << getpid() << " " << "Global() called " << endl;
}

explicit Global(const T& t) {

//cout << getpid() << " " << "Global(const T&) called " << endl;

Guard
_set(t);
}

const Global& operator =(const T& t) {

//cout << getpid() << " " << "operator = called " << endl;

Guard
_set(t);

return *this;
}

operator const T&() {

//cout << getpid() << " " << "T& called " << endl;

Guard
return _get();
}

~Global() { }

private:

static T& _get() {

//cout << getpid() << " " << "_get called " << endl;

static T* Value = new T;

return *Value;
}

static void _set(const T& t) {

//cout << getpid() << " " << "_set called " << endl;

_get() = t;

return;
}
};

class RW : public Runnable {

public:

RW() { }

void run() {

while(true) {
typedef Global<0, string> Global0;
typedef Global<1, string> Global1;

Global0 a;
Global1 b;

char pid[5];

sprintf(pid,"%d",getpid());

cout << getpid() << " setting a and b (previous)[" << (string)a << "
" << (string)b << "]" << endl;

a = "I'm A " + string(pid);

b = "I'm B " + string(pid);

cout << getpid() << " getting a and b (after)[" << (string)a << " "
<< (string)b << "]" << endl;

cout << getpid() << " assigning b to a (previous)[" << (string)a <<
" " << (string)b << "]" << endl;

a = b;

cout << getpid() << " assigning b to a (after)[" << (string)a << " "
<< (string)b << "]" << endl;

typedef Global
Global2 c;

cout << getpid() << " setting c (previous)[" << (string)c << " " <<
"]" << endl;

c = "I'm C " + string(pid);

cout << getpid() << " setting c (after)[" << (string)c << " " << "]"
<< endl;

Thread::sleep(1000);
}
}

~RW() { }
};

int main(int argc, char* argv[]) {

if (argc > 1) {

int size;

for(int i=0; i
semaphore[i] = new Semaphore;

size = atoi(argv[1]);

ThreadedExecutor executor;

for(int i=0; i
executor.execute(new RW());
}
}

I used ZThread lib to manage thread primitives.
But any other with the same Pattern Design
(Task and Executors) should work.
It seems to work. Without crash and with a lot of thread since i have
changed various things.
Thanks again for you suggestions Mr Kanze, and excuse me again for my
misunderstanding and language in the previous post.

Cheers,

Gianguglielmo


Quote:
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Dec 17, 2004 1:31 pm    Post subject: Re: A way to manage globals in multithreading environments? Reply with quote

GianGuz wrote:
Quote:
kanze (AT) gabi-soft (DOT) fr wrote:
GianGuz wrote:

[...]
Quote:
At the very least, if you present such an idea, you should
specify that it requires some sort of recursive locking
mechanism, but such mechanisms are NOT the default.

You are right. Examples should be clear and should work. I
modified it. I also follow your suggestions. The mutual
exclusion policy is managed by a semaphore but any kind of
mutex (or recursive mutex) could be used.

To be more precise about my criticisms: your initial code
contained two major flaws:
- it deadlocked unless the locking mechanism was recursive,
and
- it "leaks" a reference to the object it is supposed to
protect.

Your corrections do address the first problem, but not the
second. You still have a public function which returns a
reference to the object. And accesses through this reference
will NOT be protected.

I'll admit that I'm a bit sensitive with regards to this issue.
Someone had done the same thing in the project I'm currently
working on, and we had a crash because of it. And because the
return of the reference was part of a widely used interface,
the correction was a lot of work.

IMHO, the correct solution would have been to have dropped all
attempts to lock the element. Locking individual objects,
except for very high level objects, is almost always the wrong
granulatity. In our code, in fact, the error had been present
for many years -- it hadn't appeared largely because all of the
client code was protecting the accesses at a higher level,
i.e. the locks were simply unnecessary excess overhead. But the
one time someone tried to take advantage of them, they didn't
work -- you cannot leak a reference and expect a lock within the
object to protect anything.

For the rest, on a large project, managing the numbers so there
are no collisions will also cause not a few problems.
Identifying unique objects only by a number is not a very good
idea, IMHO, and should be avoided whenever possible.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.