[python, ruby] Add Director guard file with C++ 11 std::mutex (#2870)

* Improve mutex for director use:
- Use C++ 11 mutex and lock classes.
  Most compilers support C++ 11 by default.
  Leave Win32 and POSIX support for older compiler.
- Use a single file for Python and Ruby.
- Use macro also for guard definition instead of using '#ifdef'.
- Rename old '__THREAD__' to 'SWIG_THREADS' to
  avoid collide with other libraries.
- Remove the use of '__PTHREAD__' as it may collide with other libraries.
- Remove mutex from OCaml, as it is not used in Director class.

Signed-off-by: Erez Geva <ErezGeva2@gmail.com>

* Fixes follow @wsfulton.

Improve description of director_guard.swg.
Remove duplicate line.
Change to SWIG_GUARD_DEFINITION and SWIG_GUARD_DECLARATION
 as full English words are much more easily understood
 than abbreviations.

Signed-off-by: Erez Geva <ErezGeva2@gmail.com>

---------

Signed-off-by: Erez Geva <ErezGeva2@gmail.com>
This commit is contained in:
Erez Geva 2024-07-02 09:54:28 +02:00 committed by GitHub
parent a24461dbac
commit 2e9d570194
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 135 additions and 162 deletions

104
Lib/director_guard.swg Normal file
View File

@ -0,0 +1,104 @@
/* -----------------------------------------------------------------------------
* director_guard.swg
*
* Generic Mutex implementation
*
* Before calling the file, you may choose the following:
* - SWIG_THREADS:
* If set than we use mutexs.
* If not set we do not use mutexs.
* - SWIG_HAVE_MUTEX:
* If you have a language defined 'Mutex' class, set this flag.
* The language 'Mutex' class need to be a Basic Lockable.
* It must have public 'void lock()' and 'void unlock()' methods.
* See: https://en.cppreference.com/w/cpp/named_req/BasicLockable
* If the flag is unset, use one of the following in that order:
* - C++ 11 or above, use std::mutex.
* - Win32 use CRITICAL_SECTION.
* - Use POSIX Pthread mutex.
*
* ----------------------------------------------------------------------------- */
#ifdef SWIG_THREADS
#if __cplusplus >= 201103L
/*
* C++ 11 or above
* std::mutex https://en.cppreference.com/w/cpp/thread/mutex
* std::unique_lock https://en.cppreference.com/w/cpp/thread/unique_lock
*/
#include <mutex>
#ifdef SWIG_HAVE_MUTEX
/* Use Language defined Mutex class */
#define SWIG_GUARD(_mutex) std::unique_lock<Mutex> _guard(_mutex)
#define SWIG_GUARD_DEFINITION(_cls, _mutex) Mutex _cls::_mutex
#define SWIG_GUARD_DECLARATION(_mutex) static Mutex _mutex
#else
#define SWIG_GUARD(_mutex) std::unique_lock<std::mutex> _guard(_mutex)
#define SWIG_GUARD_DEFINITION(_cls, _mutex) std::mutex _cls::_mutex
#define SWIG_GUARD_DECLARATION(_mutex) static std::mutex _mutex
#endif
#else /* __cplusplus */
#ifdef SWIG_HAVE_MUTEX
/* Use Language defined Mutex class */
#elif defined(_WIN32)
/*
* Windows Critical Section Objects
* https://learn.microsoft.com/en-us/windows/win32/Sync/critical-section-objects
*/
#include <windows.h>
#include <synchapi.h>
namespace Swig {
class Mutex {
CRITICAL_SECTION mutex_;
public:
Mutex() { InitializeCriticalSection(&mutex_); }
~Mutex() { DeleteCriticalSection(&mutex_); }
void lock() { EnterCriticalSection(&mutex_); }
void unlock() { LeaveCriticalSection(&mutex_); }
};
}
#else /* _WIN32 */
/*
* POSIX Thread mutex
* https://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread.h.html
*/
#include <pthread.h>
namespace Swig {
class Mutex {
pthread_mutex_t mutex_;
public:
Mutex() { pthread_mutex_init(&mutex_, NULL); }
~Mutex() { pthread_mutex_destroy(&mutex_); }
void lock() { pthread_mutex_lock(&mutex_); }
void unlock() { pthread_mutex_unlock(&mutex_); }
};
}
#endif /* _WIN32 */
namespace Swig {
class Unique_lock {
Mutex &mutex_;
public:
Unique_lock(Mutex &_mutex) : mutex_(_mutex) { mutex_.lock(); }
~Unique_lock() { mutex_.unlock(); }
};
}
#define SWIG_GUARD(_mutex) Unique_lock _guard(_mutex)
#define SWIG_GUARD_DEFINITION(_cls, _mutex) Mutex _cls::_mutex
#define SWIG_GUARD_DECLARATION(_mutex) static Mutex _mutex
#endif /* __cplusplus */
#else /* SWIG_THREADS */
#define SWIG_GUARD(_mutex)
#define SWIG_GUARD_DEFINITION(_cls, _mutex)
#define SWIG_GUARD_DECLARATION(_mutex)
#endif /* SWIG_THREADS */

View File

@ -49,20 +49,6 @@ namespace Swig {
}
};
/* simple thread abstraction for pthreads on win32 */
#ifdef __THREAD__
#define __PTHREAD__
#if defined(_WIN32) || defined(__WIN32__)
#define pthread_mutex_lock EnterCriticalSection
#define pthread_mutex_unlock LeaveCriticalSection
#define pthread_mutex_t CRITICAL_SECTION
#define MUTEX_INIT(var) CRITICAL_SECTION var
#else
#include <pthread.h>
#define MUTEX_INIT(var) pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER
#endif
#endif
/* director base class */
class Director {
private:

View File

@ -14,25 +14,6 @@
#include <vector>
#include <map>
#if defined(SWIG_PYTHON_THREADS)
/* __THREAD__ is the old macro to activate some thread support */
# if !defined(__THREAD__)
# define __THREAD__ 1
# endif
#endif
#ifdef __THREAD__
#ifndef Py_LIMITED_API
# include "pythread.h"
#else
# if defined(_WIN32)
# include <windows.h>
# else
# include <pthread.h>
# endif
#endif
#endif
/*
Use -DSWIG_PYTHON_DIRECTOR_NO_VTABLE if you don't want to generate a 'virtual
table', and avoid multiple GetAttr calls to retrieve the python
@ -262,95 +243,6 @@ namespace Swig {
};
#ifdef __THREAD__
#ifndef Py_LIMITED_API
class Mutex
{
public:
Mutex() {
mutex_ = PyThread_allocate_lock();
}
~Mutex() {
PyThread_release_lock(mutex_);
}
private:
void Lock() {
PyThread_acquire_lock(mutex_, WAIT_LOCK);
}
void Unlock() {
PyThread_free_lock(mutex_);
}
PyThread_type_lock mutex_;
friend class Guard;
};
#elif defined(_WIN32)
class Mutex : private CRITICAL_SECTION {
public:
Mutex() {
InitializeCriticalSection(this);
}
~Mutex() {
DeleteCriticalSection(this);
}
private:
void Lock() {
EnterCriticalSection(this);
}
void Unlock() {
LeaveCriticalSection(this);
}
friend class Guard;
};
#else
class Mutex {
public:
Mutex() {
pthread_mutex_init(&mutex_, NULL);
}
~Mutex() {
pthread_mutex_destroy(&mutex_);
}
private:
void Lock() {
pthread_mutex_lock(&mutex_);
}
void Unlock() {
pthread_mutex_unlock(&mutex_);
}
friend class Guard;
pthread_mutex_t mutex_;
};
#endif
class Guard {
Mutex &mutex_;
public:
Guard(Mutex & mutex) : mutex_(mutex) {
mutex_.Lock();
}
~Guard() {
mutex_.Unlock();
}
};
# define SWIG_GUARD(mutex) Guard _guard(mutex)
#else
# define SWIG_GUARD(mutex)
#endif
/* director base class */
class Director {
@ -411,9 +303,7 @@ namespace Swig {
private:
typedef std::map<void *, GCItem_var> swig_ownership_map;
mutable swig_ownership_map swig_owner;
#ifdef __THREAD__
static Mutex swig_mutex_own;
#endif
SWIG_GUARD_DECLARATION(swig_mutex_own);
public:
template <typename Type>
@ -463,9 +353,7 @@ namespace Swig {
}
};
#ifdef __THREAD__
Mutex Director::swig_mutex_own;
#endif
SWIG_GUARD_DEFINITION(Director, swig_mutex_own);
}
#endif

View File

@ -0,0 +1,24 @@
/* -----------------------------------------------------------------------------
* director_py_mutex.swg
*
* contains python mutex for threads
* ----------------------------------------------------------------------------- */
#if defined(SWIG_PYTHON_THREADS) && !defined(SWIG_THREADS)
#define SWIG_THREADS 1
#endif
#if defined(SWIG_THREADS) && !defined(Py_LIMITED_API)
#include "pythread.h"
#define SWIG_HAVE_MUTEX
namespace Swig {
class Mutex
{
PyThread_type_lock mutex_;
public:
Mutex() : mutex_(PyThread_allocate_lock()) {}
~Mutex() { PyThread_release_lock(mutex_); }
void lock() { PyThread_acquire_lock(mutex_, WAIT_LOCK); }
void unlock() { PyThread_free_lock(mutex_); }
};
}
#endif

View File

@ -202,37 +202,6 @@ namespace Swig {
}
};
/* Simple thread abstraction for pthreads on win32 */
#ifdef __THREAD__
# define __PTHREAD__
# if defined(_WIN32) || defined(__WIN32__)
# define pthread_mutex_lock EnterCriticalSection
# define pthread_mutex_unlock LeaveCriticalSection
# define pthread_mutex_t CRITICAL_SECTION
# define SWIG_MUTEX_INIT(var) var
# else
# include <pthread.h>
# define SWIG_MUTEX_INIT(var) var = PTHREAD_MUTEX_INITIALIZER
# endif
#endif
#ifdef __PTHREAD__
struct Guard {
pthread_mutex_t *_mutex;
Guard(pthread_mutex_t &mutex) : _mutex(&mutex) {
pthread_mutex_lock(_mutex);
}
~Guard() {
pthread_mutex_unlock(_mutex);
}
};
# define SWIG_GUARD(mutex) Guard _guard(mutex)
#else
# define SWIG_GUARD(mutex)
#endif
/* director base class */
class Director {
private:
@ -266,9 +235,7 @@ namespace Swig {
private:
typedef std::map<void *, GCItem_var> swig_ownership_map;
mutable swig_ownership_map swig_owner;
#ifdef __PTHREAD__
static pthread_mutex_t swig_mutex_own;
#endif
SWIG_GUARD_DECLARATION(swig_mutex_own);
public:
template <typename Type>
@ -307,5 +274,6 @@ namespace Swig {
return own;
}
};
SWIG_GUARD_DEFINITION(Director, swig_mutex_own);
}

View File

@ -808,6 +808,8 @@ public:
if (Swig_directors_enabled()) {
// Insert director runtime into the f_runtime file (make it occur before %header section)
Swig_insert_file("director_common.swg", f_runtime);
Swig_insert_file("director_py_mutex.swg", f_runtime);
Swig_insert_file("director_guard.swg", f_runtime);
Swig_insert_file("director.swg", f_runtime);
}

View File

@ -1155,6 +1155,7 @@ public:
if (Swig_directors_enabled()) {
// Insert director runtime into the f_runtime file (make it occur before %header section)
Swig_insert_file("director_common.swg", f_runtime);
Swig_insert_file("director_guard.swg", f_runtime);
Swig_insert_file("director.swg", f_runtime);
}