diff --git a/.gitignore b/.gitignore
index d8fe4fa..689ad02 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
/.project
+
+# Mac
+.DS_Store
diff --git a/src/main/c++/java/threadsocket/ThreadPosix.cpp b/src/main/c++/java/threadsocket/ThreadPosix.cpp
new file mode 100644
index 0000000..b2e37de
--- /dev/null
+++ b/src/main/c++/java/threadsocket/ThreadPosix.cpp
@@ -0,0 +1,170 @@
+#include "ThreadPosix.hpp"
+
+/////////////////////////////////////////
+//Thread class
+/////////////////////////////////////////
+Thread::Thread(void* (*start_routine)(void*), void *arg, pthread_attr_t *attr) {
+ int error = pthread_create(&m_thread,attr,start_routine,arg);
+ ASSERT(error==0)
+ (void) error;
+}
+
+void* Thread::join() {
+ void* returnValuePtr;
+ int error = pthread_join(m_thread, &returnValuePtr);
+ ASSERT(error == 0);
+ (void) error;
+ return returnValuePtr;
+}
+
+//THIS FUNCTION IS STATIC
+void Thread::endThread(void *returnValue) {
+ pthread_exit(returnValue);
+}
+
+
+/////////////////////////////////////////
+//Lock class
+/////////////////////////////////////////
+Lock Lock::masterLock = Lock();
+
+Lock::Lock(int type) {
+ m_shouldDeleteMutex = true;
+ m_shouldDeleteAttr = true;
+ m_attr = new pthread_mutexattr_t;
+ pthread_mutexattr_settype(m_attr, type);
+ m_mutex = new pthread_mutex_t;
+ int error = pthread_mutex_init(m_mutex, m_attr);
+ ASSERT(error==0)
+ (void) error;
+}
+
+Lock::Lock(pthread_mutex_t* mutex) {
+ m_mutex = mutex;
+ m_shouldDeleteMutex = false;
+ m_shouldDeleteAttr = false;
+}
+
+Lock::~Lock() {
+ if(m_shouldDeleteMutex){
+ int error = pthread_mutex_destroy(m_mutex);
+ ASSERT(error==0)
+ (void) error;
+ delete m_mutex;
+ }
+ if(m_shouldDeleteAttr){
+ int error = pthread_mutexattr_destroy(m_attr);
+ ASSERT(error==0)
+ (void) error;
+ delete m_attr;
+ }
+}
+
+void Lock::obtainBlocking() {
+ int error = pthread_mutex_lock(m_mutex);
+ ASSERT_PERROR(error==0)
+ (void) error;
+}
+
+bool Lock::obtainDontBlock() {
+ int error = pthread_mutex_trylock(m_mutex);
+ return error==0;
+}
+
+void Lock::release() {
+ int error = pthread_mutex_unlock(m_mutex);
+ ASSERT_PERROR(error==0)
+ (void) error;
+}
+
+pthread_mutex_t* Lock::getMutex() {
+ return m_mutex;
+}
+
+void Lock::setShouldDeleteMutex(bool shouldDelete) {
+ m_shouldDeleteMutex = shouldDelete;
+}
+
+/////////////////////////////////////////
+//Condition class
+/////////////////////////////////////////
+Condition::Condition(pthread_condattr_t* attr) {
+ LOG("WARNING! Thread signaling is IFFY under LinuxThreads (Linux kernels pre 2.6)\n")
+ int error = pthread_cond_init(&m_cond, attr);
+ ASSERT(error==0)
+ (void) error;
+}
+
+Condition::~Condition() {
+ int error = pthread_cond_destroy(&m_cond);
+ ASSERT(error==0)
+ (void) error;
+}
+
+void Condition::wait(Lock* lock) {
+ pthread_cond_wait(&m_cond, lock->getMutex());
+}
+
+void Condition::wait(Lock* lock, U32 timeout_us) {
+ //{tv_sec,tv_nsec}, 1us = 1000ns
+ struct timespec timeToWait = {timeout_us / 1000000, (timeout_us * 1000) % 1000000000};
+ pthread_cond_timedwait(&m_cond, lock->getMutex(),&timeToWait);
+}
+
+void Condition::notify() {
+ pthread_cond_signal(&m_cond);
+}
+
+void Condition::notifyAll() {
+ pthread_cond_broadcast(&m_cond);
+}
+
+/////////////////////////////////////////
+//JavaLock class
+/////////////////////////////////////////
+JavaLock::JavaLock(Lock* lock, Condition* condition) {
+ m_lock = lock;
+ m_condition = condition;
+ IFDEBUG(m_isLocked = false;)
+}
+
+JavaLock::~JavaLock() {
+ delete m_lock;
+ delete m_condition;
+}
+
+void JavaLock::enterSynchronize() {
+ ASSERT(!m_isLocked)
+ m_lock->obtainBlocking();
+ IFDEBUG(m_isLocked = true;)
+}
+
+void JavaLock::exitSynchronize() {
+ ASSERT(m_isLocked)
+ m_lock->release();
+ IFDEBUG(m_isLocked = false;)
+}
+
+void JavaLock::wait() {
+ ASSERT(m_isLocked)
+ IFDEBUG(m_isLocked = false;)
+ m_condition->wait(m_lock);
+ IFDEBUG(m_isLocked = true;)
+}
+
+void JavaLock::wait(U32 timeout_us) {
+ ASSERT(m_isLocked)
+ IFDEBUG(m_isLocked = false;)
+ m_condition->wait(m_lock,timeout_us);
+ IFDEBUG(m_isLocked = true;)
+}
+
+void JavaLock::notify() {
+ ASSERT(m_isLocked)
+ m_condition->notify();
+}
+
+void JavaLock::notifyAll() {
+ ASSERT(m_isLocked)
+ m_condition->notifyAll();
+}
diff --git a/src/main/c++/java/threadsocket/ThreadPosix.hpp b/src/main/c++/java/threadsocket/ThreadPosix.hpp
new file mode 100644
index 0000000..05017f4
--- /dev/null
+++ b/src/main/c++/java/threadsocket/ThreadPosix.hpp
@@ -0,0 +1,124 @@
+#ifndef MULTITASKING_H_
+#define MULTITASKING_H_
+
+#include //threads
+#include //error numbers
+#include "Debug.h" //our debugging / logging capabilities
+
+/**
+ * Encapsulates a pthread_t. Basically just raw calls
+ * to the pthread API, but with easier syntax.
+ */
+class Thread {
+public:
+ /**
+ * You can set it's scheduling parameters by setting attr
+ * See http://www.unix.org/version2/whatsnew/threadsref.html
+ * for details.
+ */
+ Thread(void* (*start_routine)(void*), void *arg = NULL, pthread_attr_t *attr = NULL);
+ /** Blocks until this thread ends and returns a pointer to its return value. */
+ void* join();
+
+ /** STATIC! Ends the calling thread. Optional parameter allows it to return a value on its close. */
+ static void endThread(void *returnValue = NULL);
+
+private:
+ pthread_t m_thread;
+};
+
+/**
+ * Encapsulates a pthread_mutex_t. Basically just raw calls
+ * to the pthread API, but with easier syntax.
+ */
+class Lock {
+public:
+ /** A master lock to be shared by threads should they be so inclined. */
+ static Lock masterLock;
+
+ /** Default type is Recursive, which is probably the correct kind. */
+ Lock(int type = PTHREAD_MUTEX_RECURSIVE);
+ /** Creates a lock around a specified (and already initialized) mutex. */
+ Lock(pthread_mutex_t* mutex);
+ /** Locks need to be destroyed properly. */
+ ~Lock();
+ /** Blocks indefinitely for the lock. */
+ void obtainBlocking();
+ /** Returns true if the lock was obtained (if the lock was free), and false otherwise. */
+ bool obtainDontBlock();
+ /** Releases the lock. */
+ void release();
+ /** Makes the mutex_t available. */
+ pthread_mutex_t* getMutex();
+
+ /** Determines what happens in the destructor. */
+ void setShouldDeleteMutex(bool shouldDelete);
+
+private:
+ pthread_mutex_t* m_mutex;
+ pthread_mutexattr_t* m_attr;
+
+ bool m_shouldDeleteMutex;
+ bool m_shouldDeleteAttr;
+};
+
+/**
+ * Encapsulates a pthread_cond_t. Basically just raw calls
+ * to the pthread API, but with easier syntax.
+ */
+class Condition {
+public:
+ /** Condition attributes allow out-of-process notification, but that's all. */
+ Condition(pthread_condattr_t* attr = NULL);
+ /** Conditions need to be destroyed. */
+ ~Condition();
+ /**
+ * Unlocks the given lock, waits to be awoken, relocks the lock when it is awoken,
+ * and then returns. It can be awoken for any reason, so you should double check
+ * that the condition is still true.
+ */
+ void wait(Lock* lock);
+ /** Same as above, but with a timeout. */
+ void wait(Lock* lock, U32 timeout_us);
+ /** Wakes up one or more threads waiting for this condition variable. */
+ void notify();
+ /** Wakes up every thread waiting for this condition variable. */
+ void notifyAll();
+
+private:
+ pthread_cond_t m_cond;
+};
+
+/**
+ * Combines pthread mutexes and conditions to emulate the behavior
+ * of a Java synchronized block with wait() and signal() calls inside.
+ */
+class JavaLock {
+public:
+ /**
+ * You can specify a lock or condition variable in particular if you want,
+ * but it'll make a default one for you if you want.
+ */
+ JavaLock(Lock* lock = new Lock(), Condition* condition = new Condition());
+ /** Deletes the lock and condition. */
+ ~JavaLock();
+ /** Obtains the lock. Equivalent to synchronized(someObject){ in Java. */
+ void enterSynchronize();
+ /** Releases the lock. Equivalent to } at the end of a synchronized block in Java. */
+ void exitSynchronize();
+ /** See Condition::wait(). Must be called between enterSynchronize and exitSynchronize(). Same behavior as Java. */
+ void wait();
+ /** Same as wait(), but with a timeout */
+ void wait(U32 timeout_us);
+ /** See Condition::notify(). Must be called between enterSynchronize and exitSynchronize(). Same behavior as Java. */
+ void notify();
+ /** See Condition::notifyAll(). Must be called between enterSynchronize and exitSynchronize(). Same behavior as Java. */
+ void notifyAll();
+
+private:
+ Condition* m_condition;
+ Lock* m_lock;
+ IFDEBUG(bool m_isLocked);
+};
+
+#endif /*MULTITASKING_H_*/
diff --git a/src/main/c++/java/threadsocket/ThreadWin.cpp b/src/main/c++/java/threadsocket/ThreadWin.cpp
new file mode 100644
index 0000000..00668ea
--- /dev/null
+++ b/src/main/c++/java/threadsocket/ThreadWin.cpp
@@ -0,0 +1,246 @@
+#include "ThreadWin.hpp"
+
+/////////////////////////////////////////
+//Thread class
+/////////////////////////////////////////
+Thread::Thread(
+ LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function
+ LPVOID lpParameter, // argument for new thread
+ LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes
+ DWORD dwStackSize) { // initial thread stack size
+ m_hThread = CreateThread (
+ lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, 0, &m_dwThreadId
+ );
+ ASSERT(m_hThread != NULL);
+}
+
+DWORD Thread::join(DWORD dwMilliseconds) {
+ return WaitForSingleObject (
+ m_hThread,
+ dwMilliseconds
+ );
+}
+
+/////////////////////////////////////////
+//Lock class
+/////////////////////////////////////////
+Lock::Lock(LPSECURITY_ATTRIBUTES lpMutexAttributes) {
+ m_bShouldDeleteMutex = TRUE;
+ m_hMutex = CreateMutex (
+ lpMutexAttributes, // default security attributes
+ FALSE, // initially not owned
+ NULL // unnamed mutex
+ );
+ ASSERT(m_hMutex != NULL);
+}
+
+Lock::Lock(HANDLE mutex) {
+ m_bShouldDeleteMutex = FALSE;
+ m_hMutex = mutex;
+}
+
+Lock::~Lock() {
+ if (m_bShouldDeleteMutex) {
+ BOOL bResult = CloseHandle(m_hMutex);
+ ASSERT(bResult);
+ }
+}
+
+BOOL Lock::obtainBlocking() {
+ DWORD dwWaitResult = WaitForSingleObject (
+ m_hMutex, // handle to mutex
+ INFINITE // no time-out interval
+ );
+
+ // The thread got ownership of an abandoned mutex
+ // The database is in an indeterminate state.
+ BOOL bResult = (dwWaitResult != WAIT_ABANDONED);
+ ASSERT(bResult);
+
+ return bResult;
+}
+
+BOOL Lock::obtainDontBlock() {
+ // The pthread_mutex_trylock function is used to acquire
+ // a lock on the specified mutex variable. If the mutex has
+ // already been acquired by another thread, the function will
+ // return with an EBUSY indication rather than blocking.
+ //
+ // To achieve the same functionality in the Windows threading
+ // model set the Milliseconds parameter to zero for the
+ // WaitForSingleObject call. You will receive a WAIT_TIMEOUT
+ // indication if the mutex was not signaled when you invoked
+ // the function.
+
+ DWORD dwWaitResult = WaitForSingleObject (
+ m_hMutex, // handle to mutex
+ 0 // time-out immediately
+ );
+
+ BOOL bResult = (dwWaitResult != WAIT_TIMEOUT);
+ ASSERT(bResult);
+
+ return bResult;
+}
+
+BOOL Lock::release() {
+ BOOL bResult = ReleaseMutex (m_hMutex);
+ ASSERT(bResult);
+
+ return bResult;
+}
+
+HANDLE Lock::getMutex() {
+ return m_hMutex;
+}
+
+void Lock::setShouldDeleteMutex(BOOL bShouldDelete) {
+ m_bShouldDeleteMutex = bShouldDelete;
+}
+
+/////////////////////////////////////////
+//Condition class
+/////////////////////////////////////////
+Condition::Condition() {
+ m_cv.iWaitersCount = 0;
+ m_cv.bWasBroadcast = FALSE;
+ m_cv.hSema = CreateSemaphore (
+ NULL, // no security
+ 0, // initially 0
+ 0x7fffffff, // max count
+ NULL // unnamed
+ );
+
+ InitializeCriticalSection (&m_cv.csWaitersCountLock);
+
+ m_cv.hWaitersDone = CreateEvent (
+ NULL, // no security
+ FALSE, // auto-reset
+ FALSE, // non-signaled initially
+ NULL // unnamed
+ );
+}
+
+Condition::~Condition() {
+ DeleteCriticalSection (&m_cv.csWaitersCountLock);
+}
+
+void Condition::wait(Lock *lock) {
+ // Avoid race conditions.
+ EnterCriticalSection (&m_cv.csWaitersCountLock);
+ m_cv.iWaitersCount++;
+ LeaveCriticalSection (&m_cv.csWaitersCountLock);
+
+ // This call atomically releases the mutex and waits on the semaphore
+ // until or are called by another thread.
+ SignalObjectAndWait (lock->getMutex(), m_cv.hSema, INFINITE, FALSE);
+
+ // Reacquire lock to avoid race conditions.
+ EnterCriticalSection (&m_cv.csWaitersCountLock);
+
+ // We're no longer waiting...
+ m_cv.iWaitersCount--;
+
+ // Check to see if we're the last waiter after .
+ BOOL bLastWaiter = m_cv.bWasBroadcast && m_cv.iWaitersCount == 0;
+
+ LeaveCriticalSection (&m_cv.csWaitersCountLock);
+
+ // If we're the last waiter thread during this particular broadcast
+ // then let all the other threads proceed.
+ if (bLastWaiter) {
+ // This call atomically signals the event and waits until
+ // it can acquire the . This is required to ensure fairness.
+ SignalObjectAndWait (m_cv.hWaitersDone, lock->getMutex(), INFINITE, FALSE);
+ }
+ else {
+ // Always regain the external mutex since that's the guarantee we
+ // give to our callers.
+ WaitForSingleObject (lock->getMutex(), INFINITE);
+ }
+}
+
+void Condition::notify() {
+ EnterCriticalSection (&m_cv.csWaitersCountLock);
+ BOOL bHaveWaiters = m_cv.iWaitersCount > 0;
+ LeaveCriticalSection (&m_cv.csWaitersCountLock);
+
+ // If there aren't any waiters, then this is a no-op.
+ if (bHaveWaiters)
+ ReleaseSemaphore (m_cv.hSema, 1, 0);
+}
+
+void Condition::notifyAll() {
+ // This is needed to ensure that and are
+ // consistent relative to each other.
+ EnterCriticalSection (&m_cv.csWaitersCountLock);
+ BOOL bHaveWaiters = FALSE;
+
+ if (m_cv.iWaitersCount > 0) {
+ // We are broadcasting, even if there is just one waiter...
+ // Record that we are broadcasting, which helps optimize
+ // for the non-broadcast case.
+ m_cv.bWasBroadcast = TRUE;
+ bHaveWaiters = TRUE;
+ }
+
+ if (bHaveWaiters) {
+ // Wake up all the waiters atomically.
+ ReleaseSemaphore (m_cv.hSema, m_cv.iWaitersCount, 0);
+
+ LeaveCriticalSection (&m_cv.csWaitersCountLock);
+
+ // Wait for all the awakened threads to acquire the counting
+ // semaphore.
+ WaitForSingleObject (m_cv.hWaitersDone, INFINITE);
+ // This assignment is okay, even without the held
+ // because no other waiter threads can wake up to access it.
+ m_cv.bWasBroadcast = FALSE;
+ }
+ else {
+ LeaveCriticalSection (&m_cv.csWaitersCountLock);
+ }
+}
+
+/////////////////////////////////////////
+//JavaLock class
+/////////////////////////////////////////
+JavaLock::JavaLock(Lock* lock, Condition* condition) {
+ m_pLock = lock;
+ m_pCondition = condition;
+}
+
+JavaLock::~JavaLock() {
+ delete m_pLock;
+ delete m_pCondition;
+}
+
+void JavaLock::enterSynchronize() {
+ if (m_pLock != NULL) {
+ m_pLock->obtainBlocking();
+ }
+}
+
+void JavaLock::exitSynchronize() {
+ if (m_pLock != NULL) {
+ m_pLock->release();
+ }
+}
+
+void JavaLock::wait() {
+ if (m_pCondition != NULL) {
+ m_pCondition->wait(m_pLock);
+ }
+}
+
+void JavaLock::notify() {
+ if (m_pCondition != NULL) {
+ m_pCondition->notify();
+ }
+}
+
+void JavaLock::notifyAll() {
+ if (m_pCondition != NULL) {
+ m_pCondition->notifyAll();
+ }
+}
diff --git a/src/main/c++/java/threadsocket/ThreadWin.hpp b/src/main/c++/java/threadsocket/ThreadWin.hpp
new file mode 100644
index 0000000..db9d561
--- /dev/null
+++ b/src/main/c++/java/threadsocket/ThreadWin.hpp
@@ -0,0 +1,206 @@
+#ifndef _THREAD_H_
+#define _THREAD_H_
+
+#include //windows APIs
+#include //error numbers
+#include "Debug.h" //our debugging / logging capabilities
+
+#pragma once
+
+/**
+ * Encapsulates a win32 thread. Basically it's just raw calls
+ * to the windows APIs, but with easier syntax.
+ */
+class Thread {
+public:
+ /**
+ * See MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx
+ * for details.
+ * This webpage also tells the difference between 'CreateThread' and '_beginthreadex':
+ *
+ * A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex
+ * and _endthreadex functions for thread management rather than CreateThread and ExitThread; this
+ * requires the use of the multithreaded version of the CRT. If a thread created using CreateThread
+ * calls the CRT, the CRT may terminate the process in low-memory conditions.
+ *
+ * Because we are running the exectuable in the C++ run-time, so we should use CreateThread.
+ */
+ Thread(
+ LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function
+ LPVOID lpParameter, // argument for new thread
+ LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL, // pointer to security attributes
+ DWORD dwStackSize = 0 // initial thread stack size
+ );
+
+ /*
+ * In Windows system, we use 'WaitForSingleObject' as a replacement to 'pthread_join',
+ * See http://www.cs.rpi.edu/academics/courses/netprog/WindowsThreads.html for example.
+ *
+ * 'WaitForSingleObject' acts exactly same as 'pthread_join' while we set the parameter
+ * to 'INFINITE', i.e, if we'd like, we can control the period of thread blocking.
+ */
+ DWORD join(
+ DWORD dwMilliseconds = INFINITE
+ );
+
+ /*
+ * See MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659(v=vs.85).aspx
+ * for details.
+ * Per MSDN, this method should not be used anymore, and here is the reason for this:
+ *
+ * ExitThread is the preferred method of exiting a thread in C code. However, in C++ code,
+ * the thread is exited before any destructors can be called or any other automatic cleanup
+ * can be performed. Therefore, in C++ code, you should return from your thread function.
+ *
+ * Because we are using C++ here, we should exit a thread through the thread function.
+ */
+ //VOID exitThread(
+ // );
+
+private:
+ DWORD m_dwThreadId;
+ HANDLE m_hThread;
+};
+
+/**
+ * Encapsulates a mutex. Basically it's just raw calls to the windows APIs, but with
+ * easier syntax.
+ */
+class Lock {
+public:
+ /** Create a mutex with default security attributes. */
+ Lock(LPSECURITY_ATTRIBUTES lpMutexAttributes = NULL);
+
+ /** Constructing the 'Lock' object with an existed mutex. */
+ Lock(HANDLE mutex);
+
+ /** Default destructor. */
+ ~Lock();
+
+ /** Block INFINITE for the lock. */
+ BOOL obtainBlocking();
+
+ /** Try to obtain the lock, return TRUE if the lock was obtained. */
+ BOOL obtainDontBlock();
+
+ /** Release the lock. */
+ BOOL release();
+
+ /** Get the HANDLE of inner mutex. */
+ HANDLE getMutex();
+
+ /** Determines whether we will clean up the mutex in the destructor. */
+ void setShouldDeleteMutex(BOOL bShouldDelete);
+
+private:
+ HANDLE m_hMutex;
+ BOOL m_bShouldDeleteMutex;
+};
+
+
+/**
+ * Defines the data context of a condition variable, this is from SEC-3.4 of
+ * article http://www.cs.wustl.edu/~schmidt/win32-cv-1.html.
+ */
+typedef struct {
+
+ INT iWaitersCount; //number of waiting threads.
+
+
+ CRITICAL_SECTION csWaitersCountLock;//serialize access to .
+
+
+ HANDLE hSema; //semaphore used to queue up threads waiting for the condition to become signaled.
+
+
+ HANDLE hWaitersDone; //an auto-reset event used by the broadcast/signal thread to wait for all the waiting
+ //thread(s) to wake up and be released from the semaphore.
+
+ BOOL bWasBroadcast; //keeps track of whether we were broadcasting or signaling, this allows us to
+ //optimize the code if we're just signaling.
+
+} CONDITION_VARIABLE_CONTEXT;
+
+
+/**
+ * Encapsulates the condition variable, the inner implementation is from SEC-3.4 of
+ * article http://www.cs.wustl.edu/~schmidt/win32-cv-1.html.
+ *
+ * Since Windows's 'Condition Variable APIs' is introduced after Windows Vista, so it
+ * can't be applied to a XP system. We are creating our own 'ConditionVariable' with
+ * OS primitives of XP by following above article.
+ */
+class Condition {
+public:
+
+ /** Create a condition variable with OS primitives supported by XP. */
+ Condition();
+
+ /** Do clean up here. */
+ ~Condition();
+
+ /**
+ * Unlocks the given lock, waits to be awoken, relocks the lock when it is awoken,
+ * and then returns. It can be awoken for any reason, so you should double check
+ * that the condition is still true.
+ */
+ void wait(Lock *lock);
+
+ /** Wakes up one or more threads waiting for this condition variable. */
+ void notify();
+
+ /** Wakes up every thread waiting for this condition variable. */
+ void notifyAll();
+
+private:
+ CONDITION_VARIABLE_CONTEXT m_cv;
+};
+
+/**
+ * Combines mutexes and condition variables to emulate the behavior of a
+ * Java synchronized block with wait() and signal() calls inside.
+ */
+class JavaLock {
+public:
+ /**
+ * You can specify a lock or condition variable in particular if you want,
+ * but it'll make a default one for you if you want.
+ */
+ JavaLock(Lock* lock = new Lock(), Condition* condition = new Condition());
+
+ /** Deletes the lock and condition. */
+ ~JavaLock();
+
+ /** Obtains the lock. Equivalent to synchronized(someObject){ in Java. */
+ void enterSynchronize();
+
+ /**
+ * Releases the lock. Equivalent to } at the end of a
+ * synchronized block in Java.
+ */
+ void exitSynchronize();
+
+ /**
+ * See Condition::wait(). Must be called between enterSynchronize
+ * and exitSynchronize(). Same behavior as Java.
+ */
+ void wait();
+
+ /**
+ * See Condition::notify(). Must be called between enterSynchronize
+ * and exitSynchronize(). Same behavior as Java.
+ */
+ void notify();
+
+ /**
+ * See Condition::notifyAll(). Must be called between enterSynchronize
+ * and exitSynchronize(). Same behavior as Java.
+ */
+ void notifyAll();
+
+private:
+ Condition* m_pCondition;
+ Lock* m_pLock;
+};
+
+#endif /*_THREAD_H_*/
\ No newline at end of file