diff options
Diffstat (limited to 'flow/gsl/gslartsthreads.cpp')
-rw-r--r-- | flow/gsl/gslartsthreads.cpp | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/flow/gsl/gslartsthreads.cpp b/flow/gsl/gslartsthreads.cpp new file mode 100644 index 0000000..9bd89e5 --- /dev/null +++ b/flow/gsl/gslartsthreads.cpp @@ -0,0 +1,203 @@ + /* + + Copyright (C) 2001-2002 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "thread.h" +#include "debug.h" +#include "gslglib.h" +#include <pthread.h> + +#if defined(__DECCXX) +#define EXTC extern "C" +#else +#define EXTC +#endif + +EXTC gpointer +gsl_arts_mutex_new () +{ + return new Arts::Mutex; +} + +EXTC void +gsl_arts_mutex_free (gpointer mutex) +{ + Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex); + delete m; +} + +EXTC void +gsl_arts_mutex_lock (gpointer mutex) +{ + Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex); + m->lock(); +} + +EXTC gboolean +gsl_arts_mutex_trylock (gpointer mutex) +{ + Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex); + return m->tryLock(); +} + +EXTC void +gsl_arts_mutex_unlock (gpointer mutex) +{ + Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex); + m->unlock(); +} + +EXTC gpointer +gsl_arts_cond_new () +{ + return new Arts::ThreadCondition; +} + +EXTC void +gsl_arts_cond_free (gpointer cond) +{ + Arts::ThreadCondition *c = static_cast<Arts::ThreadCondition *>(cond); + delete c; +} + +EXTC void +gsl_arts_cond_signal (gpointer cond) +{ + Arts::ThreadCondition *c = static_cast<Arts::ThreadCondition *>(cond); + c->wakeOne(); +} + +EXTC void +gsl_arts_cond_broadcast (gpointer cond) +{ + Arts::ThreadCondition *c = static_cast<Arts::ThreadCondition *>(cond); + c->wakeAll(); +} + +EXTC void +gsl_arts_cond_wait (gpointer cond, gpointer mutex) +{ + Arts::ThreadCondition *c = static_cast<Arts::ThreadCondition *>(cond); + Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex); + + c->wait(*m); +} + +EXTC void +gsl_arts_cond_timed_wait (gpointer /*cond*/, gpointer /*mutex*/, GTimeVal * /*time*/) +{ + arts_assert(false); +} + + +class GslArtsThread : public Arts::Thread { +protected: + gpointer (*func)(gpointer data); + gpointer data; + gpointer result; + +public: + GThread gthread; + + GslArtsThread(gpointer (*func)(gpointer data), gpointer data) + : func(func), data(data) + { + gthread.data = 0; + } + void run() + { + result = func(data); + } +}; + + +/* KCC (KAI C++) is buggy. If we write out the type of the first argument + to gsl_arts_thread_create(), ala + gsl_arts_thread_create (gpointer (*func) (gpointer data2), ...) + it becomes C++ linkage, i.e. it's name gets mangled, _despite_ declared + extern "C" in the header. Other sources only calling this function, + i.e. those only seeing the prototype correctly call the unmangled + extern "C" variant, but for the above reason it isn't defined anywhere. + The solution is to go through a typedef for that argument, _which must + also be declared extern "C"_. I'm not sure, but I think it's an error + of KCC, that it puts the invisible type of the first arg into C++ mode, + although the whole function should be C only. If one declares + two equal function types, one extern "C", one not, they are even assignment + compatible. But somehow KCC puts that type into C++ mode, which for + other strange reasons force the whole function to go into C++ linkage. + It's enough, when this typedef is local to this file. (matz) */ + +/* Due to gcc's unhappyness with 'extern "C" typedef ...' we enclose + it in a real extern "C" {} block. */ +extern "C" { +typedef gpointer (*t_func)(gpointer data2); +} + +// This is C++: +GThread* gsl_arts_thread_create_full_CPP(gpointer (*func)(gpointer data), + gpointer data, + gulong /*stack_size*/, + gboolean /*joinable*/, + gboolean /*bound*/, + GThreadPriority /*priority*/, + GError ** /*error*/) +{ + GslArtsThread *thread = new GslArtsThread(func, data); + return &thread->gthread; +} + +// This is C: +extern "C" GThread* +gsl_arts_thread_create_full(gpointer (*func)(gpointer data), + gpointer data, + gulong stack_size, + gboolean joinable, + gboolean bound, + GThreadPriority priority, + GError **error) +{ + return gsl_arts_thread_create_full_CPP(func, + data, + stack_size, + joinable, + bound, + priority, + error); +} + +EXTC gpointer +gsl_arts_thread_self () +{ + GslArtsThread *current = static_cast<GslArtsThread *>(Arts::SystemThreads::the()->getCurrentThread()); + + if(current) + return ¤t->gthread; + else + { + static GThread mainThread = { 0, }; + return &mainThread; + } +} + +EXTC void +gsl_arts_thread_init (gpointer /*arg*/) +{ +} |