/* GIO - GLib Input, Output and Streaming Library
 *
 * Copyright © 2009 Codethink Limited
 * Copyright © 2009 Red Hat, Inc
 *
 * This program 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 of the licence 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., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Authors: Ryan Lortie <desrt@desrt.ca>
 *          Alexander Larsson <alexl@redhat.com>
 */

/**
 * SECTION: gthreadedsocketservice
 * @title: GThreadedSocketService
 * @short_description: A threaded GSocketService
 * @see_also: #GSocketService.
 *
 * A #GThreadedSocketService is a simple subclass of #GSocketService
 * that handles incoming connections by creating a worker thread and
 * dispatching the connection to it by emitting the ::run signal in
 * the new thread.
 *
 * The signal handler may perform blocking IO and need not return
 * until the connection is closed.
 *
 * The service is implemented using a thread pool, so there is a
 * limited amount of threads availible to serve incomming requests.
 * The service automatically stops the #GSocketService from accepting
 * new connections when all threads are busy.
 *
 * As with #GSocketService, you may connect to #GThreadedSocketService:run,
 * or subclass and override the default handler.
 */

#include "config.h"
#include "gsocketconnection.h"
#include "gthreadedsocketservice.h"
#include "glibintl.h"

#include "gio-marshal.h"


static guint g_threaded_socket_service_run_signal;

G_DEFINE_TYPE (GThreadedSocketService,
	       g_threaded_socket_service,
	       G_TYPE_SOCKET_SERVICE);

enum
{
  PROP_0,
  PROP_MAX_THREADS
};


G_LOCK_DEFINE_STATIC(job_count);

struct _GThreadedSocketServicePrivate
{
  GThreadPool *thread_pool;
  int max_threads;
  gint job_count;
};

typedef struct
{
  GThreadedSocketService *service;
  GSocketConnection *connection;
  GObject *source_object;
} GThreadedSocketServiceData;

static void
g_threaded_socket_service_func (gpointer _data,
				gpointer user_data)
{
  GThreadedSocketService *threaded = user_data;
  GThreadedSocketServiceData *data = _data;
  gboolean result;

  g_signal_emit (data->service, g_threaded_socket_service_run_signal,
                 0, data->connection, data->source_object, &result);

  g_object_unref (data->service);
  g_object_unref (data->connection);
  if (data->source_object)
    g_object_unref (data->source_object);
  g_slice_free (GThreadedSocketServiceData, data);

  G_LOCK (job_count);
  if (threaded->priv->job_count-- == threaded->priv->max_threads)
    g_socket_service_start (G_SOCKET_SERVICE (threaded));
  G_UNLOCK (job_count);
}

static gboolean
g_threaded_socket_service_incoming (GSocketService    *service,
                                    GSocketConnection *connection,
                                    GObject           *source_object)
{
  GThreadedSocketService *threaded;
  GThreadedSocketServiceData *data;

  threaded = G_THREADED_SOCKET_SERVICE (service);

  data = g_slice_new (GThreadedSocketServiceData);
  data->service = g_object_ref (service);
  data->connection = g_object_ref (connection);
  if (source_object)
    data->source_object = g_object_ref (source_object);
  else
    data->source_object = NULL;

  G_LOCK (job_count);
  if (++threaded->priv->job_count == threaded->priv->max_threads)
    g_socket_service_stop (service);
  G_UNLOCK (job_count);

  g_thread_pool_push (threaded->priv->thread_pool, data, NULL);



  return FALSE;
}

static void
g_threaded_socket_service_init (GThreadedSocketService *service)
{
  service->priv = G_TYPE_INSTANCE_GET_PRIVATE (service,
					       G_TYPE_THREADED_SOCKET_SERVICE,
					       GThreadedSocketServicePrivate);
  service->priv->max_threads = 10;
}

static void
g_threaded_socket_service_constructed (GObject *object)
{
  GThreadedSocketService *service = G_THREADED_SOCKET_SERVICE (object);

  service->priv->thread_pool =
    g_thread_pool_new  (g_threaded_socket_service_func,
			service,
			service->priv->max_threads,
			FALSE,
			NULL);
}


static void
g_threaded_socket_service_finalize (GObject *object)
{
  GThreadedSocketService *service = G_THREADED_SOCKET_SERVICE (object);

  g_thread_pool_free (service->priv->thread_pool, FALSE, TRUE);

  G_OBJECT_CLASS (g_threaded_socket_service_parent_class)
    ->finalize (object);
}

static void
g_threaded_socket_service_get_property (GObject    *object,
					guint       prop_id,
					GValue     *value,
					GParamSpec *pspec)
{
  GThreadedSocketService *service = G_THREADED_SOCKET_SERVICE (object);

  switch (prop_id)
    {
      case PROP_MAX_THREADS:
	g_value_set_int (value, service->priv->max_threads);
	break;

      default:
	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

static void
g_threaded_socket_service_set_property (GObject      *object,
					guint         prop_id,
					const GValue *value,
					GParamSpec   *pspec)
{
  GThreadedSocketService *service = G_THREADED_SOCKET_SERVICE (object);

  switch (prop_id)
    {
      case PROP_MAX_THREADS:
	service->priv->max_threads = g_value_get_int (value);
	break;

      default:
	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}


static void
g_threaded_socket_service_class_init (GThreadedSocketServiceClass *class)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
  GSocketServiceClass *ss_class = &class->parent_class;

  g_type_class_add_private (class, sizeof (GThreadedSocketServicePrivate));

  gobject_class->constructed = g_threaded_socket_service_constructed;
  gobject_class->finalize = g_threaded_socket_service_finalize;
  gobject_class->set_property = g_threaded_socket_service_set_property;
  gobject_class->get_property = g_threaded_socket_service_get_property;

  ss_class->incoming = g_threaded_socket_service_incoming;

  /**
   * GThreadedSocketService::run:
   * @service: the #GThreadedSocketService.
   * @connection: a new #GSocketConnection object.
   * @source_object: the source_object passed to g_socket_listener_add_address().
   *
   * The ::run signal is emitted in a worker thread in response to an
   * incoming connection. This thread is dedicated to handling
   * @connection and may perform blocking IO. The signal handler need
   * not return until the connection is closed.
   *
   * Returns: %TRUE to stope further signal handlers from being called
   */
  g_threaded_socket_service_run_signal =
    g_signal_new ("run", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GThreadedSocketServiceClass, run),
		  g_signal_accumulator_true_handled, NULL,
		  _gio_marshal_BOOLEAN__OBJECT_OBJECT, G_TYPE_BOOLEAN,
		  2, G_TYPE_SOCKET_CONNECTION, G_TYPE_OBJECT);

  g_object_class_install_property (gobject_class, PROP_MAX_THREADS,
				   g_param_spec_int ("max-threads",
						     P_("Max threads"),
						     P_("The max number of threads handling clients for this service"),
						     -1,
						     G_MAXINT,
						     10,
						     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}

/**
 * g_threaded_socket_service_new:
 * @max_threads: the maximal number of threads to execute concurrently
 *   handling incoming clients, -1 means no limit
 *
 * Creates a new #GThreadedSocketService with no listeners. Listeners
 * must be added with g_socket_service_add_listeners().
 *
 * Returns: a new #GSocketService.
 *
 * Since: 2.22
 */
GSocketService *
g_threaded_socket_service_new (int max_threads)
{
  return g_object_new (G_TYPE_THREADED_SOCKET_SERVICE,
		       "max-threads", max_threads,
		       NULL);
}
