|
M.Roger,
I didn't understand the two lines of your reply. Eventhough if you meant what would be the consequence if a certain "name reader" gets a corrupted value, then my answer is that there will be no fatal problems.
The application consists of a fixed number of threads that services the concurrent clients requests. all thread are executing the same prototype code.
I have seen many sample implementation of the design I am using(even by Micrsoft), but they do all care so much more about data correctness than
about parallelisation : ie for example looking at many simple chat multithreaded programs, they have a sort of a global CriticalSection that they call for nearly evry operation. Examining them I easily conculded that didn't take the very sepecificities of their code in order to only limit serialization upon the only necessary code blocks, or data blocks.
In my case, I want give much importance to parallelisation, ie speed of execution of the requests, abnd only cause serialization upon the very necessary details.
And even for those details, I try to isolate the non fatal ones, ie for example the data members of which incorrectnesses wouldn't lead to fatal consequences.
My above example is a simple case.But the problem I faced is that concurrent access to ATL/MFC CString for example causes the application to crash !
Even the concurrent execution of such two functions like the followings does cause the program to crash :
void setName(CString myName)
{
this->myName=myName;
}
bool getIsNameEqual(CString myName)
{
return this->myName==myName;
}
!
Our Philosophy, Mohammed Baqir Al Sadr
|
|
|
|
|
hINTModuleState wrote: I didn't understand the two lines of your reply. Eventhough if you meant what would be the consequence if a certain "name reader" gets a corrupted value, then my answer is that there will be no fatal problems.
I suppose you have a container, preferably a std::map , that maps user names to their data.
If you fail to look up a certain user name in the map you know that the user has either logged off or changed the name. You can then try to update the thread local name from the instance shared between threads, using a synchronization object such as a critical section.
Perhaps this article[^] can be of interest.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Ah, OK I see. The container I use is a simple array on the stack :
CPlayer playersTab[nMaxPlayers];
..
I am reading the article you supplied.
Our Philosophy, Mohammed Baqir Al Sadr
|
|
|
|
|
hINTModuleState wrote: The container I use is a simple array on the stack
You will get a performance boost by using the std::map during the lookup sequence.
Here are some additional ideas:
When I do things like this I tend to use the same concept every time with following corner stones:
- my objects are created on the heap
- my objects are used through reference counting smart pointers
- the container, e.g. std::map or std::vector , holds smart pointers
- a critical section protects the container during insertion and removal of objects
- an optional critical section inside my object protects its data if necessary
Why the heap?
Many reasons. One is that I may not know how many objects will be created and I may run out of stack space.
Why reference counting smart pointers?
1. It avoids race conditions when the object is supposed to be deallocated. When the object is not referred to by any client any longer (i.e. all smart pointers has gone out of scope) the object is automatically destroyed.
2. "Copying" an object does not involve creating a new object, allocating space for it and copying the data when used through smart pointers. The reference count is increased and the same object is operated on.
3. When the container is destroyed and its destructor is called, all elements are destroyed automatically. There's no need to iterate through the elements of the container and destroy each element "manually". Makes the code look nicer to me.
It's not that hard to create a smart pointer template. There are several smart pointer implementations here at CodeProject you can get ideas from.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
I appreciate your tips and information generosity.
Well I knew about the std::map, the MFC CArray or CMap ..and other containers.
lookup time ,in my point of view, is not determined so much by the actual used container. Rather by the compare function I think.
Ie, in my case doing the following :
CPlayer* getPlayerByName(CString targetName)
{
for (int i=0 --> maxPlayers)
if(playersTab[i].getName()==targetName)
return &playetrsTab[i];
return NULL;
}
does much depend, if profiled, on the time spent within the string compare operations.
It is already, Roger, that I am stuck on the problem of the synchronization of such variable as the name of the player, since setName and getName will cause the application to crash if run concurrently unless I do synchronization which I am fearing its impact on overall application performance.
The article you supplied is very interesting, and by the way, it is written by someone BIG.Sadly, even if I am actually resolving the problem of the efficient handling of multiple Network IOs by use of IO Completion just like M.Joseph advised for good results, I find it unavoidable to do such "explicit" synchronization as the one I am intending to do on CPlayer::name using CriticalSection and on the many data varaiables that are accessed by worker trhread procedure.
My application is a server application, that I would like to deploy on a server machine one day.
I am using simple C type arrays, instead of the dynamic containers as std::map,etc becuase it isa lready that I wo'nt do any dynamic memory allocation in order to avoid RAM fragmentation. There are many types of data, creating them on the heap also causes a waste of space.
I would like to fix the possible maximum of data that can be handled by the server from the start, then only worry about crash scenarios and may be also certain severe inconsistencies..before I would let the application perform 24h/24.
Yes I know smart pointers, I recenly received an XML parser implementation in C++ by a freindly person from France, and that does the automatic allocation and deallocation of memory : it is like a heap object created and refreneced by the stack object so to do the "delete" automatically in the destructor of the stack object...
As I said, I allocate data from the start, I reuse them all the time.
....
Our Philosophy, Mohammed Baqir Al Sadr
|
|
|
|
|
Regarding the user name and the critical section I just wonder if you have thought about the possibility to inform the thread that the name has changed, instead of having the thread reading the shared resource every time it needs it? This will make the user name resource thread local and you won't need any synchronization.
Here follows some thoughts that are based upon the information you've provided.
I may have interpreted your problem wrong and they may not be applicable in your situation, but perhaps you can find something useful.
Perhaps I can interest you in another article by the same author:
Optimization: Your Worst Enemy[^].
It seems to me that you're concentrating on optimizing the details in a way that you may lose the bigger picture. It's just a feeling I get from the information you've provided and I may perfectly well be wrong, but think about it. Worrying about RAM fragmentation these days, especially when you say you "allocate data from the start, I reuse them all the time". The memory manager is really clever in that aspect.
hINTModuleState wrote:
CPlayer* getPlayerByName(CString targetName)
{
for (int i=0 --> maxPlayers)
if(playersTab[i].getName()==targetName)
return &playetrsTab[i];
return NULL;
}
does much depend, if profiled, on the time spent within the string compare operations.
Well, yes, to some extent. But you have to compare it with how long it takes to iterate through the container to find it. You also have a lot of function calls that can be avoided, if you're looking for optimization.
Suppose you have a map that maps CStrings containing user names to smart pointers to objects with data for the user. Looking up the data for the user will make use of the hash table of the map class. Have a look here[^].
What I suggest is something like this:
typedef CMySmartPointerTemplate<CMyData> DataPtr_t;
std::map<CString, DataPtr_t> NameToDataMap;
DataPtr_t spCurrentData = NameToDataMap[TheUserName];
if( spCurrentData )
{
}
else
{
} This way you don't create a CString copy on the stack as the code for the template is inline, you avoid a function call for the same reason and the lookup uses a hash table for performance, to name a few advantages.
Since the CString class has both operator<() and operator>() the std::map template hash algorithm works straight up and you don't have to provide a comparison function.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Roger, if I have to do it that way, then I will also have to find mechanism on how to hold copies of many other variable attributes for evry thread (8 threads), and how to inform the threads of their values changes.
The application is a real time chess server, (ie for blitz play) and there are much attributes and references like the CPlayer::name :players elos, games moves, players running games,challenges time property,game brodcasts participants, tournament properties etc..many many.All of them I have to ensure that concurrent access to would not cause application crash or unbearable values incorrectnesses.I am really in a big scenario.
Well indeed, I confirm this second article you supplied : optimzation can easily lead me to contradict the abstractions I've done, or I should do.
It is already that even if I choose your previous solution according to which local copies of critical data attributres are hold by the concurrent threads, then I will have to violate data visibility and it will be like synchronization a certain member x is solved elswere its class extent, such that if I encounter other synchronization issue in other contexts (I have other threads than the worker threads taht are running too) then I will have to rewrite syn mechanism.
I think I will have to content myself with CriticalSection and only hiding synchrobnization within the scope of class member functions .
No, I nolonger can endure to change the container for my data : reading this std::map again only dazzles me to using it.
I didn't know about the use of hashing inside map container.
I already using hashing client-side when you choose to play a local chess game against the computer, rather than on the server : the chess algorithms keeps track of searched positions assements numbers not by recording the whole position (what piece on evry square) along with the numbers, but rather by storing a signature of the position against the actuall assesment number..becuase the tree of chess position always contains repetitions.
Instead of the maps, maybe I think of implementing hashing, in order to make getPlayerByName very quick, but I will preserve my stack table.
Indeed I didn't know that hashing will bring significant performance here. I didn't even believe that this is a context for it : now that I see it is implemented in stadard lib ! Becuase in chess, the number of positions generated is so big (mesured in KNps : kilo Nodes per soconds) that indeed the consequence is that the time spent on the would-be compare function would be non negligeable when it is accumulated. But eventually we want access to the assesment number of the position serached becuase it is the most costly number to generate in terms of time.
Any way I have developed a sort of dhashbord, ie remote monitor for the server performances by collecting key counters and feature values and I will make sure to implement the many solutions in hand and vizualize the results.
I share with you its picture, and I am going home now becuase my head is as if split in two, one part becuase of DirectShow and the other becuase oif thread synchronisation.
http://farm4.static.flickr.com/3014/2655919984_7fa6d4ee3c.jpg?v=0[^]
Our Philosophy, Mohammed Baqir Al Sadr
|
|
|
|
|
What about Multiple-Read/Single-Write Lock ? It allows Multiple reader thread at same time, and only one writer thread at a time.
Seems its more suitable for your performance requirement, Since it won't serialize multiple reader thread. Check this article[^]
Regards,
Jijo.
_____________________________________________________
http://weseetips.com[ ^] Visual C++ tips and tricks. Updated daily.
|
|
|
|
|
if I serialize between the reader and the writer, then, using simple CriticalSection, I also serialized the many readers,so I am back to the loss of time.
Your solution seem to have solved this, but looking at the code, it really frightens : there are events and counters,etc
Is it safe to use it an apply it to the many common data I have ?
Our Philosophy, Mohammed Baqir Al Sadr
|
|
|
|
|
|
Thank you Raj !
I will have to make a simulation test in order to actually see the performance impact.
I also visited your website, it is clean and beautiful to see !
Thank you for your help and the precious links.
Our Philosophy, Mohammed Baqir Al Sadr
|
|
|
|
|
What you could do is use a simple char array with a fixed size (allow only username of a certain size, not more). Then what you could do to avoid locks is the following:
You add two flags with with the name, those flags will contain a 'version' Id. Each time the writer wants to change the name, it first increments the first flag, changes the name and finally increase the second flag.
The reader will read the first flag, read the name and read the last flag. If both flags read are the same, it means that the data is not corrupted, otherwise you have to repeat the operation until both flags are identical.
Of course, this is only valid if you have a single writer, but it avoids you to use critical sections which can degrade a bit the performances.
|
|
|
|
|
Thank you for your intervention Cedric.
Your idea seem to ensure that the reader gets a consistent value even when run at the same time as the writer, but without synchronization primitives like Critical sections, so I am tempted to becuase I want to avoid time loss by synchronisation.
.
My problem, Cedric, is that indeed I do not care about data consistency as I stated in my firt message : if the reader gets a corrupted version of the name attribute because a writer is writing on it, then it is not a big problem for me.
My problem is that the application crashes when setName and getName are run simultaneously..And I would like to get the view point of people here of the impact of using multiple Critical section for the many attribute instances and the impact of the many calls that will fall on protected sections..those imptacs on overall application performance if not on the OS and its ressources as a whole !
Examining your solution, it is even that a data corruption scenario still persists unless I do syncronisation upon access to the flags..
..
Our Philosophy, Mohammed Baqir Al Sadr
|
|
|
|
|
hINTModuleState wrote: My problem is that the application crashes when setName and getName are run simultaneously..
That's why I suggested to use a fixed size char array instead of a string. In that specific case, your program won't crash: you always read/write in the same memory area, so the only thing that could go wrong is data corruption. You have to make sure that both flags are equals before doing anything with the string that you read from the reader thread. The problem with CString objects is that you might have reallocation, so in some cases you could try to access an invalid CString object, which is causing the crash. You don't have this problem with fixed size char arrays, because you are in control of everything.
By the way, setting the new flag value is an atomic operation.
|
|
|
|
|
Ah OK, maintenant je comprend pkoi le crash avec CString. Je vais sérieusment considerer l'utilisation des tableau fixe TCHAR maintenant.
Ce que je ne comprend pas encore beaucoup c'est cette est affaire des flags..Leur implémentation les rendes atomique et synchronisé vous me dites ?
Ce n'est qu'aujourdhui que je reli une autre chose contre cela :
voila cet article qui m'a été suggéré par Roger :
http://www.flounder.com/no_synchronization.htm[^]
(rechercher la ligne avec l'occurance : a++).
Meme faire des write ou des read sur un bool c'est pas syncronisé par défaut.
OK laisson tomber le détail interne de ces op, si l'incérmentation d'un int ou la mise d'un bool à la valuer vrai est atomique ou non, et regarde mon scénario suivant se basant sur la possibilté de context switch sur les thread :
suppose k'un writer (thread A) accède à name :
iStartCount++;
puis rentre dans :
name=_T("Tunisia");
avant de faire au final :
iEndCount++;
le reader B fait un while sur le code suivant pour voir est ce que
iStartCount==iEndCount :
CString getName()
{
while(true)
{
int iStartCount_localCopy=iStartCount;
CString name_localCopy=name;
int iEndCount_localCopy=iEndCount;
if(iStartCount_localCopy==iEndCount_localCopy)
return name_localCopy;
}
}
B et A peuvent rentrer concuremment dans les deux blocs :
B prend la meme valueur iStartCount positionné par A,
ensuite A lmodifie name, et B prend la valeur corrompue en meme temps que lui,
finalement un context switch se déclenche sur B et donc A a le temps pour rendre iEndCount semblable à iStartCount, ensuite B revient fait la compariason et donc juge que sa copie n'est pas corrompue.
Déjà il y a un scénario très mauvais selon quoi la valeur de iEndCount retenue par B est > que iStartCount, et cela qd le context switch effectué sur B permet à A d'exécuter encore une autre fois le bloc sité, et dans ce cas ma boucle reste infinie.....
Bon biensur ma boucle, peut etre que j'ai maladroitement implémenté votre idée (bien ke meme is B fait une copie de iStartCount et iEndCount avant name, alors il un autre scénario bizarre ici ki peu avoir lieu..
Our Philosophy, Mohammed Baqir Al Sadr
|
|
|
|
|
(I'll switch to english if you don't mind, because it is an international website)
hINTModuleState wrote: Meme faire des write ou des read sur un bool c'est pas syncronisé par défaut.
No, when you have multiple writers you can have a problem when incrementing a variable. Incrementing a variable is done in 3 steps: fetching the value in a registry, incrementing it and putting it back in memory. If two threads try to increment the variable at the same time, you can see the issue I guess (one thread fetches the value, the other one two and then they both increment their local variable).
But, when you have only one writer, you don't have such a problem. Furthermore, as said in the article, reading or writing a 32 bit value is atomic: you fetch it in one step from the memory.
hINTModuleState wrote: B et A peuvent rentrer concuremment dans les deux blocs :
B prend la meme valueur iStartCount positionné par A,
ensuite A lmodifie name, et B prend la valeur corrompue en meme temps que lui,
finalement un context switch se déclenche sur B et donc A a le temps pour rendre iEndCount semblable à iStartCount, ensuite B revient fait la compariason et donc juge que sa copie n'est pas corrompue.
Déjà il y a un scénario très mauvais selon quoi la valeur de iEndCount retenue par B est > que iStartCount, et cela qd le context switch effectué sur B permet à A d'exécuter encore une autre fois le bloc sité, et dans ce cas ma boucle reste infinie.....
Bon biensur ma boucle, peut etre que j'ai maladroitement implémenté votre idée (bien ke meme is B fait une copie de iStartCount et iEndCount avant name, alors il un autre scénario bizarre ici ki peu avoir lieu..
Mmmh, yes it seems that I overlooked something here. I need to think a bit deeper to that.
|
|
|
|
|
hINTModuleState wrote: B et A peuvent rentrer concuremment dans les deux blocs :
B prend la meme valueur iStartCount positionné par A,
ensuite A lmodifie name, et B prend la valeur corrompue en meme temps que lui,
finalement un context switch se déclenche sur B et donc A a le temps pour rendre iEndCount semblable à iStartCount, ensuite B revient fait la compariason et donc juge que sa copie n'est pas corrompue.
Désolé pour la réponse tardive. J'ai un peu réfléchi à la question et en fait une solution c'est d'inverser l'ordre de lecture des flags: le Thread A écrit le flag 1, les données puis le flag2 et le thread B lit le flag2, les données puis le flag1. Si les deux flags sont différents, B relit l'ensemble (donc les deux flags et les données).
|
|
|
|
|
Using Win32 api.
If I double click a file icon, then the file is opened. But how can I retrieve the full path name of this file. This file could be any type such as image or sound or text. Wish someone could help me out!
|
|
|
|
|
The application that opens the file has this information.
"Love people and use things, not love things and use people." - Unknown
"The brick walls are there for a reason...to stop the people who don't want it badly enough." - Randy Pausch
|
|
|
|
|
ice871117 wrote: If I double click a file icon, then the file is opened. But how can I retrieve the full path name of this file.
When the Shell opens a file using the associated application, the path to the file is passed to the application as a command line parameter.
Notepad C:\somefolder\somefile.txt
led mike
|
|
|
|
|
Thanks for led mike's answer
|
|
|
|
|
How about trying the API "GetFullPathName"?
|
|
|
|
|
i have a function all it does it print a CListCtrl to a text file but it is hard to read with all the data
temp.Format("%s %10s %s\r\n", m_list.GetItemText(index, 0), "-", m_list.GetItemText(index, 2));
this works but gives a output like this
some name here - text here
longer name here - text here
even longer name here - text here
short name - text here
what i want is
some name here - text here
longer name here - text here
even longer name here - text here
short name - text here
well the "- text here" should be in a line but i cant get it right here either
can anyone help me fix it ive see how to do it somewhere but cant find it now
|
|
|
|
|
locoone wrote: well the "- text here" should be in a line but i cant get it right here either
can anyone help me fix it ive see how to do it somewhere but cant find it now
Use the <pre> tags:
some name here - text here
longer name here - text here
even longer name here - text here
short name - text here Now if you want your code to produce this, try:
temp.Format("%-28s - %s\r\n", m_list.GetItemText(index, 0), m_list.GetItemText(index, 2));
"Love people and use things, not love things and use people." - Unknown
"The brick walls are there for a reason...to stop the people who don't want it badly enough." - Randy Pausch
|
|
|
|
|
use
temp.Format("%-50s %10s %s\r\n", m_list.GetItemText(index, 0), "-", m_list.GetItemText(index, 2));
May be thi can help you.
-@SuDhIrKuMaR@-
|
|
|
|
|