Pthread: Increasing program execution time with respect to number of threads - c

I am trying to build an efficient concurrent hash map using pthreads, C.
Following is my implementation
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <stdint.h>
#include <limits.h>
#include <stdio.h>
#include <linux/limits.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#define ENTRIES_PER_BUCKET 3
struct Bucket
{
pthread_mutex_t mutex;
void **keys;
int *vals;
struct Bucket *next;
};
struct Concurrent_Map
{
struct Bucket *buckets;
map_keys_equality *keys_eq;
map_key_hash *khash;
int capacity;
};
int concurrent_map_allocate /*# <t> #*/ (map_keys_equality *keq, map_key_hash *khash,
unsigned capacity,
struct Concurrent_Map **map_out)
{
struct Concurrent_Map *old_map_val = *map_out;
struct Concurrent_Map *map_alloc = malloc(sizeof(struct Concurrent_Map));
if (map_alloc == NULL)
{
return 0;
}
*map_out = (struct Concurrent_Map *)map_alloc;
struct Bucket *buckets_alloc = (struct Bucket *)malloc(sizeof(struct Bucket) * (int)capacity);
if (buckets_alloc == NULL)
{
free(map_alloc);
*map_out = old_map_val;
return 0;
}
(*map_out)->buckets = buckets_alloc;
(*map_out)->capacity = capacity;
(*map_out)->keys_eq = keq;
(*map_out)->khash = khash;
unsigned i;
for (i = 0; i < capacity; i++)
{
if (pthread_mutex_init(&((*map_out)->buckets[i].mutex), NULL) == 0)
{
void **key_alloc = malloc(sizeof(void *) * (ENTRIES_PER_BUCKET));
if (key_alloc != NULL)
{
(*map_out)->buckets[i].keys = key_alloc;
int k;
for (k = 0; k < ENTRIES_PER_BUCKET; k++)
{
(*map_out)->buckets[i].keys[k] = NULL;
}
}
int *vals_alloc = malloc(sizeof(int) * (ENTRIES_PER_BUCKET));
if (vals_alloc != NULL)
{
(*map_out)->buckets[i].vals = vals_alloc;
int k;
for (k = 0; k < ENTRIES_PER_BUCKET; k++)
{
(*map_out)->buckets[i].vals[k] = -1;
}
}
(*map_out)->buckets[i].next = NULL;
}
}
// todo exceptions in allocation
return 1;
}
static unsigned loop(unsigned k, unsigned capacity)
{
unsigned g = k % capacity;
unsigned res = (g + capacity) % capacity;
return res;
}
int concurrent_map_get(struct Concurrent_Map *map, void *key, int *value_out)
{
map_key_hash *khash = map->khash;
unsigned hash = khash(key);
unsigned start = loop(hash, map->capacity);
unsigned bucket_index = loop(start + 0, map->capacity);
if (bucket_index < map->capacity)
{
struct Bucket *bucket = &(map->buckets[bucket_index]);
pthread_mutex_t mutex = bucket->mutex;
pthread_mutex_lock(&mutex);
int j;
do
{
for (j = 0; j < ENTRIES_PER_BUCKET; j++)
{
int val = bucket->vals[j];
if (map->keys_eq(bucket->keys[j], key))
{
if (bucket->vals[j] == val)
{
*value_out = val;
return 1;
}
else
{
*value_out = -1;
return 0;
}
}
}
if (bucket->next != NULL)
{
bucket = (bucket->next);
}
else
{
break;
pthread_mutex_unlock(&mutex);
}
pthread_mutex_unlock(&mutex);
} while (1);
}
*value_out = -1;
return 0;
}
int concurrent_map_put(struct Concurrent_Map *map, void *key, int value)
{
map_key_hash *khash = map->khash;
unsigned hash = khash(key);
unsigned start = loop(hash, map->capacity);
unsigned bucket_index = loop(start + 0, map->capacity);
struct Bucket *bucket = &(map->buckets[bucket_index]);
int j;
do
{
pthread_mutex_t mutex = bucket->mutex;
int j;
pthread_mutex_lock(&mutex);
for (j = 0; j < ENTRIES_PER_BUCKET; j++)
{
if (map->keys_eq(bucket->keys[j], key))
{
pthread_mutex_unlock(&mutex);
return 0;
}
else if (bucket->keys[j] == NULL)
{
bucket->vals[j] = value;
bucket->keys[j] = key;
pthread_mutex_unlock(&mutex);
return 1;
}
}
if (bucket->next == NULL)
{
// allocate a new bucket
struct Bucket *new_bucket = malloc(sizeof(struct Bucket));
if (pthread_mutex_init(&(new_bucket->mutex), NULL) == 0)
{
void **key_alloc = malloc(sizeof(void *) * (ENTRIES_PER_BUCKET));
if (key_alloc != NULL)
{
new_bucket->keys = key_alloc;
int k;
for (k = 0; k < ENTRIES_PER_BUCKET; k++)
{
new_bucket->keys[k] = NULL;
}
}
int *vals_alloc = malloc(sizeof(int) * (ENTRIES_PER_BUCKET));
if (vals_alloc != NULL)
{
new_bucket->vals = vals_alloc;
int k;
for (k = 0; k < ENTRIES_PER_BUCKET; k++)
{
new_bucket->vals[k] = -1;
}
}
bucket->next = new_bucket;
}
}
pthread_mutex_unlock(&mutex);
bucket = bucket->next;
} while (1);
return 0;
}
int concurrent_map_erase(struct Concurrent_Map *map, void *key, void **trash)
{
map_key_hash *khash = map->khash;
unsigned hash = khash(key);
unsigned start = loop(hash, map->capacity);
unsigned bucket_index = loop(start + 0, map->capacity);
struct Bucket *bucket = &(map->buckets[bucket_index]);
int j;
do
{
pthread_mutex_t mutex = bucket->mutex;
int j;
pthread_mutex_lock(&mutex);
for (j = 0; j < ENTRIES_PER_BUCKET; j++)
{
if (map->keys_eq(bucket->keys[j], key))
{
bucket->vals[j] = -1;
bucket->keys[j] = NULL;
pthread_mutex_unlock(&mutex);
return 1;
}
}
pthread_mutex_unlock(&mutex);
if (bucket->next != NULL)
{
bucket = (bucket->next);
}
else
{
break;
}
} while (1);
return 0;
}
int concurrent_map_size(struct Concurrent_Map *map)
{
int num_buckets = 0;
struct Bucket *buckets = map->buckets;
unsigned i;
for (i = 0; i < map->capacity; i++)
{
struct Bucket bucket = buckets[i];
do
{
num_buckets++;
if (bucket.next != NULL)
{
bucket = *(bucket.next);
}
else
{
break;
}
} while (1);
}
return num_buckets * ENTRIES_PER_BUCKET;
}
struct FlowId
{
int src_port;
int dst_port;
int src_ip;
int dst_ip;
int internal_device;
int protocol;
};
bool FlowId_eq(void *a, void *b)
{
if (a == NULL || b == NULL)
{
return false;
}
struct FlowId *id1 = a;
struct FlowId *id2 = b;
return (id1->src_port == id2->src_port) && (id1->dst_port == id2->dst_port) && (id1->src_ip == id2->src_ip) && (id1->dst_ip == id2->dst_ip) && (id1->internal_device == id2->internal_device) && (id1->protocol == id2->protocol);
}
unsigned FlowId_hash(void *obj)
{
struct FlowId *id = obj;
unsigned hash = 0;
hash = __builtin_ia32_crc32si(hash, id->src_port);
hash = __builtin_ia32_crc32si(hash, id->dst_port);
hash = __builtin_ia32_crc32si(hash, id->src_ip);
hash = __builtin_ia32_crc32si(hash, id->dst_ip);
hash = __builtin_ia32_crc32si(hash, id->internal_device);
hash = __builtin_ia32_crc32si(hash, id->protocol);
return hash;
}
struct Concurrent_Map *concurrent_map;
#define NUM_THREADS 2
#define NUM_PACKETS 10000000
void *expirator(void *arg)
{
// printf("Thread started executing\n");
unsigned i = 0;
int error = 0;
unsigned packet_count = NUM_PACKETS / NUM_THREADS;
while (i < packet_count)
{
i++;
struct FlowId *id = malloc(sizeof(struct FlowId));
struct FlowId *id1 = malloc(sizeof(struct FlowId));
id->dst_ip = 1;
id->src_ip = 1;
id->internal_device = 1;
id->protocol = 1;
id->src_port = 1;
id->dst_port = rand() % 65536;
id1->dst_ip = 1;
id1->src_ip = 1;
id1->internal_device = 1;
id1->protocol = 1;
id1->src_port = 1;
id1->dst_port = rand() % 65536;
int external_port = rand() % 65536;
int external;
concurrent_map_erase(concurrent_map, id, NULL);
concurrent_map_put(concurrent_map, id, external_port);
concurrent_map_get(concurrent_map, id, &external);
if (external_port != external)
{
error++;
}
else
{
}
}
return NULL;
}
int main()
{
clock_t begin = clock();
concurrent_map_allocate(FlowId_eq, FlowId_hash, 65536, &(concurrent_map));
pthread_t *threads = malloc(sizeof(pthread_t) * NUM_THREADS);
int i;
for (i = 0; i < NUM_THREADS; i++)
{
if (pthread_create(&threads[i], NULL, expirator, NULL) != 0)
{
printf("Error creating threads");
exit(0);
}
}
for (i = 0; i < NUM_THREADS; i++)
{
if (pthread_join(threads[i], NULL) != 0)
{
printf("Error joining threads");
exit(0);
}
}
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("%lf\n", time_spent);
return 0;
}
Here is how to run this program.
gcc concurrent_map.c -o test-concurrent-new -lpthread -msse4.2 -O3
Then I measure the execution time for a fixed workload and following are the time values I observed.
1: 3.29
2: 6.687811
3: 5.88
4: 6.23
5: 6.38
6: 6.52
7: 6.74
8: 6.82
It seems that when the number of threads is increased the execution time increases and remains almost same.
I profiled this code using Mutrace, which looks for mutex contention. It turns out that
No mutex contended according to filtering parameters.
I checked the number of cache misses, and it turned out that number of cache misses are roughly equal when the number of threads is modified.
Why does not the execution time decrease when the number of threads increase?
I am running this on a 32 core machine

rand() is usually not suited for multi threaded execution. Instead use rand_r().
Also use linux time tool for timing the application.
Your workload generation imposes a huge overhead, and I assume it is the bottleneck here, not the concurrent hash map

Related

priority queue utilizing a heap working except for freeC

I have my priority queue working and printing as I expected it to, but the free is invalid and I'm not sure why, i'm following all the protocols for the heap that I have learned so far, but my program will not finish.
#include <stdlib.h>
#include "priority_queue.h"
struct item{
int priority;
int value;
};
typedef struct item Item;
struct priority_queue{
int size;
int capacity;
int front;
Item* data;
};
typedef struct priority_queue Priority_queue;
void priority_queue_fix_down(PRIORITY_QUEUE hQueue, int index, int size);
PRIORITY_QUEUE priority_queue_init_default(void){
Priority_queue* pQueue_ptr;
pQueue_ptr = (Priority_queue*)malloc(sizeof(Priority_queue));
if(pQueue_ptr != NULL){
pQueue_ptr->size = 0;
pQueue_ptr->capacity = 1;
pQueue_ptr->data = (Item*)malloc(sizeof(Item)*pQueue_ptr->capacity);
if (pQueue_ptr->data == NULL){
free(pQueue_ptr);
pQueue_ptr = NULL;
}
}
return pQueue_ptr;
}
Status priority_queue_insert(PRIORITY_QUEUE hQueue, int priority_level, int data_item)
{
Priority_queue* pQueue_ptr = (Priority_queue*)hQueue;
Item* temp, temp2;
//temp = (Item*)malloc(sizeof());
int i;
if (pQueue_ptr->size >= pQueue_ptr->capacity)
{
//not enough space
temp = (Item*)malloc(sizeof(Item) * 2 * pQueue_ptr->capacity);
if (temp == NULL)
{
return FAILURE;
}
for (i = 0; i < pQueue_ptr->size; i++)
{
temp[i] = pQueue_ptr->data[i];
}
pQueue_ptr->front = 0;
pQueue_ptr->capacity *= 2;
free(pQueue_ptr->data);
pQueue_ptr->data = temp;
}
i = pQueue_ptr->size;
(pQueue_ptr->data[i]).priority = priority_level;
(pQueue_ptr->data[i]).value = data_item;
int index_of_parent;
index_of_parent = (i - 1) / 2;
while (i >= 1 && ((pQueue_ptr->data[i]).priority > (pQueue_ptr->data[index_of_parent]).priority))
{
temp2 = pQueue_ptr->data[index_of_parent];
pQueue_ptr->data[index_of_parent] = pQueue_ptr->data[i];
pQueue_ptr->data[i] = temp2;
i = index_of_parent;
index_of_parent = (i - 1) / 2;
}
pQueue_ptr->size++;
// pQueue_ptr->front = 0;
// pQueue_ptr->back = pQueue_ptr->size-1;
return SUCCESS;
}
void print_heap(PRIORITY_QUEUE hQueue){
Priority_queue* pQueue_ptr = (Priority_queue*) hQueue;
for(int x = 0; x<pQueue_ptr->size;x++){
printf("%d\n", pQueue_ptr->data[x].priority);
}
}
Status priority_queue_service(PRIORITY_QUEUE hQueue){
//set variables
Priority_queue* pQueue_ptr = (Priority_queue*) hQueue;
Item temp;
int size, index, index_left_child, index_right_child;
if(pQueue_ptr->size == 0){
return FAILURE;
}
index = 0;
temp = pQueue_ptr->data[0];
pQueue_ptr->data[0] = pQueue_ptr->data[pQueue_ptr->size-1];
pQueue_ptr->data[size-1] = temp;
pQueue_ptr->size--;
priority_queue_fix_down(pQueue_ptr, pQueue_ptr->front, pQueue_ptr->size);
return SUCCESS;
}
int priority_queue_front(PRIORITY_QUEUE hQueue, Status* status)
{
Priority_queue* pPriority_queue = (Priority_queue*)hQueue;
if (priority_queue_is_empty(pPriority_queue))
{
if (status != NULL)
{
*status = FAILURE;
}
return 0;
}
if (status != NULL)
{
*status = SUCCESS;
}
return (pPriority_queue->data[pPriority_queue->front]).value;
}
Boolean priority_queue_is_empty(PRIORITY_QUEUE hQueue){
Priority_queue* pQueue_ptr = (Priority_queue*) hQueue;
if (pQueue_ptr->size <= 0)
return TRUE;
else
return FALSE;
}
This is where I get the error when debugging, on free(pPriority_queue->data); It doesn't even reach the line below. I tried taking someone elses "service" function and it worked, but they implemented "fix down" in their service function, while I'm trying to do it outside in a separate function.
void priority_queue_destroy(PRIORITY_QUEUE* phQueue){
Priority_queue* pPriority_queue = (Priority_queue*)*phQueue;
free(pPriority_queue->data);
free(*phQueue);
// *phQueue = NULL;
return;
}
void priority_queue_fix_down(PRIORITY_QUEUE hQueue, int index, int size){
Priority_queue* pQueue_ptr = (Priority_queue*) hQueue;
Item* temp;
temp = (Item*)malloc(sizeof(Item));
if (temp == NULL)
return NULL;
//int front = priority_queue_front(pQueue_ptr, NULL);
int index_left_child = 2* index + 1;
int index_right_child = 2* index + 2;
// print_heap(pQueue_ptr);
// printf("\nsize: %d\nindex: %d\n", size, index);
// // printf("Front: %d\n", pQueue_ptr->data[0]);
// if(pQueue_ptr->data[index_left_child].priority > (pQueue_ptr->data[index]).priority){
// printf("Left child index %d\nRight child index: %d\nLeft child has highest priority of: %d\n",index_left_child, index_right_child, pQueue_ptr->data[index_left_child].priority);
// }
// else
// printf("Right child index: %d\nLeft child index %d\nRight child has highest priority of: %d\n",index_right_child, index_left_child, pQueue_ptr->data[index_right_child].priority);
if (index_left_child < size){
if (index_right_child < size && pQueue_ptr->data[index_right_child].priority > (pQueue_ptr->data[index_left_child]).priority){
if(pQueue_ptr->data[index_right_child].priority > (pQueue_ptr->data[index]).priority){
*temp = pQueue_ptr->data[index];
pQueue_ptr->data[index] = pQueue_ptr->data[index_right_child] ;
pQueue_ptr->data[index_right_child] = *temp;
priority_queue_fix_down(pQueue_ptr, index_right_child, size);
}
}
if(pQueue_ptr->data[index_left_child].priority > (pQueue_ptr->data[index]).priority){
*temp = pQueue_ptr->data[index];
pQueue_ptr->data[index] = pQueue_ptr->data[index_left_child];
pQueue_ptr->data[index_left_child] = *temp;
priority_queue_fix_down(pQueue_ptr, index_left_child, size);
}
}
}

Getting a segmentation fault error on an Open Addressing Hash Map?

I'm getting a segmentation fault error somewhere in my insert function. It says that its due to one of the 'strcmp' comparisons but i cant find the issue after looking at all of them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define INITIAL_CAPACITY 8
typedef struct node
{
unsigned int val;
char *key;
bool del;
} Node;
typedef Node * NodePtr;
typedef struct hashMap
{
NodePtr array;
size_t capacity;
size_t size;
} HashMap;
typedef HashMap * HMPtr;
//|-------------------------
HMPtr create();
void insert(HMPtr map, char *str);
//y
void resize_insert(HMPtr map, char *str);
//y
void print(HMPtr map);
void destroy(HMPtr *mapPtr);
void resize(HMPtr map);
//y
unsigned int hash(char *str);
//y
unsigned int pop(HMPtr map, char *key);
//y
//|-------------------------
int main(void)
{
HMPtr map = create();
insert(map, "Keathan");
insert(map, "Trey");
insert(map, "Noah");
insert(map, "Kleiner");
insert(map, "data");
insert(map, "Matthew");
print(map);
destroy(&map);
return 0;
}
unsigned int pop(HMPtr map, char *str)
{
unsigned int val = hash(str);
size_t h = (size_t)val;
size_t index = h % map->capacity;
for(size_t i = 0; map->array[index].key && strcmp(str, map->array[index].key);index = (h + ((++i) + i*i)/2)%map->capacity);
if (map->array[index].key)
{
map->array[index].del = true;
return map->array[index].val;
}
return 0;
}
unsigned int hash(char *str)
{
unsigned int out = 0;
unsigned int base = 31;
unsigned int factor = 1;
for (size_t i = 0; str[i] != 0; ++i)
{
out += (unsigned int)str[i] * factor;
factor *= base;
}
return out;
}
void resize(HMPtr map)
{
NodePtr old = map->array;
size_t old_capacity = map->capacity;
map->capacity = old_capacity * 2;
map->array = calloc(map->capacity, sizeof(Node));
for(size_t i = 0; i < old_capacity; ++i)
{
if(old[i].key)
{
if(old[i].del)
free(old[i].key);
else
resize_insert(map, old[i].key);
}
}
free(old);
}
void resize_insert(HMPtr map, char *str)
{
unsigned int val = hash(str);
size_t h = (size_t)val;
size_t index = h % map->capacity;
for (size_t i = 0; map->array[index].key; index = (h + ((++i) + i*i)/2)%map->capacity);
map->array[index].key = str;
map->array[index].val = val;
++(map->size);
}
void insert(HMPtr map, char *str)
{
unsigned int val = hash(str);
size_t h = (size_t)val;
size_t index = h % map->capacity;
size_t i;
NodePtr deleted = NULL;
for(i = 0; map->array[index].key && strcmp(str, map->array[index].key);index = (h + ((++i) + i*i)/2)%map->capacity)
if(!deleted && map->array[index].del)
{
deleted = map->array + index;
for(index = (h + ((++i) + i*i)/2)%map->capacity; map->array[index].key && strcmp(str, map->array[index].key); index = (h + ((++i) + i*i)/2)%map->capacity);
break;
}
if (map->array[index].key == NULL)
{
if(deleted)
{
free(deleted->key);
deleted->del = false;
index = deleted - map->array;
}
else if (++(map->size) >= 0.7*map->capacity)
{
resize(map);
index = h % map->capacity;
for (i = 0; map->array[index].key; index = (h + ((++i) + i*i)/2)%map->capacity);
}
map->array[index].key = calloc(strlen(str)+1, sizeof(char));
strcpy(map->array[index].key, str);
}
else
map->array[index].val = val;
}
HMPtr create()
{
HMPtr newList = malloc(sizeof(HashMap));
newList->size = 0;
newList->capacity = INITIAL_CAPACITY;
newList->array = calloc(newList->capacity, sizeof(NodePtr));
return newList;
}
void destroy(HMPtr *mapPtr)
{
free((*mapPtr)->array);
free(*mapPtr);
*mapPtr = NULL;
}
void print(HMPtr map)
{
for (size_t i = 0; i < map->capacity; ++i)
printf("%s;%u\n", map->array[i].key, map->array[i].val);
}
This is the Error i recieved after running on gdb
'''
Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse2_unaligned ()
at ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S:30
30 ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: No such file or
directory.
'''
If anyone could spot the issue then that would help a lot. Thanks!
sizeof(nodePtr) is size of pointer you need sizeof(struct Node)
HMPtr create()
{
HMPtr newList = malloc(sizeof(HashMap));
newList->size = 0;
newList->capacity = INITIAL_CAPACITY;
newList->array = calloc(newList->capacity, sizeof(*newList->array));
return newList;
}

Create variable amount of struct objects inside a struct (C)

I haven't written any C for more than a decade, but here I am...
I want to be able to create and access the following items of a data structure:
FilterCoefficients[0].TargetSampleNum = 0;
FilterCoefficients[0].SourceWeights[0].Weight = 0.812;
FilterCoefficients[0].SourceWeights[0].SourceSampleNum = 0;
FilterCoefficients[0].SourceWeights[1].Weight = 0.153;
FilterCoefficients[0].SourceWeights[1].SourceSampleNum = 1;
FilterCoefficients[1].TargetSampleNum = 1;
FilterCoefficients[1].SourceWeights[0].Weight = 0.352;
FilterCoefficients[1].SourceWeights[0].SourceSampleNum = 0;
FilterCoefficients[1].SourceWeights[1].Weight = 0.721;
FilterCoefficients[1].SourceWeights[1].SourceSampleNum = 1;
[...]
The indices have to be dynamically allocated (amount of needed space changes during runtime). I am attempting to create said data structure with the following:
typedef struct SampleWeight_t
{
unsigned long SourceSampleNum;
double Weight;
} SampleWeight;
typedef struct FilterCoefficients_t
{
unsigned long TargetSampleNum;
SampleWeight* SourceWeights;
} FilterCoefficients;
However, I am having difficulties creating the structure. I am getting Break Point exceptions when malloc-ing or free-ing the structure.
FilterCoefficients* FilterCoefficients;
SampleWeight* SampleWeight;
FilterCoefficients = malloc(sizeof(FilterCoefficients) * target_width);
if (FilterCoefficients == NULL) {
//errhandler
}
for (int i = 0; i < target_width; i++) {
FilterCoefficients[i].SourceWeights = malloc(sizeof(SampleWeight) * (int)ceil(scalingFactorWidth * window_width)); // **exception usually here**
if (FilterCoefficients[i].SourceWeights == NULL) {
//errhandler
}
FilterCoefficients[i].TargetSampleNum = i;
for (int j = i - filter_width; j < i + filter_width; j++) {
FilterCoefficients[i].SourceWeights[j + filter_width].Weight = bilinear_filter(0.5 + scalingFactorWidth2 * (j - 0.5));
if (j > 0) {
FilterCoefficients[i].SourceWeights[j + filter_width].SourceSampleNum = j;
}
else {
FilterCoefficients[i].SourceWeights[j + filter_width].SourceSampleNum = 0;
}
}
}
for (int i = 0; i < target_width; i++) {
free(FilterCoefficients[i].SourceWeights); // **exception usually here**
}
free(FilterCoefficients);
Any help which is gonna point me to a solution is appreciated.
This compiles and executes. I had to simplify.
#include <stdio.h>
#include <stdlib.h>
typedef struct SampleWeight_t
{
unsigned long SourceSampleNum;
double Weight;
} SampleWeight;
typedef struct FilterCoefficients_t
{
unsigned long TargetSampleNum;
SampleWeight* SourceWeights;
} FilterCoefficients;
int main ( void) {
FilterCoefficients* FilterCoeff;
int window_width = 35;
int target_width = 55;
FilterCoeff = malloc(sizeof(FilterCoefficients) * target_width);
if (FilterCoeff == NULL) {
//errhandler
}
for (int i = 0; i < target_width; i++) {
FilterCoeff[i].SourceWeights = malloc(sizeof(SampleWeight) * window_width);
if (FilterCoeff[i].SourceWeights == NULL) {
//errhandler
}
FilterCoeff[i].TargetSampleNum = i;
for (int j = 0; j < window_width; j++) {
FilterCoeff[i].SourceWeights[j].Weight = i * j;
if (j > 0) {
FilterCoeff[i].SourceWeights[j].SourceSampleNum = j;
}
else {
FilterCoeff[i].SourceWeights[j].SourceSampleNum = 0;
}
}
}
for (int i = 0; i < target_width; i++) {
free(FilterCoeff[i].SourceWeights); // **exception usually here**
}
free(FilterCoeff);
}

VS17 not initializing pointer

My problem is that this code is not working in VS 2017 while in CLion it works.
VS says:
Severity Code Description Project File Line Suppression State
Error (active) E0144
a value of type void * cannot be used to initialize an entity of type queue_t*
therefor the program is not allocating the memory.
Further every pointer like the example above is not working.
Does somebody here know why that is the case, why VS thinks that this would be a void?
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
struct packet_t {
double d;
int i;
long l;
char *p;
struct queue_t *queue;
};
struct queue_t {
char *name;
int size;
int entries;
double time;
struct packet_t **packets;
int read;
int write;
long lost;
long total;
};
int decision = -1;
int isRunning = 1;
void logError(char message[]) {
printf("ERROR: %s", message);
}
struct queue_t *queue_create(char *name, int size) {
struct queue_t *q = malloc(sizeof(struct queue_t));
if (!q) {
logError("could not allocate memory!\n");
return 0;
}
else {
q->name = name;
q->size = size;
q->entries = 0;
q->read = 0;
q->write = 0;
q->total = 0;
q->lost = 0;
q->packets = malloc(size * sizeof(struct packet_t *));
if (!q->packets) {
logError("could not allocate memory!\n");
free(q);
return 0;
}
struct packet_t **current;
for (int i = 0; i < size; i++) {
current = q->packets + i;
*current = NULL;
}
}
return q;
}
int packet_destroy(struct packet_t *packet) {
//TODO test if deleted ?
if (packet) {
free(packet);
return 1;
}
return 0;
}
long queue_store(struct queue_t *queue, struct packet_t *packet) {
if (queue->entries < queue->size) {
packet->queue = queue;
*(queue->packets + queue->write) = packet;
queue->write++;
if (queue->write == queue->size) {
queue->write = 0;
}
queue->total++;
queue->entries++;
return queue->total;
}
//cant save packet ->destroy
packet_destroy(packet);
queue->lost++;
return 0;
}
struct packet_t *queue_retrieve(struct queue_t *queue) {
if (queue->entries == 0) return NULL;
struct packet_t **current = queue->packets + queue->read;
struct packet_t *packet = *current;
*current = NULL;
if (packet->queue) {
packet->queue = NULL;
}
queue->entries--;
queue->read++;
if (queue->read == queue->size) {
queue->read = 0;
}
return packet;
}
struct packet_t *packet_create(int i, double d, long l, char *p) {
struct packet_t *new = malloc(sizeof(struct packet_t));
if (new) {
new->i = i;
new->d = d;
new->l = l;
new->p = p;
}
else {
logError("failed to allocate memory");
}
return new;
}
int queue_destroy(struct queue_t *queue) {
if (!queue) {
logError("could not find queue!");
return 0;
}
struct packet_t *p;
for (int i = 0; i < queue->size; i++) {
p = *(queue->packets + i);
packet_destroy(p);
}
//TODO test if not needed as it's already free'd in packet_destroy
free(queue->packets);
free(queue);
return 0;
}
long test_queue(int val) {
int sum = 0, finalTime = 0;
clock_t startTime, finalTicks;
startTime = clock();
while (finalTime < val) {
struct queue_t *q = queue_create("test", 10);
queue_destroy(
sum++;
finalTicks = (clock() - startTime);
// printf("ticks: %d\n", finalTicks);
finalTime = (int)floor((finalTicks / (double)CLOCKS_PER_SEC));
// printf("time: %d\n", finalTime);
}
printf("Runtime: %d\n seconds", finalTime);
printf("Added and removed %d queues\n", sum);
}
long test_packets(int val) {
int finalTime = 0;
struct queue_t *q = queue_create("test", 10);
clock_t startTime, finalTicks;
startTime = clock();
while (finalTime < val) {
struct packet_t *t = packet_create(finalTime, finalTime + 1, finalTime + 2, NULL);
queue_store(q, t);
packet_destroy(queue_retrieve(q));
finalTicks = (clock() - startTime);
// printf("ticks: %d\n", finalTicks);
finalTime = (int)floor((finalTicks / (double)CLOCKS_PER_SEC));
// printf("time: %d\n", finalTime);
}
printf("Runtime: %d\n", finalTime);
printf("Successfully added %li entries\n", q->total);
printf("Failed to add %li entries\n", q->lost);
queue_destroy(q);
}
void resetDecision() {
decision = -1;
isRunning = 1;
}
void checkDecision() {
while (decision != 0 && decision != 1 && decision != 2) {
printf("Select option:\n (1) Run queue test \n (2) Run packet test \n(0) to cancel \n");
scanf("%d", &decision);
}
if (decision == 0) {
isRunning = 0;
}
else if (decision == 1) {
int val = 0;
while (val <= 0) {
printf("Enter the time to test");
scanf("%d", &val);
}
printf("Running test for %d seconds....\n", val);
test_queue(val);
}
else if (decision == 2) {
int val = 0;
while (val <= 0) {
printf("Enter the time to test");
scanf("%d", &val);
}
printf("Running test for %d seconds....\n", val);
test_packets(val);
}
if (decision != 0)
resetDecision();
}
int main() {
while (isRunning) {
checkDecision();
}
return 0;
}
You are compiling your program as a C++ program. In C++ there is no implicit conversion from the type void * to pointer of other object type.
So you need to write using explicit casting like
struct queue_t *q = ( struct queue_t * )malloc(sizeof(struct queue_t));
Or you should consider your program as indeed a C++ program and use the operator new instead of the C function malloc.

Unreachable Node in Dijkstra's Algorithm

So I'm having trouble with Dijkstra's algorithm (src to dest). I looked at other answers and could not find the solution to my problem. I have used an adjacency list, thus I have a list for vertices, and each vertex has it's own edge list. My problem arises when I have a node that is unreachable. Specifically, it never gets visited thus I'm stuck in my allNotComp while loop. Can anyone help me with a solution? Code is below.
#include <stdlib.h>
#include <stdio.h>
int INFINITY = 9999;
struct edge
{
int vertexIndex;
int vertexWeight;
struct edge *edgePtr;
} edge;
struct vertex
{
int vertexKey;
struct edge *edgePtr;
struct vertex *vertexPtr;
}vertex;
struct vertex *Start = NULL;
void insertEdge(int vertex, int vertex2, int vertexWeight);
void insertVertex(int vertexKey);
int allNotComp(int comp[], int size);
void printPath(int prev[], int src, int dest, int size);
void dijkstra(int src, int size, int dest);
int cost(int curr, int i);
int main(int argc, char * argv[]) {
int k = 1;
int numVertices = atoi(argv[2]);
char* source = argv[3];
char* destination = argv[4];
int src = atoi(argv[3]);
int dest = atoi(argv[4]);
Start = &vertex;
Start->vertexKey = 0;
Start->vertexPtr = NULL;
Start->edgePtr = NULL;
int m = 0;
int flag = 0;
int flag2 = 0;
for(m = 0; m < numVertices; m++){
if(src == m) {
flag = 1;
}
if(dest == m) {
flag2 = 1;
}
}
if(!(flag && flag2)) {
printf("%s ", "ERROR: Src and/or Dest not valid.\n");
exit(0);
}
while(k < numVertices) {
insertVertex(k);
k++;
}
FILE *f = fopen(argv[1], "r");
int numbers[numVertices][numVertices];
char ch;
int i = 0;
int j = 0;
for(m = 0; m < numVertices*numVertices; m++) {
fscanf(f, "%d", &(numbers[i][j]));
j=j+1;
if(j == numVertices) {
i=i+1;
j=0;
}
}
for(i=0;i<numVertices;i++) {
for(j=0;j<numVertices;j++) {
if(i == j && numbers[i][j] != 0) {
printf("%s", "ERROR: All diagonals must be zero.\n");
exit(0);
}
if(i != j) {
insertEdge(i, j, numbers[i][j]);
}
}
}
dijkstra(src, numVertices, dest);
}
void insertEdge(int vertex, int vertex2, int vertexWeight)
{
if(vertexWeight == -1) return;
struct vertex *traverse;
if(vertex == Start->vertexKey) {
traverse = Start;
}
else {
while(traverse->vertexKey != vertex) {
traverse = traverse->vertexPtr;
}
}
struct edge *e,*e1,*e2;
e=traverse->edgePtr;
while(e&& e->edgePtr)
{
e=e->edgePtr;
}
e1=(struct edge *)malloc(sizeof(*e1));
e1->vertexIndex=vertex2;
e1->vertexWeight = vertexWeight;
e1->edgePtr=NULL;
if(e)
e->edgePtr=e1;
else
traverse->edgePtr=e1;
}
void insertVertex(int vertexKey) {
struct vertex *v, *v1, *v2;
v = Start->vertexPtr;
while(v && v->vertexPtr) {
v=v->vertexPtr;
}
v1=(struct vertex *)malloc(sizeof(*v1));
v1->vertexKey = vertexKey;
v1->vertexPtr = NULL;
v1->edgePtr = NULL;
if(v) {
v->vertexPtr = v1;
}
else {
Start->vertexPtr = v1;
}
}
void dijkstra(int src, int size, int dest) {
int comp[size];
int dist[size];
int prev[size];
int i;
for(i = 0; i<size; i++) {
comp[i] = 0;
dist[i] = INFINITY;
prev[i] = -1;
}
comp[src] = 1;
dist[src] = 0;
prev[src] = src;
int curr = src;
int k;
int minDist;
int newDist;
while(allNotComp(comp, size)) {
minDist = INFINITY;
for(i = 0; i<size;i++) {
if(comp[i] == 0) {
newDist = dist[curr] + cost(curr, i);
if(newDist < dist[i]) {
dist[i] = newDist;
prev[i] = curr; }
if(dist[i] < minDist) {
minDist = dist[i];
k=i; }
}
}
curr = k;
comp[curr] = 1;
}
if(dist[dest] < INFINITY) {
printPath(prev, src, dest, size);
printf(":%d\n", dist[dest]);
} else {
printf("%s\n", "NO PATH EXISTS BETWEEN THE TWO VERTICES!");
}
}
int allNotComp(int comp[], int size) {
int i;
for(i = 0; i < size; i++) {
if(comp[i] == 0) {
return 1;
}
}
return 0;
}
int cost(int curr, int i) {
struct vertex *travel;
struct edge *traverse;
travel = Start;
while(travel->vertexPtr != NULL) {
if(travel->vertexKey != curr) {
travel = travel->vertexPtr;
}
else{
break;
}
}
traverse = travel->edgePtr;
while(traverse->edgePtr != NULL) {
if(traverse->vertexIndex != i) {
traverse = traverse->edgePtr;
}
else{
break;
}
}
if(traverse->vertexIndex != i) {
return INFINITY;
}
return traverse->vertexWeight;
}
void printPath(int prev[], int src, int dest, int size) {
if(src == dest) {
printf("%d", src);
}
else {
printPath(prev, src, prev[dest], size);
printf("-%d", dest);
}
}
Although an unreachable node never gets visited, this situation can be detected. If the dists of all unvisited nodes are INFINITY, this means all remaining nodes are unreachable, and you should end the loop.

Resources