Archived

This topic is now archived and is closed to further replies.

Memory allocation when multithreading

This topic is 5652 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Guest Anonymous Poster
Allocating memory from one thread to use in another thread in itself is not hard, nor any different from allocation memory normally. Where you may have problems is accessing that memory, this includes reads as well as writes. Consider the following (by the way, NEVER code like this):

(some details left out for brevity)
int *pSomeGlobalData = NULL;

void threadfuncA()
{
if( !pSomeGlobalData )
pSomeGlobalData = new int[MAX_INTEGERS];
}

void threadfuncB()
{
for( i=0; i<MAX_INTEGERS; i++ )
{
pSomeGlobalData++;
sleep(0); // yield to the OS, allow CPU to context switch
}
}

void main(void)
{
HANDLE h1, h2;

h1 = beginthread( ...., threadfuncA, ...);
h2 = beginthread( ...., threadfuncB, ...);
h3 = beginthread(...., threadfuncB, ....);

for( i=0; i<MAX_INTEGERS; i++ )
{
pSomeGlobalData[i]++;
sleep(0); // yield to the OS, allow CPU to context switch
}
}

As you can see from this code that threadfuncA actualy creates the global memory, but threadfuncB and main access. The problem arises when all these threads, both instances of threadfuncB, and the main thread all try to access global or shared memory at once. Consider if the CPU context switched right after a value is moved from memory to a registry value to be incremented, then the next thread completes it''s increment. When the original thread returns to increment the value that is sitting in the register, it does not reflect the actuall value sitting in memory. When it is incremented and stored back in memory, an invalid value results. This can cause you nightmares and migranes galore! Caveat Empor

Share this post


Link to post
Share on other sites
That depends. IS it static? Statis means exists only ONCE. Shares means shared between more than one thread.

There is a semantic difference. For example you could have 4 threads share 2 data areas, with 2 threads accessing each data area. This would NOT constitute a static data area field.

Statis has a specific semantics. Dont reinterpret it.

Thomas Tomiczek
THONA Consulting Ltd.
(Microsoft MVP C#/.NET)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
I''ve used CRITICAL_SECTION objects to lock shared data
Is that what you''re supposed to do?


Yes, that is one way to protect your data. The only caveat being that CS''s are process specific and cannot be shared between processes, but this shouldn''t be a problem for normal use. There is also a handy function, or set of functions, called Interlocked*, where * is either Increment or Decrement. This is the same as this code here:

CRITICAL_SECTION cs;
int g_Index;

void threadfuncA()
{
while( SomeDeterminateFunctionSucceeds() )
{
EnterCriticalSection(cs);
g_Index++
LeaveCriticalSection(cs);
}
}
...
// the above function can be simplified to this
void threadfuncA()
{
while( SomeDeterminateFunctionSucceeds() )
{
InterlockedIncrement(&g_Index);
}
}

The InterlockedIncrement function takes care of protecting your variable. Of course, if you need to do something more complicated than incrementing a variable you have to use some other form of synchronization

quote:

Should shared data be declared as static?



Wheiter it is static or not, you will still need to syncronize access. Static just means that the compiler will make a single copy of the element, provide a memory location on the stack for the data, initialize the data, usually to 0, during program startup, and deallocate the memory during program shutdown. Here is an excerpt directly from MSDN:
quote:

When modifying a variable, the static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified. When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage (its name is not visible from outside the file in which it is declared).

In C++, when modifying a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all the instances of the class. When modifying a member function in a class declaration, the static keyword specifies that the function accesses only static members.


So, static isn''t the answer either. I suggest, IMHO, that you continue using critical sections, as they are the easiest to implement and understand. You may want to read Advanced Windows by Jeff Richter. It has excellent information about multi-threading in general. I have yet to see a game programming book give it justice as it always seems to be relagated to a "oh by the way" appendix or tucked away at the end of some chapter on OS level programming. Anyway, hope this helps and sorry about the wordiness of my response .

Share this post


Link to post
Share on other sites
If you build with the Multi-Threaded libraries, you can safely call all the C & C++ library functions.

Some are safe to call without it, many are not - either due to syncronization issues (like new or delete), or global data issues (like strtok).

So you can call new concurrently from multiple threads, iff you use a thread-safe C/C++ runtime library.

Some early versions of the STL were not thread-safe either (global data issues). Most of the newer ones are - but you still need to syncronize concurrent data access via mutexes (e.g. a Win32 ''critical section'').


Magmai Kai Holmlor

"Oh, like you''ve never written buggy code" - Lee

[Look for information | GDNet Start Here | GDNet Search Tool | GDNet FAQ | MSDN RTF[L] | SGI STL Docs | STFW | Asking Smart Questions ]

[Free C++ Libraries | Boost | ACE | Loki | MTL | Blitz++ | wxWindows| Spirit(xBNF)]

Share this post


Link to post
Share on other sites