// Generated by gmmproc 2.41.4 -- DO NOT MODIFY!

// Must be included in the .cc file before the generated #ifndef GLIBMM_DISABLE_DEPRECATED,
// or else "configure --disable-deprecated-api" + "make" will fail.
#include <glibmmconfig.h>
 
#ifndef GLIBMM_DISABLE_DEPRECATED


#include <glibmm.h>

#include <glibmm/thread.h>
#include <glibmm/private/thread_p.h>


/* 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 Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser 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);

  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
{

// This was always meant as an internal method. It is no longer called,
// and no longer needs to be called. We are keeping it just to avoid
// breaking ABI, though hopefully nobody is using it anyway.
// TODO: Remove this when we can break ABI.
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_try_new(NULL,
      &call_thread_entry_slot, slot_copy, &error);

  if(error)
  {
    delete slot_copy;
    // Glib::Error::throw_exception() will probably wrap G_THREAD_ERROR in a
    // Glib::Threads::ThreadError instance, but we want a Glib::ThreadError.
    if (error->domain == G_THREAD_ERROR)
      throw Glib::ThreadError(error);
    else
      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() will probably wrap G_THREAD_ERROR in a
    // Glib::Threads::ThreadError instance, but we want a Glib::ThreadError.
    if (error->domain == G_THREAD_ERROR)
      throw Glib::ThreadError(error);
    else
      Glib::Error::throw_exception(error);
  }

  return reinterpret_cast<Thread*>(thread);
}

// static
Thread* Thread::self()
{
  return reinterpret_cast<Thread*>(g_thread_self());
}

void Thread::join()
{
  g_thread_join(&gobject_);
}

bool Thread::joinable() const
{
  return true; //An appropriate result now that this is deprecated because all threads are now joinable.
}

void Thread::set_priority(ThreadPriority priority)
{
  g_thread_set_priority(&gobject_, (GThreadPriority) priority);
}

ThreadPriority Thread::get_priority() const
{
  return THREAD_PRIORITY_NORMAL; //An appropriate result now that this is deprecated because the priority concept has been removed.
}

void thread_init(GThreadFunctions* /* vtable */)
{
  //g_thread_init() is deprecated and now does nothing,
  //so we do not even call it. That avoids a need to link to gthread-2.0,
  //which contains the empty g_thread_init() implementation.
  //g_thread_init(vtable);

  Glib::thread_init_impl();
}

bool thread_supported()
{
  //MSVC++ needs the != 0 to avoid an int -> bool cast warning.
  return (g_thread_supported() != 0);
}


// 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()) //TODO: Use a statically-allocated GMutext instead, with g_mutex_init().
{}

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_);
}

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));
}

void* StaticPrivate_get_helper(GStaticPrivate *private_key) {
  return g_static_private_get(private_key);
}

void StaticPrivate_set_helper(GStaticPrivate *private_key, gpointer data, GDestroyNotify notify) {
  return g_static_private_set(private_key, data, notify);
}

GPrivate* GPrivate_new_helper(GDestroyNotify notify) {
  return g_private_new(notify);
}


} // 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);
}

#endif // GLIBMM_DISABLE_DEPRECATED


