Hello,
The aim is to add records to a linked list, from a function that runs that perpetually in a separate thread and have the contents of the linked_list accessible from multiple threads - rather than just the add_records thread.
Consider the following code;
- this code does not have a linked list
- but the code is able to pass values (via a global structure) between two threads
- this code works
- and has formed the basis of my approach with the linked list version below which unfortunately doesn't work
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct arg_struct
{
int arg1;
int arg2;
} *args;
void *print_the_arguments(void *arguments)
{
struct arg_struct *args = arguments;
printf("Thread before\n");
printf("%d\n", args->arg1);
printf("%d\n", args->arg2);
printf("\n");
args->arg1 = args->arg1 + 10;
args->arg2 = args->arg2 + 10;
printf("Thread after\n");
printf("%d\n", args->arg1);
printf("%d\n", args->arg2);
printf("\n");
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t some_thread;
args = malloc(sizeof(struct arg_struct) * 1);
args->arg1 = 5;
args->arg2 = 7;
printf("Before\n");
printf("%d\n", args->arg1);
printf("%d\n", args->arg2);
printf("\n");
if (pthread_create(&some_thread, NULL, &print_the_arguments, args) != 0)
{
printf("print_the_arguments thread failed!\n");
return -1;
}
pthread_join(some_thread, NULL); // Wait until thread is finished
printf("After\n");
printf("%d\n", args->arg1);
printf("%d\n", args->arg2);
printf("\n");
return 0;
}
Consider the following the code;
- this code executes the add_records function in a separate thread
- the add_records function then add records to the linked list
- in this example the add_records function also reports the contents of the linked list to demonstrate that the code to populate the linked list does work
- this code doesn't accomplish my objective however, which is to add records to the linked_list in a separate thread; but then also access the linked_list from another thread (e.g. main)
Code:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h> // sleep
#include <pthread.h>
#include <time.h>
#define FALSE 0
struct record
{
int arg1;
int arg2;
};
typedef struct record record_t;
struct linked_list
{
struct record *record;
struct linked_list *prev;
struct linked_list *next;
};
typedef struct linked_list linked_list_t;
linked_list_t *add_at(int pos, linked_list_t *linked_list, record_t *record)
{
linked_list_t *node = malloc(sizeof(linked_list_t) * 1);
if (node == NULL)
{
printf("Malloc failed in node: add_at\n");
getchar();
}
node->record = malloc(sizeof(record_t) * 1);
if (node->record == NULL)
{
printf("Malloc failed in: add_at: node->record\n");
getchar();
}
node->record->arg1 = record->arg1;
node->record->arg2 = record->arg2;
node->prev = NULL;
node->next = NULL;
// handle case where linked_list is empty
if (linked_list == NULL)
{
linked_list = node;
return linked_list;
}
int idx = 0;
linked_list_t *prev = NULL;
linked_list_t *cur = linked_list;
// walk through linked_list until pos or end is reached
while (cur != NULL && idx != pos)
{
++idx;
prev = cur;
cur = cur->next;
}
// insertion point reached
// beginning, includes linked_list update
if (idx == 0)
{
linked_list = node;
node->next = cur;
cur->prev = node;
return linked_list;
}
// end
if (cur == NULL)
{
prev->next = node;
node->prev = prev;
return linked_list;
}
// middle
prev->next = node;
node->prev = prev;
node->next = cur;
cur->prev = node;
return linked_list;
} // add_at
linked_list_t *add_beg(linked_list_t *linked_list, record_t *record)
{
linked_list = add_at(0, linked_list, record);
return linked_list;
} // add_beg
void dump_fwd(linked_list_t *linked_list)
{
printf("Forward:\n");
printf("--------\n");
while (linked_list != NULL)
{
printf("Arg1: %d\n", linked_list->record->arg1);
printf("Arg2: %d\n", linked_list->record->arg2);
printf("\n");
linked_list = linked_list->next;
}
} // dump_fwd
void *add_records(void *arguments)
{
// Initialise linked_list
linked_list_t *linked_list = malloc(sizeof(linked_list_t) * 1);
if (linked_list == NULL)
{
printf("Malloc failed in: linked_list\n");
getchar();
}
linked_list = NULL;
// Initialise record
record_t *record = malloc(sizeof(record_t) * 1);
if (record == NULL)
{
printf("Malloc failed in: record\n");
getchar();
}
// Create record
record->arg1 = 10;
record->arg2 = 15;
// Add record to linked_list
linked_list = add_beg(linked_list,record);
// Display linked_list
dump_fwd(linked_list);
// Create record
record->arg1 = 20;
record->arg2 = 25;
// Add record to linked_list
linked_list = add_beg(linked_list,record);
// Display linked_list
dump_fwd(linked_list);
pthread_exit(NULL);
return NULL;
} // add_records
int main()
{
pthread_t tid_add_records;
if (pthread_create(&tid_add_records, NULL, &add_records, NULL) != 0)
{
printf("add_records thread failed!\n");
return -1;
}
// Wait until thread is finished
pthread_join(tid_add_records, NULL);
return 0;
}
Consider the following code;
- this is an attempt to combine the first two examples
- separate thread to execute the add_records function
- display the contents of the linked_list from main to demonstrate that the linked_list is accessible from multiple threads
- however the calls to dump_fwd(linked_list) in main do not report any details. So there is a problem with the logic somewhere.
- like the previous example, I call dump_fwd_II(linked_list) from within add_records to confirm that the linked_list is being updated within the add_records function. But it is as if the linked_list is a local variable
Code:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h> // sleep
#include <pthread.h>
#include <time.h>
#define FALSE 0
struct record
{
int arg1;
int arg2;
};
typedef struct record record_t;
struct linked_list
{
struct record *record;
struct linked_list *prev;
struct linked_list *next;
} *add_records_args;
typedef struct linked_list linked_list_t;
linked_list_t *add_at(int pos, linked_list_t *linked_list, record_t *record)
{
linked_list_t *node = malloc(sizeof(linked_list_t) * 1);
if (node == NULL)
{
printf("Malloc failed in node: add_at\n");
getchar();
}
node->record = malloc(sizeof(record_t) * 1);
if (node->record == NULL)
{
printf("Malloc failed in: add_at: node->record\n");
getchar();
}
node->record->arg1 = record->arg1;
node->record->arg2 = record->arg2;
node->prev = NULL;
node->next = NULL;
// handle case where linked_list is empty
if (linked_list == NULL)
{
linked_list = node;
return linked_list;
}
int idx = 0;
linked_list_t *prev = NULL;
linked_list_t *cur = linked_list;
// walk through linked_list until pos or end is reached
while (cur != NULL && idx != pos)
{
++idx;
prev = cur;
cur = cur->next;
}
// insertion point reached
// beginning, includes linked_list update
if (idx == 0)
{
linked_list = node;
node->next = cur;
cur->prev = node;
return linked_list;
}
// end
if (cur == NULL)
{
prev->next = node;
node->prev = prev;
return linked_list;
}
// middle
prev->next = node;
node->prev = prev;
node->next = cur;
cur->prev = node;
return linked_list;
} // add_at
linked_list_t *add_beg(linked_list_t *linked_list, record_t *record)
{
linked_list = add_at(0, linked_list, record);
return linked_list;
} // add_beg
void dump_fwd(linked_list_t *linked_list)
{
printf("Forward:\n");
printf("--------\n");
while (linked_list != NULL)
{
printf("Arg1: %d\n", linked_list->record->arg1);
printf("Arg2: %d\n", linked_list->record->arg2);
printf("\n");
linked_list = linked_list->next;
}
} // dump_fwd
void dump_fwd_II(linked_list_t *linked_list)
{
printf("Forward from within thread:\n");
printf("---------------------------\n");
while (linked_list != NULL)
{
printf("Arg1: %d\n", linked_list->record->arg1);
printf("Arg2: %d\n", linked_list->record->arg2);
printf("\n");
linked_list = linked_list->next;
}
} // dump_fwd_II
void *add_records(void *arguments)
{
struct linked_list *linked_list = arguments;
// Initialise record
record_t *record = malloc(sizeof(record_t) * 1);
if (record == NULL)
{
printf("Malloc failed in: record\n");
getchar();
}
// Create record
record->arg1 = 10;
record->arg2 = 15;
// Add record to linked_list
linked_list = add_beg(linked_list,record);
// Display linked_list
dump_fwd_II(linked_list);
sleep(5);
// Create record
record->arg1 = 20;
record->arg2 = 25;
// Add record to linked_list
linked_list = add_beg(linked_list,record);
// Display linked_list
dump_fwd_II(linked_list);
pthread_exit(NULL);
return NULL;
} // add_records
int main()
{
int done;
done = FALSE;
pthread_t tid_add_records;
// Initialise linked_list
linked_list_t *linked_list = malloc(sizeof(linked_list_t) * 1);
if (linked_list == NULL)
{
printf("Malloc failed in: linked_list\n");
getchar();
}
linked_list = NULL;
add_records_args = linked_list;
if (pthread_create(&tid_add_records, NULL, &add_records, add_records_args) != 0)
{
printf("add_records thread failed!\n");
return -1;
}
while (!done)
{
sleep(2);
// Display linked_list
dump_fwd(linked_list);
sleep(8);
// Display linked_list
dump_fwd(linked_list);
break;
}
// Wait until thread is finished
pthread_join(tid_add_records, NULL);
return 0;
}