Test: Threaded string builder on *nix
This commit is contained in:
parent
6bdae813be
commit
0fd6532b38
@ -292,6 +292,7 @@ include(CheckIncludeFiles)
|
|||||||
check_function_exists(strdup HAVE_STRDUP)
|
check_function_exists(strdup HAVE_STRDUP)
|
||||||
check_function_exists(strndup HAVE_STRNDUP)
|
check_function_exists(strndup HAVE_STRNDUP)
|
||||||
check_function_exists(strlcpy HAVE_STRLCPY)
|
check_function_exists(strlcpy HAVE_STRLCPY)
|
||||||
|
check_function_exists(vasprintf HAVE_VASPRINTF)
|
||||||
if(NOT DEFINED PSP2)
|
if(NOT DEFINED PSP2)
|
||||||
check_function_exists(localtime_r HAVE_LOCALTIME_R)
|
check_function_exists(localtime_r HAVE_LOCALTIME_R)
|
||||||
endif()
|
endif()
|
||||||
@ -374,6 +375,10 @@ if(HAVE_STRLCPY)
|
|||||||
list(APPEND FUNCTION_DEFINES HAVE_STRLCPY)
|
list(APPEND FUNCTION_DEFINES HAVE_STRLCPY)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_VASPRINTF)
|
||||||
|
list(APPEND FUNCTION_DEFINES HAVE_VASPRINTF)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(HAVE_LOCALTIME_R)
|
if(HAVE_LOCALTIME_R)
|
||||||
list(APPEND FUNCTION_DEFINES HAVE_LOCALTIME_R)
|
list(APPEND FUNCTION_DEFINES HAVE_LOCALTIME_R)
|
||||||
endif()
|
endif()
|
||||||
|
@ -85,6 +85,11 @@ DEFINE_VECTOR(CInemaTestList, struct CInemaTest)
|
|||||||
DECLARE_VECTOR(ImageList, void*)
|
DECLARE_VECTOR(ImageList, void*)
|
||||||
DEFINE_VECTOR(ImageList, void*)
|
DEFINE_VECTOR(ImageList, void*)
|
||||||
|
|
||||||
|
struct StringBuilder {
|
||||||
|
struct StringList out;
|
||||||
|
struct StringList err;
|
||||||
|
};
|
||||||
|
|
||||||
static bool showVersion = false;
|
static bool showVersion = false;
|
||||||
static bool showUsage = false;
|
static bool showUsage = false;
|
||||||
static char base[PATH_MAX] = {0};
|
static char base[PATH_MAX] = {0};
|
||||||
@ -102,6 +107,7 @@ static size_t jobIndex = 0;
|
|||||||
static Mutex jobMutex;
|
static Mutex jobMutex;
|
||||||
static Thread jobThreads[MAX_JOBS];
|
static Thread jobThreads[MAX_JOBS];
|
||||||
static int jobStatus;
|
static int jobStatus;
|
||||||
|
static ThreadLocal stringBuilder;
|
||||||
|
|
||||||
bool CInemaTestInit(struct CInemaTest*, const char* directory, const char* filename);
|
bool CInemaTestInit(struct CInemaTest*, const char* directory, const char* filename);
|
||||||
void CInemaTestRun(struct CInemaTest*);
|
void CInemaTestRun(struct CInemaTest*);
|
||||||
@ -117,7 +123,16 @@ ATTRIBUTE_FORMAT(printf, 2, 3) void CIlog(int minlevel, const char* format, ...)
|
|||||||
}
|
}
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
#ifdef HAVE_VASPRINTF
|
||||||
|
struct StringBuilder* builder = ThreadLocalGetValue(stringBuilder);
|
||||||
|
if (!builder) {
|
||||||
|
vprintf(format, args);
|
||||||
|
} else {
|
||||||
|
vasprintf(StringListAppend(&builder->out), format, args);
|
||||||
|
}
|
||||||
|
#else
|
||||||
vprintf(format, args);
|
vprintf(format, args);
|
||||||
|
#endif
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,10 +142,39 @@ ATTRIBUTE_FORMAT(printf, 2, 3) void CIerr(int minlevel, const char* format, ...)
|
|||||||
}
|
}
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
#ifdef HAVE_VASPRINTF
|
||||||
|
struct StringBuilder* builder = ThreadLocalGetValue(stringBuilder);
|
||||||
|
if (!builder) {
|
||||||
|
vfprintf(stderr, format, args);
|
||||||
|
} else {
|
||||||
|
vasprintf(StringListAppend(&builder->err), format, args);
|
||||||
|
}
|
||||||
|
#else
|
||||||
vfprintf(stderr, format, args);
|
vfprintf(stderr, format, args);
|
||||||
|
#endif
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIflush(struct StringList* list, FILE* out) {
|
||||||
|
size_t len = 0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < StringListSize(list); ++i) {
|
||||||
|
len += strlen(*StringListGetPointer(list, i));
|
||||||
|
}
|
||||||
|
char* string = calloc(len + 1, sizeof(char));
|
||||||
|
char* cur = string;
|
||||||
|
for (i = 0; i < StringListSize(list); ++i) {
|
||||||
|
char* brick = *StringListGetPointer(list, i);
|
||||||
|
size_t portion = strlen(brick);
|
||||||
|
memcpy(cur, brick, portion);
|
||||||
|
free(brick);
|
||||||
|
cur += portion;
|
||||||
|
}
|
||||||
|
fputs(string, out);
|
||||||
|
free(string);
|
||||||
|
StringListClear(list);
|
||||||
|
}
|
||||||
|
|
||||||
static bool parseCInemaArgs(int argc, char* const* argv) {
|
static bool parseCInemaArgs(int argc, char* const* argv) {
|
||||||
int ch;
|
int ch;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
@ -886,6 +930,11 @@ static bool CInemaTask(struct CInemaTestList* tests, size_t i) {
|
|||||||
|
|
||||||
static THREAD_ENTRY CInemaJob(void* context) {
|
static THREAD_ENTRY CInemaJob(void* context) {
|
||||||
struct CInemaTestList* tests = context;
|
struct CInemaTestList* tests = context;
|
||||||
|
struct StringBuilder builder;
|
||||||
|
StringListInit(&builder.out, 0);
|
||||||
|
StringListInit(&builder.err, 0);
|
||||||
|
ThreadLocalSetKey(stringBuilder, &builder);
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
while (true) {
|
while (true) {
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -899,12 +948,20 @@ static THREAD_ENTRY CInemaJob(void* context) {
|
|||||||
if (!CInemaTask(tests, i)) {
|
if (!CInemaTask(tests, i)) {
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
CIflush(&builder.out, stdout);
|
||||||
|
CIflush(&builder.err, stderr);
|
||||||
}
|
}
|
||||||
MutexLock(&jobMutex);
|
MutexLock(&jobMutex);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
jobStatus = 1;
|
jobStatus = 1;
|
||||||
}
|
}
|
||||||
MutexUnlock(&jobMutex);
|
MutexUnlock(&jobMutex);
|
||||||
|
|
||||||
|
CIflush(&builder.out, stdout);
|
||||||
|
StringListDeinit(&builder.out);
|
||||||
|
|
||||||
|
CIflush(&builder.err, stderr);
|
||||||
|
StringListDeinit(&builder.err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _log(struct mLogger* log, int category, enum mLogLevel level, const char* format, va_list args) {
|
void _log(struct mLogger* log, int category, enum mLogLevel level, const char* format, va_list args) {
|
||||||
@ -935,6 +992,9 @@ void _log(struct mLogger* log, int category, enum mLogLevel level, const char* f
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
ThreadLocalInitKey(&stringBuilder);
|
||||||
|
ThreadLocalSetKey(stringBuilder, NULL);
|
||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
if (!parseCInemaArgs(argc, argv)) {
|
if (!parseCInemaArgs(argc, argv)) {
|
||||||
status = 1;
|
status = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user