Change print() implementation to accumulate string locally before printing.

The string to be printed is accumulated into a local buffer before being sent to
puts().  This ensure that if multiple threads are running and printing at the
same time, their output won't be interleaved (across individual print statements--
it still may be interleaved across different print statements, just like in C).

Issue #293.
This commit is contained in:
Matt Pharr
2012-06-21 14:41:53 -07:00
parent 3c10ddd46a
commit 50eb4bf53a

View File

@@ -59,22 +59,39 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
typedef int Bool; typedef int Bool;
#define PRINT_SCALAR(fmt, type) \ #define PRINT_BUF_SIZE 4096
printf(fmt, *((type *)ptr)); \
#define APPEND(str) \
do { \
int offset = bufp - &printString[0]; \
*bufp = '\0'; \
strncat(bufp, str, PRINT_BUF_SIZE-offset); \
bufp += strlen(str); \
if (bufp >= &printString[PRINT_BUF_SIZE]) \
goto done; \
} while (0) /* eat semicolon */
#define PRINT_SCALAR(fmt, type) \
sprintf(tmpBuf, fmt, *((type *)ptr)); \
APPEND(tmpBuf); \
break break
#define PRINT_VECTOR(fmt, type) \ #define PRINT_VECTOR(fmt, type) \
putchar('['); \ *bufp++ = '['; \
if (bufp == &printString[PRINT_BUF_SIZE]) break; \
for (int i = 0; i < width; ++i) { \ for (int i = 0; i < width; ++i) { \
/* only print the value if the current lane is executing */ \ /* only print the value if the current lane is executing */ \
if (mask & (1ull<<i)) \ if (mask & (1ull<<i)) \
printf(fmt, ((type *)ptr)[i]); \ sprintf(tmpBuf, fmt, ((type *)ptr)[i]); \
else \ else \
printf("((" fmt "))", ((type *)ptr)[i]); \ sprintf(tmpBuf, "((" fmt "))", ((type *)ptr)[i]); \
putchar(i != width-1 ? ',' : ']'); \ APPEND(tmpBuf); \
*bufp++ = (i != width-1 ? ',' : ']'); \
} \ } \
break break
@@ -91,14 +108,16 @@ typedef int Bool;
*/ */
void __do_print(const char *format, const char *types, int width, uint64_t mask, void __do_print(const char *format, const char *types, int width, uint64_t mask,
void **args) { void **args) {
if (mask == 0) char printString[PRINT_BUF_SIZE+1]; // +1 for trailing NUL
return; char *bufp = &printString[0];
char tmpBuf[256];
int argCount = 0; int argCount = 0;
while (*format) { while (*format && bufp < &printString[PRINT_BUF_SIZE]) {
// Format strings are just single percent signs. // Format strings are just single percent signs.
if (*format != '%') if (*format != '%') {
putchar(*format); *bufp++ = *format;
}
else { else {
if (*types) { if (*types) {
void *ptr = args[argCount++]; void *ptr = args[argCount++];
@@ -107,17 +126,22 @@ void __do_print(const char *format, const char *types, int width, uint64_t mask,
// printf() formatting string. // printf() formatting string.
switch (*types) { switch (*types) {
case 'b': { case 'b': {
printf("%s", *((Bool *)ptr) ? "true" : "false"); sprintf(tmpBuf, "%s", *((Bool *)ptr) ? "true" : "false");
APPEND(tmpBuf);
break; break;
} }
case 'B': { case 'B': {
putchar('['); *bufp++ = '[';
if (bufp == &printString[PRINT_BUF_SIZE])
break;
for (int i = 0; i < width; ++i) { for (int i = 0; i < width; ++i) {
if (mask & (1ull << i)) if (mask & (1ull << i)) {
printf("%s", ((Bool *)ptr)[i] ? "true" : "false"); sprintf(tmpBuf, "%s", ((Bool *)ptr)[i] ? "true" : "false");
APPEND(tmpBuf);
}
else else
printf("_________"); APPEND("_________");
putchar(i != width-1 ? ',' : ']'); *bufp++ = (i != width-1) ? ',' : ']';
} }
break; break;
} }
@@ -136,14 +160,18 @@ void __do_print(const char *format, const char *types, int width, uint64_t mask,
case 'p': PRINT_SCALAR("%p", void *); case 'p': PRINT_SCALAR("%p", void *);
case 'P': PRINT_VECTOR("%p", void *); case 'P': PRINT_VECTOR("%p", void *);
default: default:
printf("UNKNOWN TYPE "); APPEND("UNKNOWN TYPE ");
putchar(*types); *bufp++ = *types;
} }
++types; ++types;
} }
} }
++format; ++format;
} }
done:
*bufp = '\0';
puts(printString);
fflush(stdout); fflush(stdout);
} }