Added sac/queue.h, moved timer.h to utl folder, new queue benchmark

This commit is contained in:
Leonardo committed 2019-06-24 02:09:02 -03:00
1 parent 6213b42d5a
commit 9062415322
7 files changed
+460 -10

No files matched your search

+1
View File
@@ -37,6 +37,7 @@ Only Collections located in __cmc__ are to be documented at *Documentation.md*.
* Extra Collections Library
* LinkedQueue
* Stack Allocated Collections Library
* Queue
* Stack
### More to Come
+1 -1
View File
@@ -13,7 +13,7 @@
* - Output
*/
#include "macro_collections.h"
#include "util/timer.h"
#include "utl/timer.h"
#include "util/twister.c"
#include <stdio.h>
#include <stdint.h>
+10
View File
@@ -0,0 +1,10 @@
CFLAGS = -Wall -Wextra
INCLUDE = ../../src
main:
gcc queue.c -I $(INCLUDE) $(CFLAGS) -o a.exe -DCMC_QUEUE
a.exe
gcc queue.c -I $(INCLUDE) $(CFLAGS) -o a.exe -DSAC_QUEUE
a.exe
gcc queue.c -I $(INCLUDE) $(CFLAGS) -o a.exe -DEXT_QUEUE
a.exe
+82
View File
@@ -0,0 +1,82 @@
/**
* queue.c
*
* Creation Date: 24/06/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/* Showing off how different queue implementations affect runtime cost */
#include "utl/timer.h"
#include <stdio.h>
#include <inttypes.h>
#define MAX 200000
#if defined(CMC_QUEUE)
#include "cmc/queue.h"
QUEUE_GENERATE(q, queue, , int)
#define TARGET "QUEUE"
#elif defined(SAC_QUEUE)
#include "sac/queue.h"
SAC_QUEUE_GENERATE(q, queue, , int, MAX)
#define TARGET "SAC QUEUE"
#elif defined(EXT_QUEUE)
#include "ext/linkedqueue.h"
LINKEDQUEUE_GENERATE(q, queue, , int)
#define TARGET "LINKED QUEUE"
#else
#error Please define either CMC_QUEUE, SAC_QUEUE or EXT_QUEUE
#endif
int main(void)
{
#if defined(CMC_QUEUE)
queue *q = q_new(MAX);
#elif defined(SAC_QUEUE)
queue _q = q_new();
queue_ptr q = &_q;
#elif defined(EXT_QUEUE)
queue *q = q_new();
#endif
size_t sum = 0;
int i = 0;
timer_t timer;
TIMER_START(timer);
while (q_count(q) != MAX)
{
q_enqueue(q, i++);
if (i % 10 == 0)
{
for (size_t i = 0; i < 9; i++)
{
sum += q_peek(q);
q_dequeue(q);
}
}
}
TIMER_STOP(timer);
TIMER_CALC(timer);
printf("----------------------------------------\n");
printf("%s\n", TARGET);
printf("Execution time: %.0lf milliseconds\n", timer.result);
printf("SUM: %" PRIuMAX "\n", sum);
printf("----------------------------------------\n");
#if defined(CMC_QUEUE) || defined(EXT_QUEUE)
q_free(q);
#endif
return 0;
}
+357
View File
@@ -0,0 +1,357 @@
/**
* queue.h
*
* Creation Date: 24/06/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/**
* A Purely Stack Allocated Queue
*
* This means that the Queue has a fixed size, but it also has the advantage of
* not requiring for manually allocating and deallocating the struct.
*
* Generating a collection with too big of a storage can be dangerous and might
* quickly cause a stack overflow.
*
* It is recommended to not generate any Stack Allocated Collection with less
* than 1000 internal storage.
*/
#ifndef CMC_SAC_QUEUE_H
#define CMC_SAC_QUEUE_H
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define SAC_QUEUE_GENERATE(PFX, SNAME, FMOD, V, SIZE) \
SAC_QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
SAC_QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
#define SAC_QUEUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V, SIZE) \
SAC_QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE)
#define SAC_QUEUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V, SIZE) \
SAC_QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
/* HEADER ********************************************************************/
#define SAC_QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
\
/* Queue Structure */ \
typedef struct SNAME##_s \
{ \
/* Internal Storage */ \
V buffer[SIZE]; \
\
/* Current amount of elements */ \
size_t count; \
\
/* Index representing the front of the queue */ \
size_t front; \
\
/* Index representing the back of the queue */ \
size_t rear; \
\
/* Function that returns an iterator to the start of the queue */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the queue */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Queue Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target queue */ \
struct SNAME##_s *target; \
\
/* Cursor's position (index) */ \
size_t cursor; \
\
/* Keeps track of relative index to the iteration of elements */ \
size_t index; \
\
/* If the iterator has reached the start of the iteration */ \
bool start; \
\
/* If the iterator has reached the end of the iteration */ \
bool end; \
\
} SNAME##_iter, *SNAME##_iter_ptr; \
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME PFX##_new(void); \
FMOD void PFX##_clear(SNAME *_queue_); \
/* Collection Input and Output */ \
FMOD bool PFX##_enqueue(SNAME *_queue_, V element); \
FMOD bool PFX##_dequeue(SNAME *_queue_); \
/* Conditional Input and Output */ \
FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition); \
FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition); \
/* Element Access */ \
FMOD V PFX##_peek(SNAME *_queue_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \
FMOD bool PFX##_empty(SNAME *_queue_); \
FMOD bool PFX##_full(SNAME *_queue_); \
FMOD size_t PFX##_count(SNAME *_queue_); \
FMOD size_t PFX##_capacity(void); \
\
/* Iterator Functions */ \
/* Iterator Initialization */ \
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
/* Iterator State */ \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
/* Iterator Movement */ \
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
/* Iterator Access */ \
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* Default Value */ \
static inline V PFX##_impl_default_value(void) \
{ \
V _empty_value_; \
\
memset(&_empty_value_, 0, sizeof(V)); \
\
return _empty_value_; \
} \
\
/* SOURCE ********************************************************************/
#define SAC_QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE) \
\
/* Implementation Detail Functions */ \
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \
\
FMOD SNAME PFX##_new(void) \
{ \
SNAME result; \
\
memset(&result, 0, sizeof(SNAME)); \
\
result.it_start = PFX##_impl_it_start; \
result.it_end = PFX##_impl_it_end; \
\
return result; \
} \
\
FMOD void PFX##_clear(SNAME *_queue_) \
{ \
memset(_queue_->buffer, 0, sizeof(_queue_->buffer)); \
\
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
} \
\
FMOD bool PFX##_enqueue(SNAME *_queue_, V element) \
{ \
if (PFX##_full(_queue_)) \
return false; \
\
_queue_->buffer[_queue_->rear] = element; \
\
_queue_->rear = (_queue_->rear == SIZE - 1) ? 0 : _queue_->rear + 1; \
_queue_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_dequeue(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
return false; \
\
_queue_->buffer[_queue_->front] = PFX##_impl_default_value(); \
\
_queue_->front = (_queue_->front == SIZE - 1) ? 0 : _queue_->front + 1; \
_queue_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition) \
{ \
if (condition) \
return PFX##_enqueue(_queue_, element); \
\
return false; \
} \
\
FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition) \
{ \
if (condition) \
return PFX##_dequeue(_queue_); \
\
return false; \
} \
\
FMOD V PFX##_peek(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
PFX##_impl_default_value(); \
\
return _queue_->buffer[_queue_->front]; \
} \
\
FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)) \
{ \
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++) \
{ \
if (comparator(_queue_->buffer[i], element) == 0) \
return true; \
} \
\
return false; \
} \
\
FMOD bool PFX##_empty(SNAME *_queue_) \
{ \
return _queue_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_queue_) \
{ \
return _queue_->count >= SIZE; \
} \
\
FMOD size_t PFX##_count(SNAME *_queue_) \
{ \
return _queue_->count; \
} \
\
FMOD size_t PFX##_capacity(void) \
{ \
return SIZE; \
} \
\
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
iter->target = target; \
iter->cursor = target->front; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(target); \
} \
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->front; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
iter->cursor = 0; \
else \
iter->cursor = (iter->target->rear == 0) ? SIZE - 1 : iter->target->rear - 1; \
\
iter->index = iter->target->count - 1; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
iter->start = PFX##_empty(iter->target); \
\
if (iter->index == iter->target->count - 1) \
iter->end = true; \
else \
{ \
iter->cursor = (iter->cursor + 1) % (SIZE); \
iter->index++; \
} \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
iter->end = PFX##_empty(iter->target); \
\
if (iter->index == 0) \
iter->start = true; \
else \
{ \
iter->cursor = (iter->cursor == 0) ? SIZE - 1 : iter->cursor - 1; \
iter->index--; \
} \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
PFX##_impl_default_value(); \
\
return iter->target->buffer[iter->cursor]; \
} \
\
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return NULL; \
\
return &(iter->target->buffer[iter->cursor]); \
} \
\
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
return iter->index; \
} \
\
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _queue_); \
PFX##_iter_to_start(&iter); \
\
return iter; \
} \
\
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _queue_); \
PFX##_iter_to_end(&iter); \
\
return iter; \
}
#endif /* CMC_SAC_QUEUE_H */
+1 -8
View File
@@ -79,7 +79,6 @@
/* Collection Allocation and Deallocation */ \
FMOD SNAME PFX##_new(void); \
FMOD void PFX##_clear(SNAME *_stack_); \
FMOD void PFX##_free(SNAME *_stack_); \
/* Collection Input and Output */ \
FMOD bool PFX##_push(SNAME *_stack_, V element); \
FMOD bool PFX##_pop(SNAME *_stack_); \
@@ -142,17 +141,11 @@
\
FMOD void PFX##_clear(SNAME *_stack_) \
{ \
memset(_stack_->buffer, 0, sizeof(V) * SIZE); \
memset(_stack_->buffer, 0, sizeof(_stack_->buffer)); \
\
_stack_->count = 0; \
} \
\
FMOD void PFX##_free(SNAME *_stack_) \
{ \
free(_stack_->buffer); \
free(_stack_); \
} \
\
FMOD bool PFX##_push(SNAME *_stack_, V element) \
{ \
if (PFX##_full(_stack_)) \
+8 -1
View File
@@ -6,8 +6,13 @@
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Simple timer macros.
*/
/* Simple timer macros utility */
#ifndef CMC_TIMER_H
#define CMC_TIMER_H
#include <time.h>
typedef struct timer_s
@@ -25,3 +30,5 @@ typedef struct timer_s
#define TIMER_CALC(timer) \
timer.result = (double)(((timer.stop - timer.start) * 1000.0) / CLOCKS_PER_SEC);
#endif /* CMC_TIMER_H */