What I'm trying to do is have the terminal print out a string, pause, and then write over that string. What's happening though is that the program simply prints out the final result, without ever showing the first string.
I thought I could use sleep to do this, but it doesn't work. Why not?
#include <stdio.h>
#include <unistd.h>
int main(void){
char message[] = "Hello there";
int messageLength = sizeof(message);
int i;
printf("Hello, Dave.");
sleep(2);
for(i = 0; i < messageLength; i++)
printf("\b");
printf("Anyone there?\n");
return 0;
}
Updated version, thanks to answers:
#include <stdio.h>
#include <unistd.h>
#include <time.h>
void twprint(char* output, int outputLength, struct timespec* delay);
void twbackspace(int length, struct timespec* delay);
int main(void){
char message1[] = "Hello, Dave.";
char message2[] = "Are you there, Dave?";
char message3[] = "I heard you talking in the pod.";
char message4[] = "Dave?";
struct timespec duration = { .tv_sec = 0, .tv_nsec = (100 * 1000 * 1000) };
/* ^ .tv_nsec = one hundred million nanoseconds */
twprint(message1, sizeof(message1)/sizeof(char), &duration);
sleep(2);
twbackspace(sizeof(message1)/sizeof(char), &duration);
twprint(message2, sizeof(message2)/sizeof(char), &duration);
sleep(2);
twbackspace(sizeof(message2)/sizeof(char), &duration);
twprint(message3, sizeof(message3)/sizeof(char), &duration);
sleep(2);
twbackspace(sizeof(message3)/sizeof(char), &duration);
sleep(2);
duration.tv_nsec *= 5;
twprint(message4, sizeof(message4)/sizeof(char), &duration);
printf("\n");
return 0;
}
void twprint(char* output, int outputLength, struct timespec* delay){
int i;
struct timespec remaining; /* dummy parameter */
for(i = 0; i < outputLength; i++){
printf("%c", output[i]);
fflush(stdout);
nanosleep(delay, &remaining);
}
}
void twbackspace(int length, struct timespec* delay){
int i;
struct timespec remaining; /* dummy parameter */
for(i = 0; i < length; i++){
printf("\b \b");
fflush(stdout);
nanosleep(delay, &remaining);
}
}
The output of printf is buffered and won't be printed to the console until the buffer is full, you print a newline, or call fflush(stdout). Try:
...
printf("Hello, Dave.");
fflush(stdout);
sleep(2);
...
Wikipedia provides a good explanation of standard streams and their behavior with respect to buffering.
You need to flush the output stream to get the line to show up:
printf("Hello, Dave.");
fflush(stdout);
Normally, console output would go to stderr, by the way. If you did that, you wouldn't have to worry about flushing (on many platforms) because stderr is typically unbuffered (so output is immediate), whereas stdout is typically line-buffered (so output doesn't show up until you write a newline character).
Related
I wrote the following code to implement a periodic thread terminated when someone presses escape. The result is a periodic thread that continues also after i pressed escape.
Can you tell me where is the error please? The compiler compiles without any error and warning. Before reading the code jump to EDIT below.
#include <stdio.h>
#include <pthread.h>
#include <allegro.h>
#include <time.h>
void *task(void *p);
void time_add_ms(struct timespec *t, int ms);
int main()
{
int tret;
int a = 1;
allegro_init();
install_keyboard();
tret = pthread_create(&tid, NULL, task, (void*)&a);
pthread_join(tid, NULL);
printf("Thread1 returns %d\n", tret);
allegro_exit();
return 0;
}
/* Sommare quantità temporale espressa in ms al tempo nella struttura timespec */
void time_add_ms(struct timespec *t, int ms)
{
t->tv_sec += ms / 1000;
t->tv_nsec += (ms % 1000) * 1000000;
if (t->tv_nsec > 1000000000){
t->tv_nsec -= 1000000000;
t->tv_sec += 1;
}
}
/* Funzione da trasformare in task */
void *task(void *p)
{
struct timespec t;
int period = 100;
int *pi;
char scan = 0;
clock_gettime(CLOCK_MONOTONIC, &t);
time_add_ms(&t, period);
pi = (int *)p;
while (scan != KEY_ESC) {
if (keypressed()) scan = readkey() >> 8;
printf("This is TASK %d\n", *pi);
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t, NULL);
time_add_ms(&t, period);
}
}
EDIT: maybe i found the problem, when i press escape, it prints the symbol ^, so the compiler or allegro doen't recognize the esc key.
This is not exactly finding the error, but I think it is what you want (more details here)
If you add following code to your main(), this will disable canonical mode, which will basically enable you to get characters immediately without waiting for a '\n' or EOF (or enter keypress in short) (already explained in the link above):
#include <termios.h>
#include <unistd.h>
int main(){
static struct termios oldt, newt;
tcgetattr( STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON);
tcsetattr( STDIN_FILENO, TCSANOW, &newt);
// rest of your code
}
And the thread loop here (I've changed it a little bit)
while (1) {
printf("This is TASK %d\n", *pi);
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t, NULL);
time_add_ms(&t, period);
if(getchar()==27) break;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
pthread_mutex_t lock;
//typedef struct for a word
typedef struct {
char word[101];
int frequency;
}Word;
//struct for thread
struct ft{
char* fileName;
int start;
int stop;
};
//compare frequency of 2 words
int compareWords(const void *f1, const void *f2){
Word *a = (Word *)f1;
Word *b = (Word *)f2;
return (b->frequency - a->frequency);
}
//count frequency of a word
void countFrequency(void *arg){
pthread_mutex_lock(&lock);
int i, c;
struct ft* fi = (struct ft*)arg;
FILE *file = fopen(fi->fileName,"r");
fseek(file,fi->start,SEEK_SET);
for(i = 0; i < fi->stop - fi->start; i++){
c = getc(file);
//printf("%d\n", c);
//frequency count
}
fclose(file);
pthread_mutex_unlock(&lock);
}
int main (int argc, char **argv){
//variabies for <time.h>
struct timespec startTime;
struct timespec endTime;
clock_gettime(CLOCK_REALTIME, &startTime);
/*------------main------------------*/
//variables
int nthreads; //number of threads
int chunkSize; //each threas processing size
//if user input is not correct, inform
if(argc < 3){
printf("./a.out text_file #ofthreads \n");
exit(-1);
}
nthreads = atoi(argv[2]);
chunkSize = sizeof(argv[1])/nthreads;
//declare threads and default attributes
pthread_t threads[nthreads];
pthread_attr_t attr;
pthread_attr_init(&attr);
//run threads in parallel
int i;
for (i = 0; i < nthreads; i++){
struct ft data[nthreads];
data[i].start = i*chunkSize;
data[i].stop = data[i].start+chunkSize;
data[i].fileName = argv[1];
// Create a new thread for every segment, and count word frequency for each
pthread_create(&threads[i], &attr, (void*) countFrequency, (void*) &data[i]);
}
//wait for results (all threads)
for (i = 0; i < nthreads; i++){
pthread_join(threads[i], NULL);
}
//func of <time.h>
clock_gettime(CLOCK_REALTIME, &endTime);
time_t sec = endTime.tv_sec - startTime.tv_sec;
long n_sec = endTime.tv_nsec - startTime.tv_nsec;
if (endTime.tv_nsec < startTime.tv_nsec)
{
--sec;
n_sec = n_sec + 1000000000L;
}
printf("Total Time was %ld.%09ld seconds\n", sec, n_sec);
}
I'm working on this program to use multiple threads to read and process a large text file and perform a word count frequency of the top 10 most frequent words in the text that are longer than 6 characters long. But I keep getting the segmentation fault error im not sure why, does anybody have any idea.?
This code:
for (i = 0; i < nthreads; i++){
struct ft data[nthreads];
declares data that is live (legal to use) for the duration of this for loop. This code:
pthread_create(&threads[i], &attr, (void*) countFrequency, (void*) &data[i]);
}
passes the address of data into the threads, and then exits the loop. Once the loop is done, data is no longer live, and all access to it leads to undefined behavior.
The compiler is free to write anything else to the memory where data used to be.
The immediate cause of the crash is that if one of the threads doesn't execute fopen before data is overwritten, then fopen may fail, and you don't check for the failure in fopen.
P.S.
As Eraklon noted, this code: chunkSize = sizeof(argv[1])/nthreads; will divide sizeof(char*) (either 4 or 8 depending on whether you build for 32-bit or for 64-bit) by number of threads. That is unlikely to be what you want, and will yield chinkSize==0 for nthreads > 4 on 32-bit and nthreads > 8 on 64-bit machines.
P.P.S.
There is a concurrency bug in your program as well: since each of the countFrequency invocations locks the same lock for the entire duration, they will all run in sequence (one after another), never in parallel. Thus your program will be slower than if you just did all the work in your main thread.
I write a C code that reads a file and do some works on it, using multi-threads functions. I read file in the fun1 so I expect that file read linearly, but some tests I do on this code show me that it seems that the file does not read in the right order. What is wrong about my code?!
#include <pthread.h>
#define BUFSIZE 1024*10
#define NUM_THREADS 4
typedef struct _thread_data_t {
unsigned char id;
char *msg;
unsigned int msg_len;
} thread_data_t;
/* thread function */
void *thr_func(void *arg) {
thread_data_t *data = (thread_data_t *)arg;
fun2(data->msg, data->msg_len);
pthread_exit(NULL);
}
void fun1(FILE *file) {
unsigned char i, j, buf[BUFSIZE];
pthread_t thr[NUM_THREADS];
thread_data_t thr_data[NUM_THREADS];
int rc, fr, fd = fileno(file);
for (;;) {
for (i = 0; i < NUM_THREADS; i++) {
fr = read(fd, buf, BUFSIZE);
if (fr <= 0) break;
thr_data[i].id = i;
thr_data[i].msg = buf;
thr_data[i].msg_len = fr;
if ((rc = pthread_create(&thr[i], NULL, thr_func, &thr_data[i]))) {
fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
fr = -1;
break;
}
}
for (j = 0; j < i; j++) {
pthread_join(thr[j], NULL);
}
if (fr <= 0) break;
}
}
Edit:
I think that until all threads finish their works nothing new read from the file. Is it true?
I think your problem is the single buffer:
buf[BUFSIZE];
In each loop you read data into that buffer and then prepare data for the thread
thr_data[i].msg = buf;
which I assume doesn't include a copy of the buffer itself. I assume msg is just a pointer.
So in the next iteration, you'll overwrite the buf with new data from the file and consequently change data for already created threads.
I guess you'll need
buf[NUM_THREADS][BUFSIZE];
so that each thread gets its own data area to work on.
Quote:
I think that until all threads finish their works nothing new read from the file. Is it true?
Correct, that's what pthread_join does for you
I cant even get to print "Main" on the screen. It seems like none of my code runs. When i dont specify any command line arguments in prints out the warning. my input file contains integers on each line.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
int patientCount,treatedPatientCount,maxPatient,allRegistered;
int *list;
FILE *input,*output;
sem_t semOutputFile,semGlobalVars;
void* Nurse();
void* Doctor(void *);
int main( int argc, char *argv[] ){
printf("Main");
if(argc != 3){
printf("Command line argument count is different then expected. Aborting!");
return -1;
}
input = fopen(argv[1],"r");
output = fopen(argv[2],"w");
allRegistered = 0;
maxPatient = 5;
treatedPatientCount = 0;
patientCount = 0;
list = malloc(sizeof(int)*maxPatient);
pthread_t nurse,doc1,doc2;
sem_init(&semGlobalVars, 0, 1);
sem_init(&semOutputFile, 0, 1);
pthread_create(&nurse, NULL, &Nurse, NULL);
pthread_create(&doc1, NULL, &Doctor, (void*) 1);
pthread_create(&doc2, NULL, &Doctor, (void*) 2);
pthread_exit(NULL);
}
void* Nurse(){
char buff[255],*eof;
while(1){
eof = fgets(buff, 255, input);
if (eof == NULL) {
allRegistered = 1;
pthread_exit(NULL);
}
int k = atoi(buff);
sem_wait(&semGlobalVars);//Critical region 1 starts
if(patientCount == maxPatient){
maxPatient *=2;
list = realloc(list,sizeof(int)*maxPatient);
}
list[patientCount++] = k;
sem_post(&semGlobalVars);//Critical region 1 ends
sem_wait(&semOutputFile);//Critical region 2 starts
fputs("Nurse registered a patient!\n",output);
sem_post(&semOutputFile);//Critical region 2 ends
sleep(2);
}
}
void* Doctor(void * id){
printf("Doctor");
char buff[255];
int waitTime = 0;
while(1){
printf("%d %d %d",allRegistered,treatedPatientCount,patientCount);
if(allRegistered == 1 && treatedPatientCount==patientCount) pthread_exit(NULL);
sem_wait(&semGlobalVars);//Critical region 1 starts
waitTime = list[treatedPatientCount++];
sem_post(&semGlobalVars);//Critical region 1 ends
sprintf (buff, "Doctor %d treated a patient\n", (int) id);
sem_wait(&semOutputFile);//Critical region 2 starts
fputs(buff,output);
sem_post(&semOutputFile);//Critical region 2 ends
sleep(waitTime);
}
}
You can add exit(0) to the end of main
What exit(0) does is flush all buffers, (and other good things,) making sure anything that was buffered (like that printf of "Main") gets written out.
All C streams (open with functions in <cstdio>) are closed (and flushed, if buffered), and all files created with tmpfile are removed.
http://www.cplusplus.com/reference/cstdlib/exit/
I'm doing some really heavy and slow scientific simulations and I was wondering if it was possible to make my program show some information about its status when the user presses a key.
It doesn't need to be portable, just for linux.
Currently, I have a code of this kind:
main()
{
//SOME GLOBAL INITIALIZATIONS
//this loop is parallelized
for(i=0;i<max;i++)
{
//Some particular to i initializations
for(j=0;max2;j++)
{
// Here are all the slow and ugly calculations
// the status should be able to be shown when
// my program is here
}
}
// Final calculations and final data
}
Not sure if it is even possible, but sometimes one may think that the code is stopped or doing nothing, and this could be very helpful.
Also, if it is not possible to do this and use at the same time omp, I can use a more "manual" parallelization.
Thanks in advance!
You can use the pthreads library: Have one thread waiting for the key or whatever signal and when it is triggered. If you need to do some expensive computations to show the output variables, use a lock to stop execution of the simulation, print the variables and release the lock. Don't know if that can get to work with openmp thought.
If you just need to print the vars, there shouldn't be a problem in mixing pthreads and openmp.
You can use ncurses' getch()
#include <ctype.h>
#include <ncurses.h>
#include <stdio.h>
int keywaiting(int *key) {
int ch;
ch = getch();
if ((ch != ERR) && key) *key = ch;
return (ch != ERR);
}
int yourprogram(void) {
int max = 1000, max2 = 1000;
int i, j;
int ch;
/* SOME GLOBAL INITIALIZATIONS */
/* this loop is parallelized */
for (i = 0; i < max; i++) {
/* Some particular to i initializations */
for (j = 0; j < max2; j++) {
/* Here are all the slow and ugly calculations */
/* the status should be able to be shown when */
/* my program is here */
printf("%03d%03d\r", i, j);
if (keywaiting(&ch)) {
printf("\r\n\r\nAborted # i = %d; j = %d\r\n", i, j);
printf("Keypress %d ('%c')\r\n\n", ch, isprint((unsigned char)ch) ? ch : '.');
printf("Press any key ...");
refresh();
i = max;
j = max2;
}
}
}
/* Final calculations and final data */
return 0;
}
int main(void) {
/* initialize ncurses */
initscr();
nodelay(stdscr, TRUE);
noecho();
keypad(stdscr, TRUE);
curs_set(0);
yourprogram();
getchar();
/* done with ncurses */
clear();
refresh();
endwin();
return 0;
}
Don't forget to link with the curses library.
here's an example that uses signals (but partially written in c++, the signal handling is not):
//ctrl+c to output status, ctrl+z to quit
//#include <iostream> c++ syntax
#include <stdio.h>
#include <signal.h>
volatile sig_atomic_t showStatus = 0;
void signalHandler(int sig){
if (sig==SIGINT){
showStatus=1;
}
if (sig==SIGTSTP){
showStatus=2;
}
}
int main(int argc, char** argv){
signal(SIGINT,signalHandler);
signal(SIGTSTP,signalHandler);
while(true){
if (showStatus==1){
showStatus=0;
//std::cout << "status" << std::endl; c++ syntax
printf("status\n");
}else if(showStatus>1){
break;
}
}
return 0;
}
Ok, thanks for all your sugestions. I have managed to get something similar to what I wanted, It's not the same but will serve (^_^)
Here is the code, it just spawns a thread that will wait for a character, then 'switches' the report array from 0 to 1. When each omp thread starts each 'j' iteration they will check for the report and will report if needed.
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include <pthread.h>
#include <ncurses.h>
unsigned char *report; // this will store whether a thread has to report or not
int max_threads;
void *check_keyboard(void *whatever)
{
int c;
int i;
newterm(NULL,stdin,stdout); // I want to still see the terminal :)
noecho();
cbreak();
while(1)
{
if(getch())
{
for(i = 0; i < max_threads; i++)
report[i]=1;
}
}
return NULL;
}
int main(int argc, const char *argv[])
{
int i,j;
int tid;
pthread_t thread0;
max_threads = omp_get_max_threads();
report = malloc(max_threads*sizeof(unsigned char));
pthread_create(&thread0,NULL,check_keyboard,NULL);
#pragma omp parallel private(i,j,tid) shared(report)
{
tid = omp_get_thread_num();
#pragma omp for
for(i = 0; i < 10; i++)
{
for(j = 0; j < 10; j++)
{
#pragma omp critical
{
if(report[tid])
{
fprintf(stderr,"Hello World from thread %d\n\r",tid);
fprintf(stderr,"This is iteration i: %d, j: %d\n\r",i,j);
report[tid] = 0;
}
}
sleep(1); // This 'is' a test for the long and ugly code
}
}
}
pthread_cancel(thread0);
pthread_exit(NULL);
return 0;
}