Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[6model/c] gather returned data from multiple threads, Configure fixes
  • Loading branch information
mberends committed Aug 8, 2011
1 parent 2bed502 commit d7d1a10
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 124 deletions.
138 changes: 69 additions & 69 deletions c/Configure.bat
@@ -1,69 +1,69 @@
:: Configure.bat

:: This script should work on a Microsoft Windows operating system with
:: either Microsoft Visual C++ or GNU Compiler Collection gcc.

:: TODO
:: - Add a --help option and provide for more options in general

@echo off
:: Determine whether the C compiler is MSVC or GCC, by attempting to use
:: them in that order.
echo int main(int argc, char * argv[]) { return 0; } >tools\build\temp.c
cl -nologo -Fotools\build\temp.obj -Fetools\build\temp.exe tools\build\temp.c >nul 2>nul
if not errorlevel 1 goto :msvc
gcc -otools\build\temp.exe tools\build\temp.c
if not errorlevel 1 goto :gcc
cc tools\build\temp.c
if not errorlevel 1 goto :cc
echo Sorry! Cannot compile with eith cl, gcc or cc. Please fix.
if exist tools\build\temp.exe del tools\build\temp.exe
if exist tools\build\temp.obj del tools\build\temp.obj
if exist tools\build\temp.c del tools\build\temp.c
goto :end_of_script
:msvc
echo Detected Microsoft Visual C/C++ (cl.exe)
del tools\build\temp.obj tools\build\temp.exe tools\build\temp.c
set COMPILER=MSVC
goto :got_compiler
:gcc
echo Detected GNU Compiler Collection (gcc.exe)
del tools\build\temp.exe tools\build\temp.c
set COMPILER=GCC
goto :got_compiler
:cc

:got_compiler
echo Compiling tools\build\Configure.c to tools\build\Configure.exe

:: !!! FUD WARNING !!!
:: Microsoft thinks that C programmers should rewrite every call to,
:: for example, strcpy, replacing it with their more "secure"
:: replacement called strcpy_s, which takes additional parameters to
:: avoid buffer overruns. Microsoft's C compilers emit many loud
:: warnings containing weasel words such as "fopen ... may be unsafe".
:: http://msdn.microsoft.com/en-us/library/8ef0s5kh%28v=VS.100%29.aspx
:: Talk about a brazen lock-in attempt! Since other target platforms
:: are not blessed with strcpy_s and so on, this project opts to
:: continue using the "older, less secure functions" and disable the
:: warnings with -D_CRT_SECURE_NO_WARNINGS
set opts_msvc=-nologo -Wall -DCC=MSVC -D_CRT_SECURE_NO_WARNINGS
set opts_gcc=-Wall -DCC=GCC
if "%COMPILER%"=="MSVC" cl %opts_msvc% -Fotools\build\Configure.obj -Fetools\build\Configure.exe tools\build\Configure.c
if "%COMPILER%"=="GCC" gcc %opts_gcc% -otools\build\Configure.exe tools\build\Configure.c
if errorlevel 1 goto :end_of_script
if exist tools\build\Configure.obj del tools\build\Configure.obj
:: echo Run tools\build\Configure.exe to create Makefile
tools\build\Configure.exe tools\build\Makefile.in Makefile

:end_of_script

:: Notes

:: Configure.bat or Configure.cmd?
:: There is almost no difference between the two file types (just something
:: subtle about errorlevel), and in 6model/c they work the same. So on user
:: friendliness grounds, .bat reassures the reader that the script will do
:: only "simple" things.
:: You could argue it the other way - we use cmd.exe, not command.com, so we
:: should use the extension that command.com cannot handle. Dunno...
:: Configure.bat

:: This script should work on a Microsoft Windows operating system with
:: either Microsoft Visual C++ or GNU Compiler Collection gcc.

:: TODO
:: - Add a --help option and provide for more options in general

@echo off
:: Determine whether the C compiler is MSVC or GCC, by attempting to use
:: them in that order.
echo int main(int argc, char * argv[]) { return 0; } >tools\build\temp.c
cl -nologo -Fotools\build\temp.obj -Fetools\build\temp.exe tools\build\temp.c >nul 2>nul
if not errorlevel 1 goto :msvc
gcc -otools\build\temp.exe tools\build\temp.c
if not errorlevel 1 goto :gcc
cc tools\build\temp.c
if not errorlevel 1 goto :cc
echo Sorry! Cannot compile with eith cl, gcc or cc. Please fix.
if exist tools\build\temp.exe del tools\build\temp.exe
if exist tools\build\temp.obj del tools\build\temp.obj
if exist tools\build\temp.c del tools\build\temp.c
goto :end_of_script
:msvc
echo Detected Microsoft Visual C/C++ (cl.exe)
del tools\build\temp.obj tools\build\temp.exe tools\build\temp.c
set COMPILER=MSVC
goto :got_compiler
:gcc
echo Detected GNU Compiler Collection (gcc.exe)
del tools\build\temp.exe tools\build\temp.c
set COMPILER=GCC
goto :got_compiler
:cc

:got_compiler
echo Compiling tools\build\Configure.c to tools\build\Configure.exe

:: !!! FUD WARNING !!!
:: Microsoft thinks that C programmers should rewrite every call to,
:: for example, strcpy, replacing it with their more "secure"
:: replacement called strcpy_s, which takes additional parameters to
:: avoid buffer overruns. Microsoft's C compilers emit many loud
:: warnings containing weasel words such as "fopen ... may be unsafe".
:: http://msdn.microsoft.com/en-us/library/8ef0s5kh%28v=VS.100%29.aspx
:: Talk about a brazen lock-in attempt! Since other target platforms
:: are not blessed with strcpy_s and so on, this project opts to
:: continue using the "older, less secure functions" and disable the
:: warnings with -D_CRT_SECURE_NO_WARNINGS
set opts_msvc=-nologo -Wall -DCC=MSVC -D_CRT_SECURE_NO_WARNINGS -wd4820 -wd4668 -wd4255
set opts_gcc=-Wall -DCC=GCC
if "%COMPILER%"=="MSVC" cl %opts_msvc% -Fotools\build\Configure.obj -Fetools\build\Configure.exe tools\build\Configure.c
if "%COMPILER%"=="GCC" gcc %opts_gcc% -otools\build\Configure.exe tools\build\Configure.c
if errorlevel 1 goto :end_of_script
if exist tools\build\Configure.obj del tools\build\Configure.obj
:: echo Run tools\build\Configure.exe to create Makefile
tools\build\Configure.exe tools\build\Makefile.in Makefile

:end_of_script

:: Notes

:: Configure.bat or Configure.cmd?
:: There is almost no difference between the two file types (just something
:: subtle about errorlevel), and in 6model/c they work the same. So on user
:: friendliness grounds, .bat reassures the reader that the script will do
:: only "simple" things.
:: You could argue it the other way - we use cmd.exe, not command.com, so we
:: should use the extension that command.com cannot handle. Dunno...
142 changes: 127 additions & 15 deletions c/t/01-toolchain/01c-threads.c
@@ -1,20 +1,21 @@
/* 01c-threads.c */
/* Check that threading in the operating system and libraries are ok */
/* Check that threading in the operating system and libraries is ok */


#include <stdio.h> /* perror printf */
#include <stdlib.h> /* system */
#include "../Test.h" /* is_ii plan */
#include <assert.h> /* assert */
#include <stdio.h> /* perror printf */
#include <stdlib.h> /* system */
#include <string.h> /* strlen */
#include "../Test.h" /* diag is_ii ok plan */

#ifdef _WIN32
#include <windows.h>
#define sleep(seconds) Sleep(seconds*1000)
#else
#include <pthread.h> /* pthread_create */
#include <pthread.h> /* pthread_create pthread_join */
#endif


struct threadargs {
struct test1_threadargs {
int testnumber;
int seconds;
char * description;
Expand All @@ -25,17 +26,24 @@ struct threadargs {
void *
test1_thread(void * args)
{
struct threadargs * targs = (struct threadargs *) args;
int testnumber = targs->testnumber;
char * description = targs->description;
int testnumber;
char * description;
char message[80];
struct test1_threadargs * targs;

targs = (struct test1_threadargs *) args;
testnumber = targs->testnumber;
description = targs->description;
sleep(targs->seconds);
printf("ok %d - from %s thread\n", testnumber, description);
sprintf(message, "from %s thread", description);
ok(1, message);
return NULL;
}


/* tests_1_4 */
void
tests1_4()
tests1_4sleeps()
{
int status;
#ifdef _WIN32
Expand All @@ -46,7 +54,7 @@ tests1_4()
pthread_attr_t thread_attr;
#endif
int threadnumber, threadstacksize;
struct threadargs thread1arguments, thread2arguments;
struct test1_threadargs thread1arguments, thread2arguments;

/* Create the first thread */
thread1arguments.testnumber = 3;
Expand Down Expand Up @@ -90,13 +98,117 @@ tests1_4()
}


/* charcount_args */
/* Input and output parameters for the threaded charcount test */
struct charcount_args {
char * textdata;
int textlength;
char sought;
int finds;
};


/* charcount */
void *
charcount(void * argptr)
{
char * s, sought;
int len, count;
struct charcount_args * args;
args = (struct charcount_args *) argptr;
s = args->textdata;
len = args->textlength;
sought = args->sought;
count = 0;
while (len--) {
if (* s++ == sought) {
++count;
}
}
args->finds = count;
return NULL;
}


/* tests5_6charcount */
/* */
void
tests5_6charcount()
{
char message[80], s01[] =
"Mostly, we're just a bunch of ants all cooperating (sort of) to haul"
"food toward the nest (on average). There are many groups of people"
"working on various bits and pieces as they see fit, since this is"
"primarily a volunteer effort.";
struct charcount_args args[4];
int i, sublength, threadstacksize, status, totalfinds;
#ifdef _WIN32
HANDLE threadhandle[4];
DWORD threadId[4];
#else
pthread_t thread_id[4];
pthread_attr_t thread_attr;
#endif

/* Prepare search arguments for four search threads each dealing */
/* with a substring */
sublength = strlen(s01) / 4;
for (i=0; i<4; ++i) {
args[i].textdata = s01 + i * sublength;
args[i].textlength = i < 3 ? sublength : (strlen(s01) - 3 * sublength);
args[i].sought = ' ';
args[i].finds = -1;
}

/* Start the four search threads */
threadstacksize = 16384; /* Minimum allowed by Posix threads */
for (i=0; i<4; ++i) {
#ifdef _WIN32
threadhandle[i] = CreateThread(NULL, threadstacksize,
(LPTHREAD_START_ROUTINE) charcount, &args[i], 0,
&threadId[i]);
status = (threadhandle[i] == NULL);
#else
status = pthread_attr_init(&thread_attr);
pthread_attr_setstacksize(&thread_attr, threadstacksize);
status = pthread_create(&thread_id[i], &thread_attr,
charcount, &args[i]);
#endif
assert( status == 0 );
}

/* Wait for the four threads to finish */
totalfinds = 0;
for (i=0; i<4; ++i) {
#ifdef _WIN32
status = WaitForSingleObject(threadhandle[i], INFINITE);
#else
status = pthread_join(thread_id[i], NULL);
#endif
totalfinds += args[i].finds;
assert( status == 0 );
}

/* Perform a single search in the main thread */
args[0].textdata = s01;
args[0].textlength = strlen(s01);
args[0].sought = ' ';
args[0].finds = -1;
charcount(&args[0]);
sprintf(message, "found %d occurrences of '%c' both single and "
"multi threaded", args[0].finds, args[0].sought);
ok(args[0].finds == totalfinds, message);
}


/* main */
int
main(int arg, char * argv[])
{
diag("01c-threads");
plan(4);
tests1_4(); /* two simple child threads */
plan(5);
tests1_4sleeps(); /* two threads that sleep and print */
tests5_6charcount(); /* four threads returning integers */
return 0;
}

Expand Down
17 changes: 5 additions & 12 deletions c/t/02-components/02a-hashtable.c
Expand Up @@ -9,7 +9,6 @@
#include <stdio.h> /* printf */
#include <stdlib.h> /* malloc */
#include <string.h> /* memmove strlen */
#include <sys/time.h> /* gettimeofday */
#include "../../src/hashtable.h"
#include "../Test.h" /* diag is plan */

Expand Down Expand Up @@ -90,29 +89,24 @@ random_string(int maxlength)
/* main */
int main(int argc, char *argv[])
{
struct timeval time_now, time_write, time_read;
struct hashtable * hashtable;
struct hashtable_iterator iter;
struct hashtable_entry entry;
void * valuepointer;
int valueint, seed, stringcount = 0, stringlength, key_bytes = 0,
int valueint, seed = 0, stringcount = 0, stringlength, key_bytes = 0,
value_bytes = 0, entrynumber, collisions = 0, delete_count;
char * source, * destination;
char * source, * destination, * value;

diag("02a-hashtable");
plan(4);
gettimeofday(&time_now, NULL);
time_write.tv_sec = time_now.tv_sec + 5;
time_write.tv_usec = time_now.tv_usec;
seed = time_now.tv_sec ^ time_now.tv_usec;
hashtable = hashtable_new();
srand(seed);
srand(seed); /* TODO: get a portable seed from for example current time */
while (stringcount<STRINGCOUNT) { /* nondeterministic because of collisions */
char * key = random_string(MAXKEYLENGTH);
/* create a value consisting of the key reversed followed by */
/* the original key, for example 'abc' -> 'cbaabc' */
stringlength = strlen(key);
char * value = (char *) malloc(2 * stringlength + 1);
value = (char *) malloc(2 * stringlength + 1);
destination=value+stringlength;
* destination -- = '\0';
for (source=key; stringlength-->0; ) {
Expand All @@ -133,7 +127,6 @@ int main(int argc, char *argv[])
value_bytes += strlen(value);
++ stringcount;
}
gettimeofday(&time_now, NULL);
}
is_ii( stringcount, STRINGCOUNT, "created a hash with 5000 entries");
srand(seed);
Expand Down Expand Up @@ -167,4 +160,4 @@ int main(int argc, char *argv[])
}
#endif

/* end of 02a-hashtable.c */
/* end of 02a-hashtable.c */

0 comments on commit d7d1a10

Please sign in to comment.