d
This commit is contained in:
31
c/ext/uthash/tests/threads/Makefile
Normal file
31
c/ext/uthash/tests/threads/Makefile
Normal file
@@ -0,0 +1,31 @@
|
||||
HASHDIR = ../../src
|
||||
PROGS = test1 test2
|
||||
|
||||
# Thread support requires compiler-specific options
|
||||
# ----------------------------------------------------------------------------
|
||||
# GNU
|
||||
CFLAGS += -I$(HASHDIR) -g -pthread
|
||||
# Solaris (Studio 11)
|
||||
#CFLAGS = -I$(HASHDIR) -g -mt
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(HASH_DEBUG),1)
|
||||
CFLAGS += -DHASH_DEBUG=1
|
||||
endif
|
||||
|
||||
all: $(PROGS) run_tests
|
||||
|
||||
$(PROGS) : $(HASHDIR)/uthash.h
|
||||
$(CC) $(CPPLFAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(@).c
|
||||
|
||||
debug:
|
||||
$(MAKE) all HASH_DEBUG=1
|
||||
|
||||
run_tests: $(PROGS)
|
||||
perl ../do_tests
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -f $(PROGS) test*.out
|
||||
rm -rf test*.dSYM
|
||||
2
c/ext/uthash/tests/threads/README
Normal file
2
c/ext/uthash/tests/threads/README
Normal file
@@ -0,0 +1,2 @@
|
||||
test1: exercise a two-reader, one-writer, rwlock-protected hash.
|
||||
test2: a template for a nthread, nloop kind of program
|
||||
22
c/ext/uthash/tests/threads/do_tests
Executable file
22
c/ext/uthash/tests/threads/do_tests
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my @tests;
|
||||
for (glob "test*[0-9]") {
|
||||
push @tests, $_ if -e "$_.ans";
|
||||
}
|
||||
|
||||
my $num_failed=0;
|
||||
|
||||
for my $test (@tests) {
|
||||
`./$test > $test.out 2> $test.err`;
|
||||
`diff $test.out $test.ans`;
|
||||
print "$test failed\n" if $?;
|
||||
$num_failed++ if $?;
|
||||
unlink "$test.err" if -z "$test.err";
|
||||
}
|
||||
|
||||
print scalar @tests . " tests conducted, $num_failed failed.\n";
|
||||
exit $num_failed;
|
||||
116
c/ext/uthash/tests/threads/test1.c
Normal file
116
c/ext/uthash/tests/threads/test1.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include "uthash.h"
|
||||
|
||||
#undef uthash_noexpand_fyi
|
||||
#define uthash_noexpand_fyi(tbl) fprintf(stderr,"warning: bucket expansion inhibited\n")
|
||||
|
||||
#define LOOPS 100000
|
||||
|
||||
typedef struct {
|
||||
int i;
|
||||
UT_hash_handle hh;
|
||||
} elt;
|
||||
|
||||
elt *elts=NULL; /* this is our hash table which two threads will use */
|
||||
pthread_rwlock_t lock;
|
||||
|
||||
void *thread_routine_r( void *arg ) {
|
||||
int i;
|
||||
long num_found=0;
|
||||
elt *e;
|
||||
|
||||
for(i=0;i<LOOPS;i++) {
|
||||
if (pthread_rwlock_rdlock(&lock) != 0) {
|
||||
fprintf(stderr,"can't acquire read lock\n");
|
||||
exit(-1);
|
||||
}
|
||||
HASH_FIND_INT(elts, &i, e);
|
||||
if (e) num_found++;
|
||||
pthread_rwlock_unlock(&lock);
|
||||
}
|
||||
return (void*)num_found;
|
||||
}
|
||||
void *thread_routine_w( void *arg ) {
|
||||
int i;
|
||||
long num_deld=0;
|
||||
elt *e;
|
||||
|
||||
for(i=0;i<LOOPS;i++) {
|
||||
if (pthread_rwlock_wrlock(&lock) != 0) {
|
||||
fprintf(stderr,"can't acquire write lock\n");
|
||||
exit(-1);
|
||||
}
|
||||
HASH_FIND_INT(elts, &i, e);
|
||||
if (e) {
|
||||
/* HASH_DEL(elts, e); */
|
||||
/* num_deld++; */
|
||||
} else {
|
||||
e = malloc(sizeof(elt));
|
||||
if (!e) exit(-1);
|
||||
e->i = i;
|
||||
HASH_ADD_INT(elts, i, e);
|
||||
}
|
||||
pthread_rwlock_unlock(&lock);
|
||||
}
|
||||
return (void*)num_deld;
|
||||
}
|
||||
|
||||
int main() {
|
||||
unsigned i;
|
||||
long num_added=0;
|
||||
int status;
|
||||
pthread_t thread_r1,thread_r2,thread_w1,thread_w2;
|
||||
void *thread_result;
|
||||
elt tmp, *e;
|
||||
|
||||
if (pthread_rwlock_init(&lock,NULL) != 0) {
|
||||
fprintf(stderr,"lock init failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (( status = pthread_create( &thread_r1, NULL, thread_routine_r, NULL) )) {
|
||||
printf("failure: status %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
if (( status = pthread_create( &thread_r2, NULL, thread_routine_r, NULL) )) {
|
||||
printf("failure: status %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
if (( status = pthread_create( &thread_w1, NULL, thread_routine_w, NULL) )) {
|
||||
printf("failure: status %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
if (( status = pthread_create( &thread_w2, NULL, thread_routine_w, NULL) )) {
|
||||
printf("failure: status %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = pthread_join( thread_r1, &thread_result );
|
||||
printf("thread result: %d %ld\n", status, (long)thread_result);
|
||||
|
||||
status = pthread_join( thread_r2, &thread_result );
|
||||
printf("thread result: %d %ld\n", status, (long)thread_result);
|
||||
|
||||
status = pthread_join( thread_w1, &thread_result );
|
||||
printf("thread result: %d %ld\n", status, (long)thread_result);
|
||||
|
||||
status = pthread_join( thread_w2, &thread_result );
|
||||
printf("thread result: %d %ld\n", status, (long)thread_result);
|
||||
|
||||
i = HASH_COUNT(elts);
|
||||
printf("final count of items in hash: %u\n", i);
|
||||
|
||||
if (pthread_rwlock_destroy(&lock) != 0) {
|
||||
fprintf(stderr,"lock destroy failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
75
c/ext/uthash/tests/threads/test2.c
Normal file
75
c/ext/uthash/tests/threads/test2.c
Normal file
@@ -0,0 +1,75 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include "uthash.h"
|
||||
|
||||
#undef uthash_noexpand_fyi
|
||||
#define uthash_noexpand_fyi(tbl) fprintf(stderr,"warning: bucket expansion inhibited\n");
|
||||
|
||||
#define LOOPS 100000
|
||||
#define NTHREADS 2
|
||||
|
||||
typedef struct {
|
||||
int i;
|
||||
int v;
|
||||
UT_hash_handle hh;
|
||||
} elt;
|
||||
|
||||
elt *elts=NULL; /* this is our hash table which two threads will use */
|
||||
pthread_rwlock_t lock;
|
||||
|
||||
void *thread_routine( void *arg ) {
|
||||
int keepgoing=0;
|
||||
/* TODO write me */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
unsigned i;
|
||||
long num_added=0;
|
||||
int status;
|
||||
pthread_t thread[NTHREADS];
|
||||
void *thread_result;
|
||||
elt tmp, *e;
|
||||
|
||||
if (pthread_rwlock_init(&lock,NULL) != 0) {
|
||||
fprintf(stderr,"lock init failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* populate it to start */
|
||||
for(i=0; i<LOOPS; i++) {
|
||||
e = malloc(sizeof(elt));
|
||||
if (!e) exit(-1);
|
||||
e->i = i;
|
||||
e->v = 0;
|
||||
HASH_ADD_INT(elts, i, e);
|
||||
}
|
||||
|
||||
for(i=0; i<NTHREADS; i++) {
|
||||
if (( status = pthread_create( &thread[i], NULL, thread_routine, NULL) )) {
|
||||
printf("failure: status %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<NTHREADS; i++) {
|
||||
status = pthread_join( thread[i], &thread_result );
|
||||
printf("thread result: %d %ld\n", status, (long)thread_result);
|
||||
}
|
||||
|
||||
i = HASH_COUNT(elts);
|
||||
printf("final count of items in hash: %u\n", i);
|
||||
|
||||
if (pthread_rwlock_destroy(&lock) != 0) {
|
||||
fprintf(stderr,"lock destroy failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user