summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2010-09-02 21:48:14 +0200
committerAndreas Baumann <abaumann@yahoo.com>2010-09-02 21:48:14 +0200
commit81859cf3cad74a7d8cc5938255ac8daa1cf15514 (patch)
tree4419741200b9f5a1cc9a3f46aac754cb00a388f9
parent30b7a7c89a8fd0816fb32dc56916d5d5d8ee53b3 (diff)
downloadsqlitexx-81859cf3cad74a7d8cc5938255ac8daa1cf15514.tar.gz
sqlitexx-81859cf3cad74a7d8cc5938255ac8daa1cf15514.tar.bz2
added a threading test 9, but not working yet
-rw-r--r--tests/GNUmakefile2
-rw-r--r--tests/test9.MUST1
-rw-r--r--tests/test9.cpp104
-rw-r--r--tests/threads.c122
-rw-r--r--tests/threads.h137
5 files changed, 358 insertions, 8 deletions
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index c84d19b..87122a1 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -24,7 +24,7 @@ TEST_CPP_BINS = \
test6$(EXE) \
test7$(EXE) \
test8$(EXE) \
- test9$(EXE)
+ threads.o test9$(EXE)
TEST_BINS = \
testc$(EXE)
diff --git a/tests/test9.MUST b/tests/test9.MUST
index f4f0227..985eccc 100644
--- a/tests/test9.MUST
+++ b/tests/test9.MUST
@@ -1,2 +1,3 @@
creating DB..
connection object is sqlite3xx::connection(test9.db)
+create table..
diff --git a/tests/test9.cpp b/tests/test9.cpp
index af4a035..5b57a87 100644
--- a/tests/test9.cpp
+++ b/tests/test9.cpp
@@ -27,10 +27,80 @@
#if !defined _WIN32
#include <unistd.h>
#endif /* !defined _WIN32 */
+#include "threads.h"
using namespace sqlite3xx;
using namespace std;
+const int NOF_PRODUCERS = 2;
+const int NOF_CONSUMERS = 2;
+const int NOF_PRODUCER_TRANSACTIONS = 10;
+const int NOF_PRODUCER_OPS = 10;
+const int NOF_CONSUMER_TRANSACTIONS = 10;
+const int NOF_CONSUMER_OPS = 10;
+
+#define UNUSED( x ) if( 0 && (x) ) { }
+
+MUTEX_TYPE cout_mutex;
+
+static THREAD_FUNC_DECL produce( void *thread_data )
+{
+ UNUSED( thread_data );
+
+ try {
+ connection c( "test9.db" );
+ c.prepare( "ins", "insert into x values( ? )" )( "text", sqlite3xx::prepare::treat_direct );
+
+ for( int i = 0; i < NOF_PRODUCER_TRANSACTIONS; i++ ) {
+ work t( c, "ins" );
+ MUTEX_LOCK( cout_mutex );
+ cout << "producer transaction " << i << " started" << endl;
+ MUTEX_UNLOCK( cout_mutex );
+ for( int j = 0; j < NOF_PRODUCER_OPS; j++ ) {
+ result r = t.prepared( "ins" )( i * 1000 + j ).exec( );
+ assert( r.affected_rows( ) == 1 );
+ }
+ t.commit( );
+ }
+ } catch( sql_error& e ) {
+ cerr << "producer error, " << e.msg( ) << ": " << e.query( ) << endl;
+ }
+
+ THREAD_FUNC_RETURN;
+}
+
+static THREAD_FUNC_DECL consume( void *thread_data )
+{
+ UNUSED( thread_data );
+
+ try {
+ connection c( "test9.db" );
+ c.prepare( "sel", "select * from x" );
+
+ for( int i = 0; i < NOF_CONSUMER_TRANSACTIONS; i++ ) {
+ work t( c, "sel" );
+ MUTEX_LOCK( cout_mutex );
+ cout << "consumer transaction " << i << " started" << endl;
+ MUTEX_UNLOCK( cout_mutex );
+ for( int j = 0; j < NOF_CONSUMER_OPS; j++ ) {
+ result r = t.prepared( "sel" ).exec( );
+ for( result::const_iterator it = r.begin( ); it < r.end( ); it++ ) {
+ int x;
+ it["x"].to( x );
+ }
+ MUTEX_LOCK( cout_mutex );
+ cout << "consumer transaction got " << r.size( ) << " rows." << endl;
+ MUTEX_UNLOCK( cout_mutex );
+ }
+ t.commit( );
+ }
+ } catch( sql_error& e ) {
+ cerr << "consumer error, " << e.msg( ) << ": " << e.query( ) << endl;
+ }
+
+ THREAD_FUNC_RETURN;
+}
+
int main( ) {
(void)unlink( "test9.db" );
@@ -39,7 +109,34 @@ int main( ) {
connection c( "test9.db" );
cout << "connection object is " << c << endl;
+ cout << "create table.." << endl;
c.exec( "create table x( x integer )" );
+
+ // now have some threads creating data and some others
+ // consuming it. stupid, but should nicely stress the thing
+ THREAD_TYPE prod[NOF_PRODUCERS];
+ THREAD_TYPE cons[NOF_CONSUMERS];
+
+ MUTEX_SETUP( cout_mutex );
+
+ for( int i = 0; i < NOF_PRODUCERS; i++ ) {
+ THREAD_CREATE( &prod[i], produce, NULL );
+ }
+
+ for( int i = 0; i < NOF_CONSUMERS; i++ ) {
+ THREAD_CREATE( &cons[i], consume, NULL );
+ }
+
+ for( int i = 0; i < NOF_PRODUCERS; i++ ) {
+ THREAD_JOIN( prod[i] );
+ }
+
+ for( int i = 0; i < NOF_CONSUMERS; i++ ) {
+ THREAD_JOIN( cons[i] );
+ }
+
+ MUTEX_CLEANUP( cout_mutex );
+
} catch( sql_error& e ) {
cerr << e.msg( ) << ": " << e.query( ) << endl;
}
@@ -48,13 +145,6 @@ int main( ) {
/*
try {
- cout << "starting transaction.." << endl;
- work wc( c, "create" );
-
- cout << "create table.." << endl;
- wc.exec( "create table a( i integer, d double, s text, t text )" );
- wc.commit( );
-
work wi( c, "insert" );
cout << "insert some data.." << endl;
c.prepare( "ins", "insert into a( i, d, s, t ) values( NULL, NULL, NULL, ? )" )
diff --git a/tests/threads.c b/tests/threads.c
new file mode 100644
index 0000000..98195de
--- /dev/null
+++ b/tests/threads.c
@@ -0,0 +1,122 @@
+/*
+ threads.c
+
+ Posix and Windows threads
+
+gSOAP XML Web services tools
+Copyright (C) 2000-2009, Robert van Engelen, Genivia Inc., All Rights Reserved.
+This part of the software is released under one of the following licenses:
+GPL, the gSOAP public license, or Genivia's license for commercial use.
+--------------------------------------------------------------------------------
+gSOAP public license.
+
+The contents of this file are subject to the gSOAP Public License Version 1.3
+(the "License"); you may not use this file except in compliance with the
+License. You may obtain a copy of the License at
+http://www.cs.fsu.edu/~engelen/soaplicense.html
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the License.
+
+The Initial Developer of the Original Code is Robert A. van Engelen.
+Copyright (C) 2000-2009, Robert van Engelen, Genivia Inc., All Rights Reserved.
+--------------------------------------------------------------------------------
+GPL license.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+Author contact information:
+engelen@genivia.com / engelen@acm.org
+
+This program is released under the GPL with the additional exemption that
+compiling, linking, and/or using OpenSSL is allowed.
+--------------------------------------------------------------------------------
+A commercial use license is available from Genivia, Inc., contact@genivia.com
+--------------------------------------------------------------------------------
+*/
+
+#include "threads.h"
+
+/******************************************************************************\
+ *
+ * Emulation of POSIX condition variables for WIN32
+ *
+\******************************************************************************/
+
+#ifdef WIN32
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int emulate_pthread_cond_init(COND_TYPE *cv)
+{
+ cv->waiters_count_ = 0;
+ cv->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
+ InitializeCriticalSection(&cv->waiters_count_lock_);
+
+ return 0;
+}
+
+int emulate_pthread_cond_destroy(COND_TYPE *cv)
+{
+ CloseHandle(cv->signal_event_);
+ DeleteCriticalSection(&cv->waiters_count_lock_);
+
+ return 0;
+}
+
+int emulate_pthread_cond_signal(COND_TYPE *cv)
+{
+ int have_waiters;
+
+ EnterCriticalSection(&cv->waiters_count_lock_);
+ have_waiters = cv->waiters_count_ > 0;
+ LeaveCriticalSection(&cv->waiters_count_lock_);
+
+ if (have_waiters)
+ return SetEvent(cv->signal_event_) == 0;
+
+ return 0;
+}
+
+int emulate_pthread_cond_wait(COND_TYPE *cv, MUTEX_TYPE *cs)
+{
+ int result;
+
+ EnterCriticalSection(&cv->waiters_count_lock_);
+ cv->waiters_count_++;
+ LeaveCriticalSection(&cv->waiters_count_lock_);
+
+ ReleaseMutex(*cs);
+
+ result = (WaitForSingleObject(cv->signal_event_, INFINITE) == WAIT_FAILED);
+
+ if (!result)
+ {
+ EnterCriticalSection(&cv->waiters_count_lock_);
+ cv->waiters_count_--;
+ LeaveCriticalSection(&cv->waiters_count_lock_);
+
+ result = (WaitForSingleObject(*cs, INFINITE) == WAIT_FAILED);
+ }
+
+ return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tests/threads.h b/tests/threads.h
new file mode 100644
index 0000000..dec8ddc
--- /dev/null
+++ b/tests/threads.h
@@ -0,0 +1,137 @@
+/*
+ threads.h
+
+ Posix and Windows threads interface
+
+gSOAP XML Web services tools
+Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved.
+This part of the software is released under one of the following licenses:
+GPL, the gSOAP public license, or Genivia's license for commercial use.
+--------------------------------------------------------------------------------
+gSOAP public license.
+
+The contents of this file are subject to the gSOAP Public License Version 1.3
+(the "License"); you may not use this file except in compliance with the
+License. You may obtain a copy of the License at
+http://www.cs.fsu.edu/~engelen/soaplicense.html
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the License.
+
+The Initial Developer of the Original Code is Robert A. van Engelen.
+Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved.
+--------------------------------------------------------------------------------
+GPL license.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+Author contact information:
+engelen@genivia.com / engelen@acm.org
+
+This program is released under the GPL with the additional exemption that
+compiling, linking, and/or using OpenSSL is allowed.
+--------------------------------------------------------------------------------
+A commercial use license is available from Genivia, Inc., contact@genivia.com
+--------------------------------------------------------------------------------
+*/
+
+#ifndef THREADS_H
+#define THREADS_H
+
+#ifndef _WIN32
+# include <unistd.h> /* defines _POSIX_THREADS if pthreads are available */
+#else
+# define ssize_t int
+# include <io.h>
+# include <sys/types.h>
+# include <process.h>
+# include <windows.h>
+#endif
+
+#if defined(_POSIX_THREADS) || defined(_SC_THREADS)
+# include <pthread.h>
+#endif
+
+/******************************************************************************\
+ *
+ * Threads
+ *
+\******************************************************************************/
+
+#if defined(_WIN32)
+# define SLEEP(x) Sleep((x) * 1000)
+# define THREAD_TYPE HANDLE
+# define THREAD_FUNC_DECL unsigned int _stdcall
+# define THREAD_FUNC_RETURN return 0;
+# define THREAD_ID GetCurrentThreadId()
+# define THREAD_CREATE(x,y,z) *(x) = (HANDLE)_beginthreadex( NULL, 8*4096, (y), (z), 0, NULL)
+# define THREAD_DETACH(x)
+# define THREAD_JOIN(x) WaitForSingleObject((x), INFINITE)
+# define THREAD_EXIT _endthread()
+# define MUTEX_TYPE HANDLE
+# define MUTEX_INITIALIZER CreateMutex(NULL, FALSE, NULL)
+# define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
+# define MUTEX_CLEANUP(x) CloseHandle(x)
+# define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
+# define MUTEX_UNLOCK(x) ReleaseMutex(x)
+# define COND_SETUP(x) emulate_pthread_cond_init(&(x))
+# define COND_CLEANUP(x) emulate_pthread_cond_destroy(&(x))
+# define COND_SIGNAL(x) emulate_pthread_cond_signal(&(x))
+# define COND_WAIT(x,y) emulate_pthread_cond_wait(&(x), &(y))
+typedef struct
+{ u_int waiters_count_;
+ CRITICAL_SECTION waiters_count_lock_;
+ HANDLE signal_event_;
+} COND_TYPE;
+#ifdef __cplusplus
+extern "C" {
+#endif
+int emulate_pthread_cond_init(COND_TYPE*);
+int emulate_pthread_cond_destroy(COND_TYPE*);
+int emulate_pthread_cond_signal(COND_TYPE*);
+int emulate_pthread_cond_wait(COND_TYPE*, MUTEX_TYPE*);
+#ifdef __cplusplus
+}
+#endif
+#elif defined(_POSIX_THREADS) || defined(_SC_THREADS)
+# define SLEEP(x) sleep(x)
+# define THREAD_TYPE pthread_t
+# define THREAD_FUNC_DECL void *
+# define THREAD_FUNC_RETURN return NULL;
+# define THREAD_ID pthread_self()
+# define THREAD_CREATE(x,y,z) pthread_create((x), NULL, (y), (z))
+# define THREAD_DETACH(x) pthread_detach((x))
+# define THREAD_JOIN(x) pthread_join((x), NULL)
+# define THREAD_EXIT pthread_exit(NULL)
+# define MUTEX_TYPE pthread_mutex_t
+# define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+# define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
+# define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
+#if 0 /* 1: DEBUG MUTEX */
+# define MUTEX_LOCK(x) (fprintf(stderr, "! LOCK %p %s:%d\n", &x, __FILE__, __LINE__), pthread_mutex_lock(&(x)))
+# define MUTEX_UNLOCK(x) (fprintf(stderr, "! UNLOCK %p %s:%d\n", &x, __FILE__, __LINE__), pthread_mutex_unlock(&(x)))
+#else
+# define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
+# define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
+#endif
+# define COND_TYPE pthread_cond_t
+# define COND_SETUP(x) pthread_cond_init(&(x), NULL)
+# define COND_CLEANUP(x) pthread_cond_destroy(&(x))
+# define COND_SIGNAL(x) pthread_cond_signal(&(x))
+# define COND_WAIT(x,y) pthread_cond_wait(&(x), &(y))
+#else
+# error "No POSIX threads detected: we need thread and mutex operations. See for example OpenSSL /threads/th-lock.c on how to implement mutex on your platform"
+#endif
+
+#endif