413 lines
8.7 KiB
C++
413 lines
8.7 KiB
C++
|
// Generated by gtkmmproc -- DO NOT MODIFY!
|
||
|
|
||
|
|
||
|
#include <glibmm/thread.h>
|
||
|
#include <glibmm/private/thread_p.h>
|
||
|
|
||
|
// -*- c++ -*-
|
||
|
/* $Id: thread.ccg,v 1.9 2006/05/12 08:08:44 murrayc Exp $ */
|
||
|
|
||
|
/* 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.h>
|
||
|
|
||
|
|
||
|
namespace
|
||
|
{
|
||
|
|
||
|
extern "C"
|
||
|
{
|
||
|
|
||
|
static void* call_thread_entry_slot(void* data)
|
||
|
{
|
||
|
sigc::slot_base *const slot = reinterpret_cast<sigc::slot_base*>(data);
|
||
|
|
||
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
||
|
try
|
||
|
{
|
||
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
||
|
// Recreate the specific slot, and drop the reference obtained by create().
|
||
|
(*static_cast<sigc::slot<void>*>(slot))();
|
||
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
||
|
}
|
||
|
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();
|
||
|
}
|
||
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
||
|
|
||
|
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());
|
||
|
}
|
||
|
|
||
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
||
|
void Glib::ThreadError::throw_func(GError* gobject)
|
||
|
{
|
||
|
throw Glib::ThreadError(gobject);
|
||
|
}
|
||
|
#else
|
||
|
//When not using exceptions, we just pass the Exception object around without throwing it:
|
||
|
std::auto_ptr<Glib::Error> Glib::ThreadError::throw_func(GError* gobject)
|
||
|
{
|
||
|
return std::auto_ptr<Glib::Error>(new Glib::ThreadError(gobject));
|
||
|
}
|
||
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
||
|
|
||
|
|