Click to See Complete Forum and Search --> : Multithreading


nazgul27
September 23rd, 2005, 03:19 PM
Guys, here is the problem.

CCriticalSection cs;


class Server
{
struct LiveData
{
LiveData () {++id;}
static int id;
};

std::deque <LiveData> deq;
}


// working thread


UINT Thread (LPVOID p)
{

Server* pDlg = (Server*) p;

.........
p->AddLiveData ();
::PostMessage (hwnd, NEW_DATA, 0,0);
}



void SErver::AddLiveData ()
{
LiveData ld;

cs.Lock ();
deq.push_back (ld);
cs.Unlock ();
}

UINT Server::WindowProc (...)
{
case NEW_DATA:

cs.Lock ();

LiveData ld = deq.front ();
deq.pop_front ();

cs.Unlock ();
}



The point is the following: the working thread gets data, calls a funtion from the main thread and the main thread add a new object to the deque. Then the working thread posts a message that new data is available.

The main thread gets LiveData objects one by one starting from the head and removes those objects from the deque.

Each new LiveData object is assigned an ID number which is incremented everytime a new object is created.

On run time I have two list boxes. One is filled with added data (adding new object to the deque) , another is filled with retrieved data (removed from the deque).

Here is the problem. Sometimes I add the objects with the following IDs:

1 2 3 4 5 6 7 8

But the retrieved objects look like:

1 2 3 3 4 5 6 6 7 8

SOME objects are retrieved twice ! Sometimes objects are retrieved like this:

1 2 3 5 6 8 9

SOME objects are missing.

Please help me, what am I doing wrong?

Siddhartha
September 23rd, 2005, 03:21 PM
[ redirected ]

Regards,
Siddhartha

akraus1
September 23rd, 2005, 04:19 PM
The root problem I guess is that during the read operation you do not lock the array. If you delete an item from your list you invalidate the iterators of all readers. For the add operation I am not sure but it could be the case for not ordered collections also.

MikeAThon
September 23rd, 2005, 09:04 PM
Guys, here is the problem....

Each new LiveData object is assigned an ID number which is incremented everytime a new object is created.
I don't see this in your code. I see that the static variable "id" is incremented every time a LiveData object is constructed, but I don't see that the newly-incremented value is somehow stored in the LiveData object. So I don't know what you mean when you say that each new LiveData object has an "assigned" ID.

...SOME objects are missing.
Naturally. As you correctly noticed, the "id" variable is incremented every time LiveData is constructed. This includes stack variables like the one that retrieves a LiveData object in the deq.front() call.
what am I doing wrong?
It's not really clear what you're trying to accomplish. But please note that you are using the Critical section to protect access to the deque, whereas there is no protection to access of the "id" variable. This means that a first thread might have started to construct a LiveData object, got interrupted before it could increment id by a second thread which "corrupted" the value of id, which remains "corrupted" when the first thread is again allowed to execute. By "corrupted" I mean that id has a value that you don't expect, hence the confusion over the results that you are seeing.

You might try protecting acces to "id" with a critical section too. Beware of thread lock

Mike

nazgul27
September 26th, 2005, 08:14 AM
Thanks, I changed the code and added this:


struct LiveData
{
LiveData () {id = ++ iNumber;}

static int iNumber;
int id;
}



now I a real id to an object. But. Objects are added in order, one by one, no problem. But reading thread retrieves the objects not in correct order.

Added objects:

1 2 3 4 5 6

Retrieved objects:

1 2 4 3 6 5

How do I guarantee that objects are retrieved in the same order they have been added? I need that because I send the objects to the clients and the objects must be in order

topper
September 26th, 2006, 01:36 AM
Please help me... I'm new here..

Here is the problem.

A Pthread program that performs the summation function was provided
in C code listing 1.1 below. Rewrite this program in Java.


C code listing 1.1


/**
* A pthread program illustrating how to
* create a simple thread and some of the pthread API
* This program implements the summation function where
* the summation operation is run as a separate thread.
*
* gcc thrd.c -lpthread
*
* Figure 4.6
*
* @author Gagne, Galvin, Silberschatz
* Operating System Concepts - Seventh Edition
* Copyright John Wiley & Sons - 2005.
*/


/* Modified by Krishna Sivalingam - Feb. 2006 */


#include <pthread.h>
#include <stdio.h>


int sum; /* this data is shared by the thread(s) */
double prod; /* this data is shared by the thread(s) */


void *runner1(void *param); /* the thread */
void *runner2(void *param); /* the thread */


int main(int argc, char *argv[])
{
pthread_t tid1, tid2; /* the thread identifier */
pthread_attr_t attr; /* set of attributes for the thread */


if (argc != 2) {
fprintf(stderr,"usage: a.out <integer value>\n");
/*exit(1);*/
return -1;
}


if (atoi(argv[1]) < 0) {
fprintf(stderr,"Argument %d must be non-negative\n",atoi(argv[1]));
/*exit(1);*/
return -1;



}


/* get the default attributes */
pthread_attr_init(&attr);

/* create the thread for summation */
pthread_create(&tid2,&attr,runner2,argv[1]);
pthread_create(&tid1,&attr,runner1,argv[1]);


/* create the thread for factorial */


/* now wait for threads to exit */
pthread_join(tid1,NULL);


pthread_join(tid2,NULL);


printf("sum = %d; prod = %.0lf\n",sum, prod);



}


/**
* The thread will begin control in this function
*/
void *runner1(void *param)
{
int i, upper = atoi(param);
sum = 0; /* Shared global variable. */

if (upper > 0) {
for (i = 1; i <= upper; i++)
sum += i;
}
fprintf(stdout," Thread 1 sez: %.0lf\n", prod);
pthread_exit(0);



}


/**
* The thread will begin control in this function
*/
void *runner2(void *param)
{
int i, upper = atoi(param);
prod = 1.0;

fprintf(stdout," Thread 2: %d\n", sum);
if (upper > 0) {
for (i = 1; i <= upper; i++)
prod *= i;
}


pthread_exit(0);

}

MikeAThon
September 26th, 2006, 10:30 AM
Topper,

Point #1: Start a new thread. It serves no purpose for you to hijack an older thread whose topic is completely unrelated to your own problem.

Point #2: Evidentally, this is a homework assignment. Unless you expend some effort on your own in solving the assignment (which you did not), then it is unlikely that anyone here will help, since such a free-ride defeats the entire purpose of homework. See this FAQ: "Can you help me with my homework assignment?" at http://www.codeguru.com/forum/showthread.php?t=366302&highlight=homework

Mike

TomWidmer
September 26th, 2006, 11:42 AM
If you want the elements to come through sequentially, you need to atomically create the LiveData object and add it to the deque, otherwise you can have the case where you create the LiveData object, another thread jumps in and creates theirs (with a higher id), but manages to add it to the deque first (all this ignores the additional problem that the id isn't incremented atomically, using InterlockedIncrement). The solution is extremely simple:

void SErver::AddLiveData ()
{
cs.Lock ();
LiveData ld;
deq.push_back (ld);
cs.Unlock ();
}

karal
October 27th, 2006, 12:59 AM
multithreading is not an easy task. good luck