More work on Deque, UDPConnection

This commit is contained in:
Stephen Seo 2019-01-31 12:16:01 +09:00
parent c0046e5160
commit 48cf70ef49
5 changed files with 228 additions and 8 deletions

View file

@ -6,6 +6,10 @@
UDPC_Deque* UDPC_Deque_init(uint32_t alloc_size) UDPC_Deque* UDPC_Deque_init(uint32_t alloc_size)
{ {
UDPC_Deque *deque = malloc(sizeof(UDPC_Deque)); UDPC_Deque *deque = malloc(sizeof(UDPC_Deque));
if(!deque)
{
return NULL;
}
UDPC_Deque_clear(deque); UDPC_Deque_clear(deque);
deque->alloc_size = alloc_size; deque->alloc_size = alloc_size;
deque->buf = malloc(alloc_size); deque->buf = malloc(alloc_size);
@ -163,7 +167,12 @@ int UDPC_Deque_get_back(UDPC_Deque *deque, void **data, uint32_t *size)
*data = malloc(*size); *data = malloc(*size);
if(deque->tail < *size) if(deque->tail == 0)
{
memcpy(*data, &deque->buf[deque->alloc_size - *size], *size);
return returnValue;
}
else if(deque->tail < *size)
{ {
memcpy(data[*size - deque->tail], deque->buf, deque->tail); memcpy(data[*size - deque->tail], deque->buf, deque->tail);
memcpy( memcpy(
@ -172,9 +181,32 @@ int UDPC_Deque_get_back(UDPC_Deque *deque, void **data, uint32_t *size)
*size - deque->tail); *size - deque->tail);
return returnValue; return returnValue;
} }
else
{
memcpy(*data, &deque->buf[deque->tail - *size], *size);
return returnValue;
}
}
memcpy(*data, &deque->buf[deque->tail - *size], *size); void* UDPC_Deque_get_back_ptr(UDPC_Deque *deque, uint32_t unitSize)
return returnValue; {
if(deque->size < unitSize)
{
return NULL;
}
if(deque->tail == 0 && deque->size >= unitSize)
{
return &deque->buf[deque->alloc_size - unitSize];
}
else if(deque->tail < unitSize)
{
return NULL;
}
else
{
return &deque->buf[deque->tail - unitSize];
}
} }
int UDPC_Deque_get_front(UDPC_Deque *deque, void **data, uint32_t *size) int UDPC_Deque_get_front(UDPC_Deque *deque, void **data, uint32_t *size)
@ -203,9 +235,21 @@ int UDPC_Deque_get_front(UDPC_Deque *deque, void **data, uint32_t *size)
*size - (deque->alloc_size - deque->head)); *size - (deque->alloc_size - deque->head));
return returnValue; return returnValue;
} }
else
{
memcpy(*data, &deque->buf[deque->head], *size);
return returnValue;
}
}
memcpy(*data, &deque->buf[deque->head], *size); void* UDPC_Deque_get_front_ptr(UDPC_Deque *deque, uint32_t unitSize)
return returnValue; {
if(deque->size < unitSize || deque->head + unitSize > deque->alloc_size)
{
return NULL;
}
return &deque->buf[deque->head];
} }
void UDPC_Deque_pop_back(UDPC_Deque *deque, uint32_t size) void UDPC_Deque_pop_back(UDPC_Deque *deque, uint32_t size)
@ -294,6 +338,32 @@ int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void
return 1; return 1;
} }
void* UDPC_Deque_index_ptr(UDPC_Deque *deque, uint32_t unitSize, uint32_t index)
{
uint32_t pos = unitSize * index;
uint32_t abspos;
if(pos >= deque->size)
{
return NULL;
}
if(pos + deque->head >= deque->alloc_size)
{
abspos = pos + deque->head - deque->alloc_size;
}
else
{
abspos = pos + deque->head;
}
if(abspos + unitSize > deque->alloc_size)
{
return NULL;
}
return &deque->buf[abspos];
}
int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out) int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out)
{ {
uint32_t pos = unitSize * (index + 1); uint32_t pos = unitSize * (index + 1);
@ -328,6 +398,32 @@ int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, v
return 1; return 1;
} }
void* UDPC_Deque_index_rev_ptr(UDPC_Deque *deque, uint32_t unitSize, uint32_t index)
{
uint32_t pos = unitSize * (index + 1);
uint32_t abspos;
if(pos >= deque->size + unitSize)
{
return NULL;
}
if(pos > deque->tail)
{
abspos = deque->alloc_size - (pos - deque->tail);
}
else
{
abspos = deque->tail - pos;
}
if(abspos + unitSize > deque->alloc_size)
{
return NULL;
}
return &deque->buf[abspos];
}
int UDPC_Deque_remove(UDPC_Deque *deque, uint32_t unitSize, uint32_t index) int UDPC_Deque_remove(UDPC_Deque *deque, uint32_t unitSize, uint32_t index)
{ {
uint32_t pos = unitSize * index; uint32_t pos = unitSize * index;

View file

@ -60,6 +60,14 @@ uint32_t UDPC_Deque_get_used(UDPC_Deque *deque);
*/ */
int UDPC_Deque_get_back(UDPC_Deque *deque, void **data, uint32_t *size); int UDPC_Deque_get_back(UDPC_Deque *deque, void **data, uint32_t *size);
/*!
* \brief Get data ptr from back of deque
* The returned ptr is part of the Deque's internal buffer and must not be
* manually free'd; it will be free'd when the Deque itself is destroyed.
* \return non-null if tail of deque has contiguous data of size unitSize
*/
void* UDPC_Deque_get_back_ptr(UDPC_Deque *deque, uint32_t unitSize);
/*! /*!
* \brief Get data from front of deque * \brief Get data from front of deque
* Data must be free'd after use as it was allocated with malloc. * Data must be free'd after use as it was allocated with malloc.
@ -69,6 +77,14 @@ int UDPC_Deque_get_back(UDPC_Deque *deque, void **data, uint32_t *size);
*/ */
int UDPC_Deque_get_front(UDPC_Deque *deque, void **data, uint32_t *size); int UDPC_Deque_get_front(UDPC_Deque *deque, void **data, uint32_t *size);
/*!
* \brief Get data ptr from front of deque
* The returned ptr is part of the Deque's internal buffer and must not be
* manually free'd; it will be free'd when the Deque itself is destroyed.
* \return non-null if head of deque has contiguous data of size unitSize
*/
void* UDPC_Deque_get_front_ptr(UDPC_Deque *deque, uint32_t unitSize);
/*! /*!
* \brief "free" data from the back of the deque * \brief "free" data from the back of the deque
* If size is greater than data used, then all data will be "free"d. * If size is greater than data used, then all data will be "free"d.
@ -98,6 +114,15 @@ void UDPC_Deque_pop_front(UDPC_Deque *deque, uint32_t size);
*/ */
int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out); int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out);
/*!
* \brief Get a ptr to the indexed data at position unitSize * index
* The ptr will be indexed relative to the head of the Deque.
* The returned ptr is part of the Deque's internal buffer and will be free'd
* when the Deque is destroyed, so it should not be free'd directly.
* \return non-null if indexed data is a valid contiguous part of the buffer
*/
void* UDPC_Deque_index_ptr(UDPC_Deque *deque, uint32_t unitSize, uint32_t index);
/*! /*!
* \brief Get a unitSize sized chunk of data at position relative to tail * \brief Get a unitSize sized chunk of data at position relative to tail
* The out pointer will be malloc'd with size unitSize and will have a copy of * The out pointer will be malloc'd with size unitSize and will have a copy of
@ -109,6 +134,15 @@ int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void
*/ */
int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out); int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out);
/*!
* \brief Get a ptr to the indexed data at position unitSize * index
* The ptr will be indexed relative to the tail of the Deque.
* The returned ptr is part of the Deque's internal buffer and will be free'd
* when the Deque is destroyed, so it should not be free'd directly.
* \return non-null if indexed data is a valid contiguous part of the buffer
*/
void* UDPC_Deque_index_rev_ptr(UDPC_Deque *deque, uint32_t unitSize, uint32_t index);
/*! /*!
* \brief Replaces the data at index with data at the end (if exists) * \brief Replaces the data at index with data at the end (if exists)
* Note this will reduce the size of the Deque by unitSize amount. * Note this will reduce the size of the Deque by unitSize amount.

View file

@ -62,6 +62,8 @@ UDPC_Context* UDPC_init(uint16_t listenPort, int isClient)
context->connected = UDPC_Deque_init(sizeof(UDPC_INTERNAL_ConnectionData) context->connected = UDPC_Deque_init(sizeof(UDPC_INTERNAL_ConnectionData)
* (isClient != 0 ? 1 : UDPC_CD_AMOUNT)); * (isClient != 0 ? 1 : UDPC_CD_AMOUNT));
timespec_get(&context->lastUpdated, TIME_UTC);
return context; return context;
} }
@ -166,6 +168,70 @@ const char* UDPC_get_error_str(uint32_t error)
} }
} }
void UDPC_update(UDPC_Context *ctx)
{
// get dt
struct timespec ts;
timespec_get(&ts, TIME_UTC);
float dt = UDPC_ts_diff_to_seconds(&ts, &ctx->lastUpdated);
ctx->lastUpdated = ts;
// check rtt
for(int x = 0; x * sizeof(UDPC_INTERNAL_ConnectionData) < ctx->connected->size; ++x)
{
// TODO after fixing Deque
}
}
float UDPC_ts_diff_to_seconds(struct timespec *ts0, struct timespec *ts1)
{
float sec = 0.0f;
if(!ts0 || !ts1)
{
return sec;
}
if(ts0->tv_sec > ts1->tv_sec)
{
sec = ts0->tv_sec - ts1->tv_sec;
if(ts0->tv_nsec > ts1->tv_nsec)
{
sec += ((float)(ts0->tv_nsec - ts1->tv_nsec)) / 1000000000.0f;
}
else if(ts0->tv_nsec < ts1->tv_nsec)
{
sec -= 1.0f;
sec += ((float)(1000000000 + ts0->tv_nsec - ts1->tv_nsec)) / 1000000000.0f;
}
}
else if(ts0->tv_sec < ts1->tv_sec)
{
sec = ts1->tv_sec - ts0->tv_sec;
if(ts0->tv_nsec < ts1->tv_nsec)
{
sec += ((float)(ts1->tv_nsec - ts0->tv_nsec)) / 1000000000.0f;
}
else if(ts0->tv_nsec > ts1->tv_nsec)
{
sec -= 1.0f;
sec += ((float)(1000000000 + ts1->tv_nsec - ts0->tv_nsec)) / 1000000000.0f;
}
}
else
{
if(ts0->tv_nsec > ts1->tv_nsec)
{
sec += ((float)(ts0->tv_nsec - ts1->tv_nsec)) / 1000000000.0f;
}
else
{
sec += ((float)(ts1->tv_nsec - ts0->tv_nsec)) / 1000000000.0f;
}
}
return sec;
}
int UDPC_INTERNAL_threadfn(void *context) int UDPC_INTERNAL_threadfn(void *context)
{ {
UDPC_Context *ctx = (UDPC_Context*)context; UDPC_Context *ctx = (UDPC_Context*)context;

View file

@ -20,11 +20,13 @@
#include <unistd.h> #include <unistd.h>
#define CleanupSocket(x) close(x) #define CleanupSocket(x) close(x)
#else
#define CleanupSocket(x) ((void)0)
#endif #endif
#define UDPC_CD_AMOUNT 32 #define UDPC_CD_AMOUNT 32
// This struct should not be used outside of this library /// This struct should not be used outside of this library
typedef struct typedef struct
{ {
uint32_t addr; uint32_t addr;
@ -39,7 +41,7 @@ typedef struct
struct timespec sent; struct timespec sent;
} UDPC_INTERNAL_PacketInfo; } UDPC_INTERNAL_PacketInfo;
// This struct should not be used outside of this library /// This struct should not be used outside of this library
typedef struct typedef struct
{ {
/* /*
@ -64,7 +66,7 @@ typedef struct
struct timespec rtt; struct timespec rtt;
} UDPC_INTERNAL_ConnectionData; } UDPC_INTERNAL_ConnectionData;
// This struct should not be modified, only passed to functions that require it /// This struct should not be modified, only passed to functions that require it
typedef struct typedef struct
{ {
/* /*
@ -84,6 +86,7 @@ typedef struct
mtx_t tflagsMtx; mtx_t tflagsMtx;
cnd_t threadCV; cnd_t threadCV;
UDPC_Deque *connected; UDPC_Deque *connected;
struct timespec lastUpdated;
} UDPC_Context; } UDPC_Context;
UDPC_Context* UDPC_init(uint16_t listenPort, int isClient); UDPC_Context* UDPC_init(uint16_t listenPort, int isClient);
@ -96,6 +99,11 @@ uint32_t UDPC_get_error(UDPC_Context *ctx);
const char* UDPC_get_error_str(uint32_t error); const char* UDPC_get_error_str(uint32_t error);
/// If threaded, this function is called automatically
void UDPC_update(UDPC_Context *ctx);
float UDPC_ts_diff_to_seconds(struct timespec *ts0, struct timespec *ts1);
int UDPC_INTERNAL_threadfn(void *context); // internal usage only int UDPC_INTERNAL_threadfn(void *context); // internal usage only
#endif #endif

View file

@ -36,11 +36,27 @@ int main()
// push back success // push back success
ASSERT_TRUE(UDPC_Deque_push_back(deque, arr, sizeof(int) * 4)); ASSERT_TRUE(UDPC_Deque_push_back(deque, arr, sizeof(int) * 4));
ASSERT_EQ_MEM(arr, deque->buf, sizeof(int) * 4); ASSERT_EQ_MEM(arr, deque->buf, sizeof(int) * 4);
ASSERT_EQ_MEM(arr, UDPC_Deque_get_back_ptr(deque, sizeof(int) * 4), sizeof(int) * 4);
ASSERT_EQ_MEM(arr, UDPC_Deque_get_front_ptr(deque, sizeof(int) * 4), sizeof(int) * 4);
for(int x = 0; x < 4; ++x)
{
ASSERT_EQ_MEM(&arr[x], UDPC_Deque_index_ptr(deque, sizeof(int), x), sizeof(int));
ASSERT_EQ_MEM(&arr[3 - x], UDPC_Deque_index_rev_ptr(deque, sizeof(int), x), sizeof(int));
}
ASSERT_EQ(deque->size, sizeof(int) * 4); ASSERT_EQ(deque->size, sizeof(int) * 4);
// push front success // push front success
ASSERT_TRUE(UDPC_Deque_push_front(deque, &arr[4], sizeof(int) * 4)); ASSERT_TRUE(UDPC_Deque_push_front(deque, &arr[4], sizeof(int) * 4));
ASSERT_EQ_MEM(&arr[4], &deque->buf[sizeof(int) * 12], sizeof(int) * 4); ASSERT_EQ_MEM(&arr[4], &deque->buf[sizeof(int) * 12], sizeof(int) * 4);
ASSERT_EQ_MEM(arr, UDPC_Deque_get_back_ptr(deque, sizeof(int) * 4), sizeof(int) * 4);
ASSERT_EQ_MEM(&arr[4], UDPC_Deque_get_front_ptr(deque, sizeof(int) * 4), sizeof(int) * 4);
for(int x = 0; x < 4; ++x)
{
ASSERT_EQ_MEM(&arr[x + 4], UDPC_Deque_index_ptr(deque, sizeof(int), x), sizeof(int));
ASSERT_EQ_MEM(&arr[x], UDPC_Deque_index_ptr(deque, sizeof(int), x + 4), sizeof(int));
ASSERT_EQ_MEM(&arr[3 - x], UDPC_Deque_index_rev_ptr(deque, sizeof(int), x), sizeof(int));
ASSERT_EQ_MEM(&arr[7 - x], UDPC_Deque_index_rev_ptr(deque, sizeof(int), x + 4), sizeof(int));
}
ASSERT_EQ(deque->size, sizeof(int) * 8); ASSERT_EQ(deque->size, sizeof(int) * 8);
// realloc bigger success // realloc bigger success