diff options
Diffstat (limited to 'libs/glibmm2/glibmm/thread.cc')
-rw-r--r-- | libs/glibmm2/glibmm/thread.cc | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/libs/glibmm2/glibmm/thread.cc b/libs/glibmm2/glibmm/thread.cc new file mode 100644 index 0000000000..1910c6fa38 --- /dev/null +++ b/libs/glibmm2/glibmm/thread.cc @@ -0,0 +1,399 @@ +// Generated by gtkmmproc -- DO NOT MODIFY! + +#include <glibmm/thread.h> +#include <glibmm/private/thread_p.h> + +// -*- c++ -*- +/* $Id$ */ + +/* Copyright (C) 2002 The gtkmm Development Team + * + * 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; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <glibmm/exceptionhandler.h> +#include <glib/gmessages.h> + + +namespace +{ + +extern "C" +{ + +static void* call_thread_entry_slot(void* data) +{ + sigc::slot_base *const slot = reinterpret_cast<sigc::slot_base*>(data); + + try + { + // Recreate the specific slot, and drop the reference obtained by create(). + (*static_cast<sigc::slot<void>*>(slot))(); + } + catch(Glib::Thread::Exit&) + { + // Just exit from the thread. The Thread::Exit exception + // is our sane C++ replacement of g_thread_exit(). + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + + delete slot; + return 0; +} + +} //extern "C" + +} // anonymous namespace + + +namespace Glib +{ + +// internal +void thread_init_impl() +{ + // Make sure the exception map is initialized before creating any thread. + Glib::Error::register_init(); +} + + +/**** Glib::Thread *********************************************************/ + +// static +Thread* Thread::create(const sigc::slot<void>& slot, bool joinable) +{ + // Make a copy of slot on the heap + sigc::slot_base *const slot_copy = new sigc::slot<void>(slot); + + GError* error = 0; + + GThread *const thread = g_thread_create( + &call_thread_entry_slot, slot_copy, joinable, &error); + + if(error) + { + delete slot_copy; + Glib::Error::throw_exception(error); + } + + return reinterpret_cast<Thread*>(thread); +} + +// static +Thread* Thread::create(const sigc::slot<void>& slot, unsigned long stack_size, + bool joinable, bool bound, ThreadPriority priority) +{ + // Make a copy of slot on the heap + sigc::slot_base *const slot_copy = new sigc::slot<void>(slot); + + GError* error = 0; + + GThread *const thread = g_thread_create_full( + &call_thread_entry_slot, slot_copy, stack_size, joinable, + bound, (GThreadPriority) priority, &error); + + if(error) + { + delete slot_copy; + Glib::Error::throw_exception(error); + } + + return reinterpret_cast<Thread*>(thread); +} + +// static +Thread* Thread::self() +{ + return reinterpret_cast<Thread*>(g_thread_self()); +} + +bool Thread::joinable() const +{ + return gobject_.joinable; +} + +void Thread::join() +{ + g_thread_join(&gobject_); +} + +void Thread::set_priority(ThreadPriority priority) +{ + g_thread_set_priority(&gobject_, (GThreadPriority) priority); +} + +ThreadPriority Thread::get_priority() const +{ + return (ThreadPriority) gobject_.priority; +} + +// static +void Thread::yield() +{ + g_thread_yield(); +} + +Thread* wrap(GThread* gobject) +{ + return reinterpret_cast<Thread*>(gobject); +} + + +/**** Glib::StaticMutex ****************************************************/ + +void StaticMutex::lock() +{ + g_static_mutex_lock(&gobject_); +} + +bool StaticMutex::trylock() +{ + return g_static_mutex_trylock(&gobject_); +} + +void StaticMutex::unlock() +{ + g_static_mutex_unlock(&gobject_); +} + +StaticMutex::operator Mutex&() +{ + // If GStaticMutex is implemented as struct (e.g. on Linux), its first struct + // member (runtime_mutex) is a GMutex pointer. If the gthread implementation + // is native (i.e. the vtable pointer passed to g_thread_init() was 0), then + // the runtime_mutex pointer is unused, and the rest of the GStaticMutex + // struct resembles the mutex data. + // + // On Win32, GStaticMutex is just a typedef to struct _GMutex*. Either way, + // the first sizeof(GMutex*) bytes of GStaticMutex always resemble a GMutex + // pointer. The gthread implementation relies on that, and we'll also do so. + + GMutex*& runtime_mutex = reinterpret_cast<GMutex*&>(gobject_); + + // Fortunately, it cannot hurt if we set this to the GMutex pointer returned + // by g_static_mutex_get_mutex(). Either we just overwrite it with the same + // value, or it was unused anyway. Doing that allows casting the pointer + // location to a Glib::Mutex reference (its only data member is a GMutex*). + + runtime_mutex = g_static_mutex_get_mutex(&gobject_); + + return reinterpret_cast<Mutex&>(runtime_mutex); +} + + +/**** Glib::Mutex **********************************************************/ + +Mutex::Mutex() +: + gobject_ (g_mutex_new()) +{} + +Mutex::~Mutex() +{ + g_mutex_free(gobject_); +} + +void Mutex::lock() +{ + g_mutex_lock(gobject_); +} + +bool Mutex::trylock() +{ + return g_mutex_trylock(gobject_); +} + +void Mutex::unlock() +{ + g_mutex_unlock(gobject_); +} + + +/**** Glib::StaticRecMutex *************************************************/ + +void StaticRecMutex::lock() +{ + g_static_rec_mutex_lock(&gobject_); +} + +bool StaticRecMutex::trylock() +{ + return g_static_rec_mutex_trylock(&gobject_); +} + +void StaticRecMutex::unlock() +{ + g_static_rec_mutex_unlock(&gobject_); +} + +void StaticRecMutex::lock_full(unsigned int depth) +{ + g_static_rec_mutex_lock_full(&gobject_, depth); +} + +unsigned int StaticRecMutex::unlock_full() +{ + return g_static_rec_mutex_unlock_full(&gobject_); +} + +StaticRecMutex::operator RecMutex&() +{ + return static_cast<RecMutex&>(*this); +} + + +/**** Glib::RecMutex *******************************************************/ + +RecMutex::RecMutex() +{ + g_static_rec_mutex_init(&gobject_); + + // GLib doesn't have GRecMutex, only GStaticRecMutex. Force initialization + // of the mutex now, to mimic the behaviour of a (hypothetical) GRecMutex. + g_static_mutex_get_mutex(&gobject_.mutex); +} + +RecMutex::~RecMutex() +{ + g_static_rec_mutex_free(&gobject_); +} + + +/**** Glib::StaticRWLock ***************************************************/ + +void StaticRWLock::reader_lock() +{ + g_static_rw_lock_reader_lock(&gobject_); +} + +bool StaticRWLock::reader_trylock() +{ + return g_static_rw_lock_reader_trylock(&gobject_); +} + +void StaticRWLock::reader_unlock() +{ + g_static_rw_lock_reader_unlock(&gobject_); +} + +void StaticRWLock::writer_lock() +{ + g_static_rw_lock_writer_lock(&gobject_); +} + +bool StaticRWLock::writer_trylock() +{ + return g_static_rw_lock_writer_trylock(&gobject_); +} + +void StaticRWLock::writer_unlock() +{ + g_static_rw_lock_writer_unlock(&gobject_); +} + +StaticRWLock::operator RWLock&() +{ + return static_cast<RWLock&>(*this); +} + + +/**** Glib::RWLock *********************************************************/ + +RWLock::RWLock() +{ + g_static_rw_lock_init(&gobject_); + + // GLib doesn't have GRWLock, only GStaticRWLock. Force initialization + // of the mutex and the condition variables now, to mimic the behaviour + // of a (hypothetical) GRWLock. + + if(g_static_mutex_get_mutex(&gobject_.mutex)) + { + gobject_.read_cond = g_cond_new(); + gobject_.write_cond = g_cond_new(); + } +} + +RWLock::~RWLock() +{ + g_static_rw_lock_free(&gobject_); +} + + +/**** Glib::Cond ***********************************************************/ + +Cond::Cond() +: + gobject_ (g_cond_new()) +{} + +Cond::~Cond() +{ + g_cond_free(gobject_); +} + +void Cond::signal() +{ + g_cond_signal(gobject_); +} + +void Cond::broadcast() +{ + g_cond_broadcast(gobject_); +} + +void Cond::wait(Mutex& mutex) +{ + g_cond_wait(gobject_, mutex.gobj()); +} + +bool Cond::timed_wait(Mutex& mutex, const Glib::TimeVal& abs_time) +{ + return g_cond_timed_wait(gobject_, mutex.gobj(), const_cast<Glib::TimeVal*>(&abs_time)); +} + + +} // namespace Glib + + +namespace +{ +} // anonymous namespace + + +Glib::ThreadError::ThreadError(Glib::ThreadError::Code error_code, const Glib::ustring& error_message) +: + Glib::Error (G_THREAD_ERROR, error_code, error_message) +{} + +Glib::ThreadError::ThreadError(GError* gobject) +: + Glib::Error (gobject) +{} + +Glib::ThreadError::Code Glib::ThreadError::code() const +{ + return static_cast<Code>(Glib::Error::code()); +} + +void Glib::ThreadError::throw_func(GError* gobject) +{ + throw Glib::ThreadError(gobject); +} + + |