feat(cat-heap): initial implementation
							parent
							
								
									1c563d8421
								
							
						
					
					
						commit
						8e076f8543
					
				| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
#ifndef VIETER_CAT_HEAP
 | 
			
		||||
#define VIETER_CAT_HEAP
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
typedef struct vieter_cat_heap vieter_cat_heap;
 | 
			
		||||
 | 
			
		||||
typedef enum vieter_cat_heap_error {
 | 
			
		||||
  vieter_cat_heap_ok = 0,
 | 
			
		||||
  vieter_cat_heap_arch_empty = 1,
 | 
			
		||||
  vieter_cat_heap_arch_not_found = 2
 | 
			
		||||
} vieter_cat_heap_error;
 | 
			
		||||
 | 
			
		||||
vieter_cat_heap *vieter_cat_heap_init();
 | 
			
		||||
 | 
			
		||||
void vieter_cat_heap_free(vieter_cat_heap **ptp);
 | 
			
		||||
 | 
			
		||||
uint64_t vieter_cat_heap_size(vieter_cat_heap *cheap);
 | 
			
		||||
 | 
			
		||||
vieter_cat_heap_error vieter_cat_heap_insert(vieter_cat_heap *cheap,
 | 
			
		||||
                                             char *category, uint64_t key,
 | 
			
		||||
                                             void *data);
 | 
			
		||||
 | 
			
		||||
vieter_cat_heap_error vieter_cat_heap_pop(void **out, vieter_cat_heap *cheap,
 | 
			
		||||
                                          char *category);
 | 
			
		||||
 | 
			
		||||
vieter_cat_heap_error vieter_cat_heap_peek(void **out, vieter_cat_heap *cheap,
 | 
			
		||||
                                           char *category);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -123,5 +123,22 @@ vieter_job_queue_remove(vieter_job **out, vieter_job_queue *queue, uint64_t id);
 | 
			
		|||
 */
 | 
			
		||||
vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue,
 | 
			
		||||
                                             uint64_t id, char *report_message);
 | 
			
		||||
/*
 | 
			
		||||
 * Acquire a read lock on the job queue. Return value is the result of
 | 
			
		||||
 * pthread_rwlock_rdlock.
 | 
			
		||||
 */
 | 
			
		||||
int vieter_job_queue_rlock(vieter_job_queue *job_queue);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Acquire a write lock on the job queue. Return value is the result of
 | 
			
		||||
 * pthread_rwlock_wrlock.
 | 
			
		||||
 */
 | 
			
		||||
int vieter_job_queue_wlock(vieter_job_queue *job_queue);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Unlock the lock after having acquired it. Return value is the result of
 | 
			
		||||
 * pthread_rwlock_unlock.
 | 
			
		||||
 */
 | 
			
		||||
int vieter_job_queue_unlock(vieter_job_queue *job_queue);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
A category heap consists of a collection of heaps, with each heap representing
 | 
			
		||||
a certain category. In practice, this category would be an architecture (e.g.
 | 
			
		||||
`x86_64`). This is used by the job queue to have a queue for each architecture
 | 
			
		||||
for a given state.
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,107 @@
 | 
			
		|||
#include "vieter_cat_heap_internal.h"
 | 
			
		||||
 | 
			
		||||
vieter_cat_heap *vieter_cat_heap_init() {
 | 
			
		||||
  return calloc(1, sizeof(vieter_cat_heap));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vieter_cat_heap_free(vieter_cat_heap **ptp) {
 | 
			
		||||
  vieter_cat_heap *cheap = *ptp;
 | 
			
		||||
 | 
			
		||||
  if (cheap->cat_count > 0) {
 | 
			
		||||
    for (uint64_t i = 0; i < cheap->cat_count; i++) {
 | 
			
		||||
      free(cheap->categories[i]);
 | 
			
		||||
      vieter_heap_free(cheap->heaps[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    free(cheap->categories);
 | 
			
		||||
    free(cheap->heaps);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  free(cheap);
 | 
			
		||||
  *ptp = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t vieter_cat_heap_size(vieter_cat_heap *cheap) {
 | 
			
		||||
  uint64_t total = 0;
 | 
			
		||||
 | 
			
		||||
  for (uint64_t i = 0; i < cheap->cat_count; i++) {
 | 
			
		||||
    total += vieter_heap_size(cheap->heaps[i]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return total;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vieter_cat_heap_error vieter_cat_heap_insert(vieter_cat_heap *cheap,
 | 
			
		||||
                                             char *category, uint64_t key,
 | 
			
		||||
                                             void *data) {
 | 
			
		||||
  uint64_t i = 0;
 | 
			
		||||
 | 
			
		||||
  // For now, we do a linear search through all categories. This is more than
 | 
			
		||||
  // fast enough for most usecases.
 | 
			
		||||
  while (i < cheap->cat_count && strcmp(category, cheap->categories[i]) != 0) {
 | 
			
		||||
    i++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (i == cheap->cat_count) {
 | 
			
		||||
    if (cheap->cat_count == 0) {
 | 
			
		||||
      cheap->categories = malloc(sizeof(char *));
 | 
			
		||||
      cheap->heaps = malloc(sizeof(vieter_heap *));
 | 
			
		||||
    } else {
 | 
			
		||||
      cheap->categories =
 | 
			
		||||
          realloc(cheap->categories, sizeof(char *) * (cheap->cat_count + 1));
 | 
			
		||||
      cheap->heaps =
 | 
			
		||||
          realloc(cheap->heaps, sizeof(vieter_heap *) * (cheap->cat_count + 1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cheap->cat_count++;
 | 
			
		||||
 | 
			
		||||
    cheap->categories[i] = strdup(category);
 | 
			
		||||
    cheap->heaps[i] = vieter_heap_init();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  vieter_heap_insert(cheap->heaps[i], key, data);
 | 
			
		||||
 | 
			
		||||
  return vieter_cat_heap_ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vieter_cat_heap_error vieter_cat_heap_pop(void **out, vieter_cat_heap *cheap,
 | 
			
		||||
                                          char *category) {
 | 
			
		||||
  uint64_t i = 0;
 | 
			
		||||
 | 
			
		||||
  while (i < cheap->cat_count && strcmp(category, cheap->categories[i]) != 0) {
 | 
			
		||||
    i++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (i == cheap->cat_count) {
 | 
			
		||||
    return vieter_cat_heap_arch_not_found;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  vieter_heap_error res = vieter_heap_pop(out, cheap->heaps[i]);
 | 
			
		||||
 | 
			
		||||
  if (res != vieter_heap_ok) {
 | 
			
		||||
    return vieter_cat_heap_arch_empty;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return vieter_cat_heap_ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vieter_cat_heap_error vieter_cat_heap_peek(void **out, vieter_cat_heap *cheap,
 | 
			
		||||
                                           char *category) {
 | 
			
		||||
  uint64_t i = 0;
 | 
			
		||||
 | 
			
		||||
  while (i < cheap->cat_count && strcmp(category, cheap->categories[i]) != 0) {
 | 
			
		||||
    i++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (i == cheap->cat_count) {
 | 
			
		||||
    return vieter_cat_heap_arch_not_found;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  vieter_heap_error res = vieter_heap_peek(out, cheap->heaps[i]);
 | 
			
		||||
 | 
			
		||||
  if (res != vieter_heap_ok) {
 | 
			
		||||
    return vieter_cat_heap_arch_empty;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return vieter_cat_heap_ok;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
#include "vieter_cat_heap.h"
 | 
			
		||||
#include "vieter_heap.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
struct vieter_cat_heap {
 | 
			
		||||
  uint64_t cat_count;
 | 
			
		||||
  char **categories;
 | 
			
		||||
  vieter_heap **heaps;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +63,7 @@ vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue,
 | 
			
		|||
vieter_job_queue_error vieter_job_queue_pop(vieter_job **out,
 | 
			
		||||
                                            vieter_job_queue *queue,
 | 
			
		||||
                                            vieter_job_state state) {
 | 
			
		||||
 | 
			
		||||
  vieter_heap_error res = vieter_heap_pop((void **)out, queue->heaps[state]);
 | 
			
		||||
 | 
			
		||||
  if (res != vieter_heap_ok) {
 | 
			
		||||
| 
						 | 
				
			
			@ -151,3 +152,15 @@ vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue,
 | 
			
		|||
 | 
			
		||||
  return vieter_job_queue_ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vieter_job_queue_rlock(vieter_job_queue *job_queue) {
 | 
			
		||||
  return pthread_rwlock_rdlock(&job_queue->lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vieter_job_queue_wlock(vieter_job_queue *job_queue) {
 | 
			
		||||
  return pthread_rwlock_wrlock(&job_queue->lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vieter_job_queue_unlock(vieter_job_queue *job_queue) {
 | 
			
		||||
  return pthread_rwlock_unlock(&job_queue->lock);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,10 +4,12 @@
 | 
			
		|||
#include "vieter_heap.h"
 | 
			
		||||
#include "vieter_job_queue.h"
 | 
			
		||||
#include "vieter_tree.h"
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
struct vieter_job_queue {
 | 
			
		||||
  vieter_tree *tree;
 | 
			
		||||
  vieter_heap *heaps[VIETER_JOB_STATES];
 | 
			
		||||
  pthread_rwlock_t lock;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue