summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/include/IceUtil/Thread.h9
-rw-r--r--cpp/src/IceUtil/Thread.cpp34
-rw-r--r--cpp/test/IceUtil/thread/DetachTest.cpp97
-rw-r--r--cpp/test/IceUtil/thread/DetachTest.h31
-rw-r--r--cpp/test/IceUtil/thread/Makefile1
-rw-r--r--cpp/test/IceUtil/thread/TestSuite.cpp2
6 files changed, 173 insertions, 1 deletions
diff --git a/cpp/include/IceUtil/Thread.h b/cpp/include/IceUtil/Thread.h
index f9d954dee95..b7ffea27c9e 100644
--- a/cpp/include/IceUtil/Thread.h
+++ b/cpp/include/IceUtil/Thread.h
@@ -73,6 +73,14 @@ public:
//
void join();
+ //
+ // Detach a thread. Once a thread is detached, it cannot be detached
+ // again, nor can it be joined with. Every thread must either be
+ // joined with or detached exactly once. Failing to do so results
+ // in resource leaks.
+ //
+ void detach();
+
static void sleep(const Time&);
static void yield();
@@ -81,6 +89,7 @@ private:
#ifdef _WIN32
HandleWrapperPtr _handle;
unsigned _id;
+ bool _detached;
#else
pthread_t _id;
#endif
diff --git a/cpp/src/IceUtil/Thread.cpp b/cpp/src/IceUtil/Thread.cpp
index 41e96cc1ac7..86cb499cb5b 100644
--- a/cpp/src/IceUtil/Thread.cpp
+++ b/cpp/src/IceUtil/Thread.cpp
@@ -35,7 +35,8 @@ IceUtil::ThreadControl::ThreadControl() :
IceUtil::ThreadControl::ThreadControl(const HandleWrapperPtr& handle, unsigned id) :
_handle(handle),
- _id(id)
+ _id(id),
+ _detached(false)
{
}
@@ -62,6 +63,11 @@ IceUtil::ThreadControl::join()
{
if(_handle->handle)
{
+ if (_detached)
+ {
+ throw ThreadSyscallException(__FILE__, __LINE__);
+ }
+ _detached = true;
int rc = WaitForSingleObject(_handle->handle, INFINITE);
if(rc != WAIT_OBJECT_0)
{
@@ -71,6 +77,19 @@ IceUtil::ThreadControl::join()
}
void
+IceUtil::ThreadControl::detach()
+{
+ if(_handle->handle)
+ {
+ if (_detached)
+ {
+ throw ThreadSyscallException(__FILE__, __LINE__);
+ }
+ _detached = true;
+ }
+}
+
+void
IceUtil::ThreadControl::sleep(const Time& timeout)
{
timeval tv = timeout;
@@ -228,6 +247,19 @@ IceUtil::ThreadControl::join()
}
void
+IceUtil::ThreadControl::detach()
+{
+ if(_id)
+ {
+ int rc = pthread_detach(_id);
+ if(rc != 0)
+ {
+ throw ThreadSyscallException(__FILE__, __LINE__);
+ }
+ }
+}
+
+void
IceUtil::ThreadControl::sleep(const Time& timeout)
{
struct timeval tv = timeout;
diff --git a/cpp/test/IceUtil/thread/DetachTest.cpp b/cpp/test/IceUtil/thread/DetachTest.cpp
new file mode 100644
index 00000000000..bd7a5499f99
--- /dev/null
+++ b/cpp/test/IceUtil/thread/DetachTest.cpp
@@ -0,0 +1,97 @@
+// **********************************************************************
+//
+// Copyright (c) 2002
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <IceUtil/IceUtil.h>
+
+#include <stdio.h>
+
+#include <DetachTest.h>
+#include <TestCommon.h>
+
+using namespace std;
+using namespace IceUtil;
+
+static const string createTestName("thread detach");
+
+class DetachTestThread : public Thread
+{
+public:
+
+ DetachTestThread()
+ {
+ }
+
+ virtual void run()
+ {
+ }
+};
+
+typedef Handle<DetachTestThread> DetachTestThreadPtr;
+
+DetachTest::DetachTest() :
+ TestBase(createTestName)
+{
+}
+
+void
+DetachTest::run()
+{
+ //
+ // Check that calling join() more than once raises ThreadSyscallException.
+ //
+ DetachTestThreadPtr t = new DetachTestThread();
+ ThreadControl control = t->start();
+ control.join();
+ bool gotException = false;
+ try {
+ control.join();
+ }
+ catch(const ThreadSyscallException&)
+ {
+ gotException = true;
+ }
+ test(gotException);
+
+ //
+ // Check that calling detach() more than once raises ThreadSyscallException.
+ //
+ t = new DetachTestThread();
+ control = t->start();
+ control.detach();
+ gotException = false;
+ try {
+ control.detach();
+ }
+ catch(const ThreadSyscallException&)
+ {
+ gotException = true;
+ }
+ test(gotException);
+
+ //
+ // Check that calling join() after detach() raises ThreadSyscallException.
+ //
+ t = new DetachTestThread();
+ control = t->start();
+ control.detach();
+ gotException = false;
+ try {
+ control.join();
+ }
+ catch(const ThreadSyscallException&)
+ {
+ gotException = true;
+ }
+ test(gotException);
+}
diff --git a/cpp/test/IceUtil/thread/DetachTest.h b/cpp/test/IceUtil/thread/DetachTest.h
new file mode 100644
index 00000000000..b7b844ad9b4
--- /dev/null
+++ b/cpp/test/IceUtil/thread/DetachTest.h
@@ -0,0 +1,31 @@
+// **********************************************************************
+//
+// Copyright (c) 2002
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#ifndef DETACH_TEST_H
+#define DETACH_TEST_H
+
+#include <TestBase.h>
+
+class DetachTest : public TestBase
+{
+public:
+
+ DetachTest();
+
+private:
+
+ virtual void run();
+};
+
+#endif
diff --git a/cpp/test/IceUtil/thread/Makefile b/cpp/test/IceUtil/thread/Makefile
index 6beeb239e7c..ad5fa17752b 100644
--- a/cpp/test/IceUtil/thread/Makefile
+++ b/cpp/test/IceUtil/thread/Makefile
@@ -20,6 +20,7 @@ TARGETS = $(CLIENT)
OBJS = TestBase.o \
CreateTest.o \
+ DetachTest.o \
RWRecMutexTest.o \
RecMutexTest.o \
MutexTest.o \
diff --git a/cpp/test/IceUtil/thread/TestSuite.cpp b/cpp/test/IceUtil/thread/TestSuite.cpp
index 582509f9c9f..09d4e82fff6 100644
--- a/cpp/test/IceUtil/thread/TestSuite.cpp
+++ b/cpp/test/IceUtil/thread/TestSuite.cpp
@@ -17,6 +17,7 @@
#include <RecMutexTest.h>
#include <RWRecMutexTest.h>
#include <CreateTest.h>
+#include <DetachTest.h>
#include <MonitorMutexTest.h>
#include <MonitorRecMutexTest.h>
@@ -26,6 +27,7 @@ void
initializeTestSuite()
{
allTests.push_back(new CreateTest);
+ allTests.push_back(new DetachTest);
allTests.push_back(new MutexTest);
allTests.push_back(new RecMutexTest);
allTests.push_back(new RWRecMutexTest);