gstreamer_core/gst/gsttaskpool.c
author hgs
Fri, 30 Apr 2010 19:11:56 -0500
changeset 19 24ed0baaf8e5
parent 16 8e837d1bf446
permissions -rw-r--r--
201017
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16
hgs
parents:
diff changeset
     1
/* GStreamer
hgs
parents:
diff changeset
     2
 * Copyright (C) 2009 Wim Taymans <wim.taymans@gmail.com>
hgs
parents:
diff changeset
     3
 *
hgs
parents:
diff changeset
     4
 * gsttaskpool.c: Pool for streaming threads
hgs
parents:
diff changeset
     5
 *
hgs
parents:
diff changeset
     6
 * This library is free software; you can redistribute it and/or
hgs
parents:
diff changeset
     7
 * modify it under the terms of the GNU Library General Public
hgs
parents:
diff changeset
     8
 * License as published by the Free Software Foundation; either
hgs
parents:
diff changeset
     9
 * version 2 of the License, or (at your option) any later version.
hgs
parents:
diff changeset
    10
 *
hgs
parents:
diff changeset
    11
 * This library is distributed in the hope that it will be useful,
hgs
parents:
diff changeset
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
hgs
parents:
diff changeset
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
hgs
parents:
diff changeset
    14
 * Library General Public License for more details.
hgs
parents:
diff changeset
    15
 *
hgs
parents:
diff changeset
    16
 * You should have received a copy of the GNU Library General Public
hgs
parents:
diff changeset
    17
 * License along with this library; if not, write to the
hgs
parents:
diff changeset
    18
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
hgs
parents:
diff changeset
    19
 * Boston, MA 02111-1307, USA.
hgs
parents:
diff changeset
    20
 */
hgs
parents:
diff changeset
    21
hgs
parents:
diff changeset
    22
/**
hgs
parents:
diff changeset
    23
 * SECTION:gsttaskpool
hgs
parents:
diff changeset
    24
 * @short_description: Pool of GStreamer streaming threads
hgs
parents:
diff changeset
    25
 * @see_also: #GstTask, #GstPad
hgs
parents:
diff changeset
    26
 *
hgs
parents:
diff changeset
    27
 * This object provides an abstraction for creating threads. The default
hgs
parents:
diff changeset
    28
 * implementation uses a regular GThreadPool to start tasks.
hgs
parents:
diff changeset
    29
 *
hgs
parents:
diff changeset
    30
 * Subclasses can be made to create custom threads.
hgs
parents:
diff changeset
    31
 *
hgs
parents:
diff changeset
    32
 * Last reviewed on 2009-04-23 (0.10.24)
hgs
parents:
diff changeset
    33
 */
hgs
parents:
diff changeset
    34
hgs
parents:
diff changeset
    35
#include "gst_private.h"
hgs
parents:
diff changeset
    36
hgs
parents:
diff changeset
    37
#include "gstinfo.h"
hgs
parents:
diff changeset
    38
#include "gsttaskpool.h"
hgs
parents:
diff changeset
    39
#ifdef __SYMBIAN32__
hgs
parents:
diff changeset
    40
#include <glib_global.h>
hgs
parents:
diff changeset
    41
#endif
hgs
parents:
diff changeset
    42
hgs
parents:
diff changeset
    43
GST_DEBUG_CATEGORY_STATIC (taskpool_debug);
hgs
parents:
diff changeset
    44
#define GST_CAT_DEFAULT (taskpool_debug)
hgs
parents:
diff changeset
    45
hgs
parents:
diff changeset
    46
static void gst_task_pool_class_init (GstTaskPoolClass * klass);
hgs
parents:
diff changeset
    47
static void gst_task_pool_init (GstTaskPool * pool);
hgs
parents:
diff changeset
    48
static void gst_task_pool_finalize (GObject * object);
hgs
parents:
diff changeset
    49
hgs
parents:
diff changeset
    50
#define _do_init \
hgs
parents:
diff changeset
    51
{ \
hgs
parents:
diff changeset
    52
  GST_DEBUG_CATEGORY_INIT (taskpool_debug, "taskpool", 0, "Thread pool"); \
hgs
parents:
diff changeset
    53
}
hgs
parents:
diff changeset
    54
hgs
parents:
diff changeset
    55
G_DEFINE_TYPE_WITH_CODE (GstTaskPool, gst_task_pool, GST_TYPE_OBJECT, _do_init);
hgs
parents:
diff changeset
    56
hgs
parents:
diff changeset
    57
typedef struct
hgs
parents:
diff changeset
    58
{
hgs
parents:
diff changeset
    59
  GstTaskPoolFunction func;
hgs
parents:
diff changeset
    60
  gpointer user_data;
hgs
parents:
diff changeset
    61
} TaskData;
hgs
parents:
diff changeset
    62
hgs
parents:
diff changeset
    63
static void
hgs
parents:
diff changeset
    64
default_func (TaskData * tdata, GstTaskPool * pool)
hgs
parents:
diff changeset
    65
{
hgs
parents:
diff changeset
    66
  GstTaskPoolFunction func;
hgs
parents:
diff changeset
    67
  gpointer user_data;
hgs
parents:
diff changeset
    68
hgs
parents:
diff changeset
    69
  func = tdata->func;
hgs
parents:
diff changeset
    70
  user_data = tdata->user_data;
hgs
parents:
diff changeset
    71
  g_slice_free (TaskData, tdata);
hgs
parents:
diff changeset
    72
hgs
parents:
diff changeset
    73
  func (user_data);
hgs
parents:
diff changeset
    74
}
hgs
parents:
diff changeset
    75
hgs
parents:
diff changeset
    76
static void
hgs
parents:
diff changeset
    77
default_prepare (GstTaskPool * pool, GError ** error)
hgs
parents:
diff changeset
    78
{
hgs
parents:
diff changeset
    79
  GST_OBJECT_LOCK (pool);
hgs
parents:
diff changeset
    80
  pool->pool = g_thread_pool_new ((GFunc) default_func, pool, -1, FALSE, NULL);
hgs
parents:
diff changeset
    81
  GST_OBJECT_UNLOCK (pool);
hgs
parents:
diff changeset
    82
}
hgs
parents:
diff changeset
    83
hgs
parents:
diff changeset
    84
static void
hgs
parents:
diff changeset
    85
default_cleanup (GstTaskPool * pool)
hgs
parents:
diff changeset
    86
{
hgs
parents:
diff changeset
    87
  GST_OBJECT_LOCK (pool);
hgs
parents:
diff changeset
    88
  if (pool->pool) {
hgs
parents:
diff changeset
    89
    /* Shut down all the threads, we still process the ones scheduled
hgs
parents:
diff changeset
    90
     * because the unref happens in the thread function.
hgs
parents:
diff changeset
    91
     * Also wait for currently running ones to finish. */
hgs
parents:
diff changeset
    92
    g_thread_pool_free (pool->pool, FALSE, TRUE);
hgs
parents:
diff changeset
    93
    pool->pool = NULL;
hgs
parents:
diff changeset
    94
  }
hgs
parents:
diff changeset
    95
  GST_OBJECT_UNLOCK (pool);
hgs
parents:
diff changeset
    96
}
hgs
parents:
diff changeset
    97
hgs
parents:
diff changeset
    98
static gpointer
hgs
parents:
diff changeset
    99
default_push (GstTaskPool * pool, GstTaskPoolFunction func,
hgs
parents:
diff changeset
   100
    gpointer user_data, GError ** error)
hgs
parents:
diff changeset
   101
{
hgs
parents:
diff changeset
   102
  TaskData *tdata;
hgs
parents:
diff changeset
   103
hgs
parents:
diff changeset
   104
  tdata = g_slice_new (TaskData);
hgs
parents:
diff changeset
   105
  tdata->func = func;
hgs
parents:
diff changeset
   106
  tdata->user_data = user_data;
hgs
parents:
diff changeset
   107
hgs
parents:
diff changeset
   108
  GST_OBJECT_LOCK (pool);
hgs
parents:
diff changeset
   109
  if (pool->pool)
hgs
parents:
diff changeset
   110
    g_thread_pool_push (pool->pool, tdata, error);
hgs
parents:
diff changeset
   111
  else {
hgs
parents:
diff changeset
   112
    g_slice_free (TaskData, tdata);
hgs
parents:
diff changeset
   113
  }
hgs
parents:
diff changeset
   114
  GST_OBJECT_UNLOCK (pool);
hgs
parents:
diff changeset
   115
hgs
parents:
diff changeset
   116
  return NULL;
hgs
parents:
diff changeset
   117
}
hgs
parents:
diff changeset
   118
hgs
parents:
diff changeset
   119
static void
hgs
parents:
diff changeset
   120
default_join (GstTaskPool * pool, gpointer id)
hgs
parents:
diff changeset
   121
{
hgs
parents:
diff changeset
   122
  /* we do nothing here, we can't join from the pools */
hgs
parents:
diff changeset
   123
}
hgs
parents:
diff changeset
   124
hgs
parents:
diff changeset
   125
static void
hgs
parents:
diff changeset
   126
gst_task_pool_class_init (GstTaskPoolClass * klass)
hgs
parents:
diff changeset
   127
{
hgs
parents:
diff changeset
   128
  GObjectClass *gobject_class;
hgs
parents:
diff changeset
   129
  GstTaskPoolClass *gsttaskpool_class;
hgs
parents:
diff changeset
   130
hgs
parents:
diff changeset
   131
  gobject_class = (GObjectClass *) klass;
hgs
parents:
diff changeset
   132
  gsttaskpool_class = (GstTaskPoolClass *) klass;
hgs
parents:
diff changeset
   133
hgs
parents:
diff changeset
   134
  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_task_pool_finalize);
hgs
parents:
diff changeset
   135
hgs
parents:
diff changeset
   136
  gsttaskpool_class->prepare = default_prepare;
hgs
parents:
diff changeset
   137
  gsttaskpool_class->cleanup = default_cleanup;
hgs
parents:
diff changeset
   138
  gsttaskpool_class->push = default_push;
hgs
parents:
diff changeset
   139
  gsttaskpool_class->join = default_join;
hgs
parents:
diff changeset
   140
}
hgs
parents:
diff changeset
   141
hgs
parents:
diff changeset
   142
static void
hgs
parents:
diff changeset
   143
gst_task_pool_init (GstTaskPool * pool)
hgs
parents:
diff changeset
   144
{
hgs
parents:
diff changeset
   145
}
hgs
parents:
diff changeset
   146
hgs
parents:
diff changeset
   147
static void
hgs
parents:
diff changeset
   148
gst_task_pool_finalize (GObject * object)
hgs
parents:
diff changeset
   149
{
hgs
parents:
diff changeset
   150
  GST_DEBUG ("taskpool %p finalize", object);
hgs
parents:
diff changeset
   151
hgs
parents:
diff changeset
   152
  G_OBJECT_CLASS (gst_task_pool_parent_class)->finalize (object);
hgs
parents:
diff changeset
   153
}
hgs
parents:
diff changeset
   154
hgs
parents:
diff changeset
   155
/**
hgs
parents:
diff changeset
   156
 * gst_task_pool_new:
hgs
parents:
diff changeset
   157
 *
hgs
parents:
diff changeset
   158
 * Create a new default task pool. The default task pool will use a regular
hgs
parents:
diff changeset
   159
 * GThreadPool for threads.
hgs
parents:
diff changeset
   160
 *
hgs
parents:
diff changeset
   161
 * Returns: a new #GstTaskPool. gst_object_unref() after usage.
hgs
parents:
diff changeset
   162
 */
hgs
parents:
diff changeset
   163
#ifdef __SYMBIAN32__
hgs
parents:
diff changeset
   164
EXPORT_C
hgs
parents:
diff changeset
   165
#endif
hgs
parents:
diff changeset
   166
hgs
parents:
diff changeset
   167
GstTaskPool *
hgs
parents:
diff changeset
   168
gst_task_pool_new (void)
hgs
parents:
diff changeset
   169
{
hgs
parents:
diff changeset
   170
  GstTaskPool *pool;
hgs
parents:
diff changeset
   171
hgs
parents:
diff changeset
   172
  pool = g_object_new (GST_TYPE_TASK_POOL, NULL);
hgs
parents:
diff changeset
   173
hgs
parents:
diff changeset
   174
  return pool;
hgs
parents:
diff changeset
   175
}
hgs
parents:
diff changeset
   176
hgs
parents:
diff changeset
   177
/**
hgs
parents:
diff changeset
   178
 * gst_task_pool_prepare:
hgs
parents:
diff changeset
   179
 * @pool: a #GstTaskPool
hgs
parents:
diff changeset
   180
 * @error: an error return location
hgs
parents:
diff changeset
   181
 *
hgs
parents:
diff changeset
   182
 * Prepare the taskpool for accepting gst_task_pool_push() operations.
hgs
parents:
diff changeset
   183
 *
hgs
parents:
diff changeset
   184
 * MT safe.
hgs
parents:
diff changeset
   185
 */
hgs
parents:
diff changeset
   186
#ifdef __SYMBIAN32__
hgs
parents:
diff changeset
   187
EXPORT_C
hgs
parents:
diff changeset
   188
#endif
hgs
parents:
diff changeset
   189
hgs
parents:
diff changeset
   190
void
hgs
parents:
diff changeset
   191
gst_task_pool_prepare (GstTaskPool * pool, GError ** error)
hgs
parents:
diff changeset
   192
{
hgs
parents:
diff changeset
   193
  GstTaskPoolClass *klass;
hgs
parents:
diff changeset
   194
hgs
parents:
diff changeset
   195
  g_return_if_fail (GST_IS_TASK_POOL (pool));
hgs
parents:
diff changeset
   196
hgs
parents:
diff changeset
   197
  klass = GST_TASK_POOL_GET_CLASS (pool);
hgs
parents:
diff changeset
   198
hgs
parents:
diff changeset
   199
  if (klass->prepare)
hgs
parents:
diff changeset
   200
    klass->prepare (pool, error);
hgs
parents:
diff changeset
   201
}
hgs
parents:
diff changeset
   202
hgs
parents:
diff changeset
   203
/**
hgs
parents:
diff changeset
   204
 * gst_task_pool_cleanup:
hgs
parents:
diff changeset
   205
 * @pool: a #GstTaskPool
hgs
parents:
diff changeset
   206
 *
hgs
parents:
diff changeset
   207
 * Wait for all tasks to be stopped. This is mainly used internally
hgs
parents:
diff changeset
   208
 * to ensure proper cleanup of internal data structures in test suites.
hgs
parents:
diff changeset
   209
 *
hgs
parents:
diff changeset
   210
 * MT safe.
hgs
parents:
diff changeset
   211
 */
hgs
parents:
diff changeset
   212
#ifdef __SYMBIAN32__
hgs
parents:
diff changeset
   213
EXPORT_C
hgs
parents:
diff changeset
   214
#endif
hgs
parents:
diff changeset
   215
hgs
parents:
diff changeset
   216
void
hgs
parents:
diff changeset
   217
gst_task_pool_cleanup (GstTaskPool * pool)
hgs
parents:
diff changeset
   218
{
hgs
parents:
diff changeset
   219
  GstTaskPoolClass *klass;
hgs
parents:
diff changeset
   220
hgs
parents:
diff changeset
   221
  g_return_if_fail (GST_IS_TASK_POOL (pool));
hgs
parents:
diff changeset
   222
hgs
parents:
diff changeset
   223
  klass = GST_TASK_POOL_GET_CLASS (pool);
hgs
parents:
diff changeset
   224
hgs
parents:
diff changeset
   225
  if (klass->cleanup)
hgs
parents:
diff changeset
   226
    klass->cleanup (pool);
hgs
parents:
diff changeset
   227
}
hgs
parents:
diff changeset
   228
hgs
parents:
diff changeset
   229
/**
hgs
parents:
diff changeset
   230
 * gst_task_pool_push:
hgs
parents:
diff changeset
   231
 * @pool: a #GstTaskPool
hgs
parents:
diff changeset
   232
 * @func: the function to call
hgs
parents:
diff changeset
   233
 * @user_data: data to pass to @func
hgs
parents:
diff changeset
   234
 * @error: return location for an error
hgs
parents:
diff changeset
   235
 *
hgs
parents:
diff changeset
   236
 * Start the execution of a new thread from @pool.
hgs
parents:
diff changeset
   237
 *
hgs
parents:
diff changeset
   238
 * Returns: a pointer that should be used for the gst_task_pool_join
hgs
parents:
diff changeset
   239
 * function. This pointer can be NULL, you must check @error to detect
hgs
parents:
diff changeset
   240
 * errors.
hgs
parents:
diff changeset
   241
 */
hgs
parents:
diff changeset
   242
#ifdef __SYMBIAN32__
hgs
parents:
diff changeset
   243
EXPORT_C
hgs
parents:
diff changeset
   244
#endif
hgs
parents:
diff changeset
   245
hgs
parents:
diff changeset
   246
gpointer
hgs
parents:
diff changeset
   247
gst_task_pool_push (GstTaskPool * pool, GstTaskPoolFunction func,
hgs
parents:
diff changeset
   248
    gpointer user_data, GError ** error)
hgs
parents:
diff changeset
   249
{
hgs
parents:
diff changeset
   250
  GstTaskPoolClass *klass;
hgs
parents:
diff changeset
   251
hgs
parents:
diff changeset
   252
  g_return_val_if_fail (GST_IS_TASK_POOL (pool), NULL);
hgs
parents:
diff changeset
   253
hgs
parents:
diff changeset
   254
  klass = GST_TASK_POOL_GET_CLASS (pool);
hgs
parents:
diff changeset
   255
hgs
parents:
diff changeset
   256
  if (klass->push == NULL)
hgs
parents:
diff changeset
   257
    goto not_supported;
hgs
parents:
diff changeset
   258
hgs
parents:
diff changeset
   259
  return klass->push (pool, func, user_data, error);
hgs
parents:
diff changeset
   260
hgs
parents:
diff changeset
   261
  /* ERRORS */
hgs
parents:
diff changeset
   262
not_supported:
hgs
parents:
diff changeset
   263
  {
hgs
parents:
diff changeset
   264
    g_warning ("pushing tasks on pool %p is not supported", pool);
hgs
parents:
diff changeset
   265
    return NULL;
hgs
parents:
diff changeset
   266
  }
hgs
parents:
diff changeset
   267
}
hgs
parents:
diff changeset
   268
hgs
parents:
diff changeset
   269
/**
hgs
parents:
diff changeset
   270
 * gst_task_pool_join:
hgs
parents:
diff changeset
   271
 * @pool: a #GstTaskPool
hgs
parents:
diff changeset
   272
 * @id: the id
hgs
parents:
diff changeset
   273
 *
hgs
parents:
diff changeset
   274
 * Join a task and/or return it to the pool. @id is the id obtained from 
hgs
parents:
diff changeset
   275
 * gst_task_pool_push().
hgs
parents:
diff changeset
   276
 */
hgs
parents:
diff changeset
   277
#ifdef __SYMBIAN32__
hgs
parents:
diff changeset
   278
EXPORT_C
hgs
parents:
diff changeset
   279
#endif
hgs
parents:
diff changeset
   280
hgs
parents:
diff changeset
   281
void
hgs
parents:
diff changeset
   282
gst_task_pool_join (GstTaskPool * pool, gpointer id)
hgs
parents:
diff changeset
   283
{
hgs
parents:
diff changeset
   284
  GstTaskPoolClass *klass;
hgs
parents:
diff changeset
   285
hgs
parents:
diff changeset
   286
  g_return_if_fail (GST_IS_TASK_POOL (pool));
hgs
parents:
diff changeset
   287
hgs
parents:
diff changeset
   288
  klass = GST_TASK_POOL_GET_CLASS (pool);
hgs
parents:
diff changeset
   289
hgs
parents:
diff changeset
   290
  if (klass->join)
hgs
parents:
diff changeset
   291
    klass->join (pool, id);
hgs
parents:
diff changeset
   292
}