Thursday, January 27, 2011

No need to multi-thread if one dones't have to ...

I like spend time writing, re-writing, reversing and hacking into codes. I consider myself a learner. Regarding multi-threaded codes, I keep a simple belief that almost all of them could be written using a single thread doing effectively the same thing. I realize the world isn't going to change because of what I believe. I wrote the following little piece to demonstrate a friend of mine that a multi-threaded version of one of his little projects which has a functions that blocks and responsible for a few other things (eg. write_db(), on_demand() ) could also have been written using a single-thread. For whatever it is worth, here is my little demo code:


#include < stdio.h >
#include < sys/time.h >
#include < signal.h >
#include < setjmp.h >

typedef void (*sighandler_t) (int);
sigjmp_buf saved_state;

struct data
{
unsigned int count;
unsigned int epoch;
double watt;
} d;

/*
* This value (in seconds) defines how often an
* attempt is made to read the serial port.
*/
unsigned int sleep_time = 10;
unsigned int sleep_start = 0; // in epoch seconds

/*
* Function to write into SQLite/RRD database.
*/
int write_db()
{
printf("[*] write_db()\n");
return 0;
}

/*
* Function to serve on-demand query.
*/
void on_demand()
{
printf("[*] on_demand() :: ");
printf("count %u now %u watt %.2f\n", d.count, d.epoch, d.watt);
fflush(stdout);
siglongjmp(saved_state, 1);
}

/*
* Function to read from serial port.
*/
int blocking_read()
{
struct timeval timeout;

printf("[*] blocking_read() :: ");

/* simulate the read() blocking-time */
timeout.tv_sec = 0;
timeout.tv_usec = 500;

select(0, NULL, NULL, NULL, &timeout);
d.count = d.count + 1;
d.epoch = time(NULL);
d.watt = random();

printf("count %u now %u watt %.2f\n", d.count, d.epoch, d.watt);
fflush(stdout);
return 0;
}

int main()
{
printf("[*] main() -- pid: %u\n\n", getpid());
fflush(stdout);

signal(SIGUSR1, (sighandler_t) on_demand);

while (1)
{
/*
* If we have just came out from a
* signal, perform the pending delay.
*/
sigsetjmp(saved_state, 1);
if ((int)(sleep_start + sleep_time - time(NULL)) > 0) {
printf("[-] pending delay %u secs\n",
(int)(sleep_start + sleep_time - time(NULL)));
fflush(stdout);
sleep((sleep_start + sleep_time) - time(NULL));
}

blocking_read();
write_db();
printf("\n");
fflush(stdout);

/*
* collect serial port data at
* each 'sleep_time' seconds.
*/
sleep_start = time(NULL);
sleep(sleep_time);
}
return 0;
}

0 comments:

Post a Comment