summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/Semaphore_Test.cpp223
-rw-r--r--tests/Semaphore_Test.dsp70
2 files changed, 293 insertions, 0 deletions
diff --git a/tests/Semaphore_Test.cpp b/tests/Semaphore_Test.cpp
new file mode 100644
index 00000000000..5eab7585aab
--- /dev/null
+++ b/tests/Semaphore_Test.cpp
@@ -0,0 +1,223 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// Semaphore Test
+//
+// = DESCRIPTION
+// This test verifies the functionality of the ACE_OS semaphore
+// implementation. It is a variation of the Reader/Writer test
+//
+// = AUTHOR
+// Darrell Brunsch
+//
+// ============================================================================
+
+#include "ace/Synch.h"
+#include "ace/Thread.h"
+#include "ace/Service_Config.h"
+#include "ace/Get_Opt.h"
+#include "test_config.h"
+
+#if defined (ACE_HAS_THREADS)
+
+// Default number of iterations.
+static size_t n_iterations = 50;
+
+// Default number of loops.
+static size_t n_loops = 100;
+
+// Default number of readers.
+static size_t n_readers = 4;
+
+// Default number of writers.
+static size_t n_writers = 4;
+
+// Thread id of last writer.
+static ACE_thread_t shared_data;
+
+// Lock for shared_data.
+//static ACE_RW_Mutex rw_mutex;
+ACE_sema_t semaphore;
+
+// Count of the number of readers and writers.
+static ACE_Atomic_Op<ACE_Thread_Mutex, int> current_readers;
+static ACE_Atomic_Op<ACE_Thread_Mutex, int> current_writers;
+
+// Explain usage and exit.
+static void
+print_usage_and_die (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "usage: %n [-r n_readers] [-w n_writers] [-n iteration_count]\n"));
+ ACE_OS::exit (1);
+}
+
+static void
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, "r:w:n:");
+
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 'r':
+ n_readers = ACE_OS::atoi (get_opt.optarg);
+ break;
+ case 'w':
+ n_writers = ACE_OS::atoi (get_opt.optarg);
+ break;
+ case 'n':
+ n_iterations = atoi (get_opt.optarg);
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+// Iterate <n_iterations> each time checking that nobody modifies the data
+// while we have a read lock.
+
+static void *
+reader (void *)
+{
+ ACE_Thread_Control tc (ACE_Thread_Manager::instance ());
+ ACE_NEW_THREAD;
+
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) reader starting\n"));
+
+ for (size_t iterations = 1; iterations <= n_iterations; iterations++)
+ {
+ while (ACE_OS::sema_wait (&semaphore, ACE_Time_Value (0, 10000)))
+ ACE_DEBUG ((LM_DEBUG, " (%t) Reader waiting for lock...\n"));
+
+ if (current_writers > 0)
+ ACE_DEBUG ((LM_DEBUG, " (%t) writers found!!!\n"));
+
+ ACE_thread_t data = shared_data;
+
+ for (size_t loop = 1; loop <= n_loops; loop++)
+ {
+ ACE_Thread::yield ();
+
+ if (!ACE_OS::thr_equal (shared_data, data))
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) somebody changed %d to %d\n",
+ data, shared_data));
+ }
+
+ --current_readers;
+ //ACE_DEBUG ((LM_DEBUG, " (%t) done with reading guarded data\n"));
+
+ ACE_Thread::yield ();
+
+ ACE_OS::sema_post (&semaphore);
+ }
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) reader ending\n"));
+
+ return 0;
+}
+
+// Iterate <n_iterations> each time modifying the global data
+// and checking that nobody steps on it while we can write it.
+
+static void *
+writer (void *)
+{
+ ACE_Thread_Control tc (ACE_Thread_Manager::instance ());
+ ACE_NEW_THREAD;
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) writer starting\n"));
+
+ for (size_t iterations = 1; iterations <= n_iterations; iterations++)
+ {
+ while (ACE_OS::sema_wait (&semaphore, ACE_Time_Value (0, 10000)))
+ ACE_DEBUG ((LM_DEBUG, " (%t) Writer waiting for lock...\n"));
+
+ ++current_writers;
+
+ if (current_writers > 1)
+ ACE_DEBUG ((LM_DEBUG, " (%t) other writers found!!!\n"));
+
+ if (current_readers > 0)
+ ACE_DEBUG ((LM_DEBUG, " (%t) readers found!!!\n"));
+
+ ACE_thread_t self = ACE_Thread::self ();
+
+ shared_data = self;
+
+ for (size_t loop = 1; loop <= n_loops; loop++)
+ {
+ ACE_Thread::yield ();
+
+ if (!ACE_OS::thr_equal (shared_data, self))
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) somebody wrote on my data %d\n",
+ shared_data));
+ }
+
+ --current_writers;
+
+ //ACE_DEBUG ((LM_DEBUG, " (%t) done with guarded data\n"));
+ ACE_Thread::yield ();
+
+ ACE_OS::sema_post (&semaphore);
+ }
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) writer ending\n"));
+
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
+
+// Spawn off threads.
+
+int main (int argc, char *argv[])
+{
+ ACE_START_TEST ("Semaphore_Test");
+
+#if defined (ACE_HAS_THREADS)
+ parse_args (argc, argv);
+
+ ACE_OS::sema_init (&semaphore, 1);
+
+ current_readers = 0; // Possibly already done
+ current_writers = 0; // Possibly already done
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) main thread starting\n"));
+
+ if (ACE_Thread_Manager::instance ()->spawn_n (n_readers,
+ ACE_THR_FUNC (reader),
+ 0,
+ THR_NEW_LWP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn_n"), 1);
+ else if (ACE_Thread_Manager::instance ()->spawn_n (n_writers,
+ ACE_THR_FUNC (writer),
+ 0,
+ THR_NEW_LWP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn_n"), 1);
+
+ ACE_Thread_Manager::instance ()->wait ();
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) exiting main thread\n"));
+
+ ACE_OS::sema_destroy (&semaphore);
+#else
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+#endif /* ACE_HAS_THREADS */
+ ACE_END_TEST;
+ return 0;
+}
+
diff --git a/tests/Semaphore_Test.dsp b/tests/Semaphore_Test.dsp
new file mode 100644
index 00000000000..5430e4f197a
--- /dev/null
+++ b/tests/Semaphore_Test.dsp
@@ -0,0 +1,70 @@
+# Microsoft Developer Studio Project File - Name="Semaphore_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Semaphore_Test - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Semaphore_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Semaphore_Test.mak" CFG="Semaphore_Test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Semaphore_Test - Win32 Debug" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ace.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\ace"
+# Begin Target
+
+# Name "Semaphore_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp"
+# Begin Source File
+
+SOURCE=.\Semaphore_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h"
+# Begin Source File
+
+SOURCE=.\test_config.h
+# End Source File
+# End Group
+# End Target
+# End Project