mirror of
https://github.com/tezc/sc.git
synced 2025-01-28 07:03:06 +08:00
commit
45d73efe4c
@ -4,7 +4,7 @@
|
||||
|
||||
- Generic array which grows when you add elements.
|
||||
- Index access is possible (e.g float* arr; 'printf("%f", arr[i]')).
|
||||
- Copy <b>sc_array.h</b> and <b>sc_array.c</b> to your project.
|
||||
- Lazy allocation. No memory allocation until first 'add'.
|
||||
|
||||
|
||||
##### Usage
|
||||
@ -41,15 +41,6 @@
|
||||
sc_array_destroy(p);
|
||||
|
||||
```
|
||||
#### Internals
|
||||
|
||||
##### Memory
|
||||
- Single array allocation.
|
||||
- Lazy allocation. No memory allocation until first 'add'.
|
||||
|
||||
##### Performance
|
||||
- As all the items are in a single contiguous memory, it gives the best
|
||||
performance you can expect.
|
||||
|
||||
##### Note
|
||||
|
||||
|
@ -10,8 +10,7 @@
|
||||
- Integer operations are compiled into bounds check + a single MOV instruction
|
||||
on x86. Buffer keeps data in Little Endian format, so on big endian systems,
|
||||
integer put/get is bswap(byte swap) + MOV.
|
||||
- Just copy <b>sc_buf.h</b> and <b>sc_buf.c</b> to your project.
|
||||
|
||||
- Max capacity is 4GB. Max string size is ~2 GB
|
||||
|
||||
##### Usage
|
||||
|
||||
@ -61,4 +60,70 @@ int main()
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
##### Lazy error check
|
||||
|
||||
- Rather than checking error code for each
|
||||
put(Out of memory/limit exceeded) / get(buffer underflow) operation,
|
||||
error check can be postponed until end of an operation batch.
|
||||
|
||||
```c
|
||||
|
||||
#include "sc_buf.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
uint32_t val, val2;
|
||||
struct sc_buf buf;
|
||||
|
||||
sc_buf_init(&buf, 0);
|
||||
sc_buf_put_32(&buf, 1); // Even if we get OOM, it is safe to continue.
|
||||
sc_buf_put_32(&buf, 2);
|
||||
sc_buf_put_32(&buf, 3);
|
||||
sc_buf_put_32(&buf, 4);
|
||||
|
||||
if (sc_buf_valid(&buf) == false) {
|
||||
printf("OOM!.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sc_buf_term(&buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```c
|
||||
|
||||
#include "sc_buf.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
uint32_t val;
|
||||
struct sc_buf buf;
|
||||
|
||||
sc_buf_init(&buf, 0);
|
||||
sc_buf_put_32(&buf, 1);
|
||||
sc_buf_put_32(&buf, 2);
|
||||
|
||||
val = sc_buf_get_32(&buf);
|
||||
val = sc_buf_get_32(&buf);
|
||||
val = sc_buf_get_32(&buf); // Buffer underflow here
|
||||
val = sc_buf_get_32(&buf); // Buffer underflow here
|
||||
|
||||
if (sc_buf_valid(&buf) == false) {
|
||||
printf("Buffer underflow!.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sc_buf_term(&buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
@ -17,8 +17,8 @@ struct sc_thread
|
||||
|
||||
#else
|
||||
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct sc_thread
|
||||
{
|
||||
|
@ -27,7 +27,7 @@ void test1()
|
||||
sc_signal_snprintf(tmp, sizeof(tmp), "%llu", 100000000000ll);
|
||||
assert(strcmp(tmp, "100000000000") == 0);
|
||||
|
||||
char* x = (char*)0xabcdef;
|
||||
char *x = (char *) 0xabcdef;
|
||||
sc_signal_snprintf(tmp, sizeof(tmp), "%p", x);
|
||||
assert(strcmp(tmp, "0xabcdef") == 0);
|
||||
|
||||
@ -46,10 +46,60 @@ void test2()
|
||||
assert(sc_signal_init() == 0);
|
||||
}
|
||||
|
||||
int main()
|
||||
#ifdef SC_HAVE_WRAP
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <wait.h>
|
||||
|
||||
void sig_handler(int signum)
|
||||
{
|
||||
}
|
||||
|
||||
void test3(int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
assert(true);
|
||||
} else if (pid) {
|
||||
int status = 0;
|
||||
wait(&status);
|
||||
if (WIFSIGNALED(status)) {
|
||||
return;
|
||||
} else {
|
||||
assert(true);
|
||||
}
|
||||
} else {
|
||||
execvp(argv[1], argv + 1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void test4()
|
||||
{
|
||||
assert(sc_signal_init() == 0);
|
||||
sc_signal_shutdown_fd = STDOUT_FILENO;
|
||||
raise(SIGINT);
|
||||
sleep(3);
|
||||
}
|
||||
|
||||
#else
|
||||
void test3(int argc, char **argv)
|
||||
{
|
||||
}
|
||||
void test4()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
test3(argc, argv);
|
||||
test4();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -35,6 +35,17 @@ if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
|
||||
"${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
||||
|
||||
target_compile_options(${PROJECT_NAME}_test PRIVATE -DSC_HAVE_WRAP)
|
||||
target_compile_options(${PROJECT_NAME}_test PRIVATE -fno-builtin)
|
||||
target_link_options(${PROJECT_NAME}_test PRIVATE
|
||||
-Wl,--wrap=nanosleep)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
add_test(NAME ${PROJECT_NAME}_test COMMAND ${PROJECT_NAME}_test)
|
||||
|
||||
SET(MEMORYCHECK_COMMAND_OPTIONS
|
||||
|
@ -24,13 +24,13 @@
|
||||
#include "sc_time.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <assert.h>
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
uint64_t sc_time_ms()
|
||||
@ -142,7 +142,7 @@ int sc_time_sleep(uint64_t milliseconds)
|
||||
do {
|
||||
t = rem;
|
||||
rc = nanosleep(&t, &rem);
|
||||
} while (rc != 0 && errno != EINTR);
|
||||
} while (rc != 0 && errno == EINTR);
|
||||
|
||||
return rc;
|
||||
#endif
|
||||
|
@ -39,9 +39,76 @@ void test2(void)
|
||||
assert(t2 > t1);
|
||||
}
|
||||
|
||||
#ifdef SC_HAVE_WRAP
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
void sig_handler(int signum)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void test3(void)
|
||||
{
|
||||
uint64_t t1, t2;
|
||||
|
||||
signal(SIGALRM, sig_handler);
|
||||
alarm(2);
|
||||
|
||||
t1 = sc_time_mono_ms();
|
||||
sc_time_sleep(4000);
|
||||
t2 = sc_time_mono_ms();
|
||||
|
||||
assert(t2 > t1);
|
||||
|
||||
alarm(2);
|
||||
t1 = sc_time_mono_ns();
|
||||
sc_time_sleep(4000);
|
||||
t2 = sc_time_mono_ns();
|
||||
|
||||
assert(t2 > t1);
|
||||
}
|
||||
|
||||
bool fail_nanosleep = false;
|
||||
int __real_nanosleep(const struct timespec *__requested_time,
|
||||
struct timespec *__remaining);
|
||||
int __wrap_nanosleep(const struct timespec *__requested_time,
|
||||
struct timespec *__remaining)
|
||||
{
|
||||
if (fail_nanosleep) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return __real_nanosleep(__requested_time, __remaining);
|
||||
}
|
||||
|
||||
void test4(void)
|
||||
{
|
||||
fail_nanosleep = true;
|
||||
assert(sc_time_sleep(100) != 0);
|
||||
fail_nanosleep = false;
|
||||
}
|
||||
|
||||
#else
|
||||
void test3(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test4(void)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user