void next (int state, int is_skip) { struct hemp_playlist_entry *e; static int back_count = 0; time_t now; time(&now); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); if (current) { current->last_played = now; g_queue_push_tail(hotlist, current); } e = g_queue_peek_head(hotlist); if (e && (e->last_played + NO_REPEAT_TIME < now)) { current = g_queue_pop_head(hotlist); } else if (!g_queue_is_empty(coldlist)) { do { current = g_queue_pop_head(coldlist); } while (current->last_played > 0); /* Need to do it this way in case a coldlist entry * is also on the hotlist and has already been played */ } else if (e && is_skip) { current = g_queue_pop_head(hotlist); /* Never skip to silence. */ } else { drop_pipeline(0); return; } current->start_count++; g_object_set (G_OBJECT (pipeline), "uri", current->uri, NULL); if (state == HEMP_STATE_PAUSED) { gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); } else { gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); } }
void queue_add_track(gboolean notif, sp_track* track) { sp_track_add_ref(track); if (!sp_track_is_loaded(track)) { sp_track_release(track); g_debug("Track not loaded."); return; } if (!track_available(track)) { sp_track_release(track); g_debug("Track is not available."); return; } g_debug("Adding track %p to queue.", track); g_queue_push_tail(&g_queue, track); if (g_shuffle) queue_setup_shuffle(); g_shuffle_first = g_current_track; if (notif) queue_notify(); }
/** * @brief Queue a new RTP buffer into the track's queue * * @param tr The track to queue the buffer onto * @param buffer The RTP buffer to queue */ void track_write(Track *tr, struct MParserBuffer *buffer) { /* Make sure the producer is not stopped */ g_assert(g_atomic_int_get(&tr->stopped) == 0); /* Ensure we have the exclusive access */ g_mutex_lock(tr->lock); /* do this inside the lock so that next_serial does not change */ if ( ! buffer->seq_no ) buffer->seq_no = tr->next_serial; tr->next_serial = buffer->seq_no + 1; bq_debug("P:%p PQH:%p elem: %p (%hu)", tr, tr->queue->head, buffer, buffer->seq_no); g_queue_push_tail(tr->queue, buffer); /* Leave the exclusive access */ g_mutex_unlock(tr->lock); }
static void process_fsroot_list (CcnetProcessor *processor) { GList *ptr; char *object_id; USE_PRIV; /* When there are more than one fs roots, there may be many * duplicate fs objects between different commits. * We remember checked fs objects in a hash table to avoid * redundant checks. */ if (priv->n_roots > 1) priv->fs_objects = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); request_object_batch_begin (priv); for (ptr = priv->fs_roots; ptr != NULL; ptr = ptr->next) { object_id = ptr->data; /* Empty dir or file always exists. */ if (strcmp (object_id, EMPTY_SHA1) == 0) { object_id += 41; continue; } #ifdef DEBUG seaf_debug ("[recvfs] Inspect object %s.\n", object_id); #endif g_queue_push_tail (priv->dir_queue, g_strdup(object_id)); g_free (object_id); } g_list_free (priv->fs_roots); priv->fs_roots = NULL; }
static void g_file_monitor_source_queue_event (GFileMonitorSource *fms, GFileMonitorEvent event_type, const gchar *child, GFile *other) { QueuedEvent *event; event = g_slice_new (QueuedEvent); event->event_type = event_type; if (child) event->child = g_local_file_new_from_dirname_and_basename (fms->dirname, child); else if (fms->dirname) event->child = _g_local_file_new (fms->dirname); else if (fms->filename) event->child = _g_local_file_new (fms->filename); event->other = other; if (other) g_object_ref (other); g_queue_push_tail (&fms->event_queue, event); }
static gboolean process_ping (CockpitChannel *self, JsonObject *ping) { GBytes *payload; if (self->priv->throttled) { g_debug ("%s: received ping while throttled", self->priv->id); g_queue_push_tail (self->priv->throttled, json_object_ref (ping)); return FALSE; } else { g_debug ("%s: replying to ping with pong", self->priv->id); json_object_set_string_member (ping, "command", "pong"); payload = cockpit_json_write_bytes (ping); cockpit_transport_send (self->priv->transport, NULL, payload); g_bytes_unref (payload); return TRUE; } }
static SearchThreadData * search_thread_data_new (NemoSearchEngineSimple *engine, NemoQuery *query) { SearchThreadData *data; char *text, *lower, *normalized, *uri; GFile *location; data = g_new0 (SearchThreadData, 1); data->engine = engine; data->directories = g_queue_new (); data->visited = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); uri = nemo_query_get_location (query); location = NULL; if (uri != NULL) { location = g_file_new_for_uri (uri); g_free (uri); } if (location == NULL) { location = g_file_new_for_path ("/"); } g_queue_push_tail (data->directories, location); text = nemo_query_get_text (query); normalized = g_utf8_normalize (text, -1, G_NORMALIZE_NFD); lower = g_utf8_strdown (normalized, -1); data->words = g_strsplit (lower, " ", -1); g_free (text); g_free (lower); g_free (normalized); data->mime_types = nemo_query_get_mime_types (query); data->cancellable = g_cancellable_new (); return data; }
void modem_tones_stop(ModemTones *self, guint source) { ModemTonesPrivate *priv; ModemTonesStoppedNotify *notify; gpointer data; ModemRequest *stopping; DEBUG("(%p, %u)", self, source); g_return_if_fail(self); priv = self->priv; g_return_if_fail(priv->dispose_has_run <= 1); if (!priv->playing) return; if (source && priv->playing != source) return; if (priv->timeout) g_source_remove(priv->timeout); g_assert(priv->timeout == 0); source = priv->playing, priv->playing = 0; notify = priv->notify; data = priv->data; priv->notify = NULL, priv->data = NULL; if (notify) { stopping = modem_request_with_timeout( self, priv->proxy, "StopTone", reply_to_stop_tone, G_CALLBACK(notify), data, 5000, G_TYPE_INVALID); g_queue_push_tail(priv->stop_requests, stopping); modem_request_add_data(stopping, "modem-tones-stop-source", GUINT_TO_POINTER(source)); } }
static void gst_decklink_video_src_got_frame (GstElement * element, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time, GstClockTime capture_duration) { GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element); GST_LOG_OBJECT (self, "Got video frame at %" GST_TIME_FORMAT, GST_TIME_ARGS (capture_time)); gst_decklink_video_src_convert_to_external_clock (self, &capture_time, &capture_duration); GST_LOG_OBJECT (self, "Actual timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (capture_time)); g_mutex_lock (&self->lock); if (!self->flushing) { CaptureFrame *f; while (g_queue_get_length (&self->current_frames) >= self->buffer_size) { f = (CaptureFrame *) g_queue_pop_head (&self->current_frames); GST_WARNING_OBJECT (self, "Dropping old frame at %" GST_TIME_FORMAT, GST_TIME_ARGS (f->capture_time)); capture_frame_free (f); } f = (CaptureFrame *) g_malloc0 (sizeof (CaptureFrame)); f->frame = frame; f->capture_time = capture_time; f->capture_duration = capture_duration; f->mode = mode; frame->AddRef (); g_queue_push_tail (&self->current_frames, f); g_cond_signal (&self->cond); } g_mutex_unlock (&self->lock); }
static void gst_teletextdec_event_handler (vbi_event * ev, void *user_data) { page_info *pi; vbi_pgno pgno; vbi_subno subno; GstTeletextDec *teletext = GST_TELETEXTDEC (user_data); switch (ev->type) { case VBI_EVENT_TTX_PAGE: pgno = ev->ev.ttx_page.pgno; subno = ev->ev.ttx_page.subno; if (pgno != teletext->pageno || (teletext->subno != -1 && subno != teletext->subno)) return; GST_DEBUG_OBJECT (teletext, "Received teletext page %03d.%02d", (gint) vbi_bcd2dec (pgno), (gint) vbi_bcd2dec (subno)); pi = g_new (page_info, 1); pi->pgno = pgno; pi->subno = subno; g_mutex_lock (teletext->queue_lock); g_queue_push_tail (teletext->queue, pi); g_mutex_unlock (teletext->queue_lock); break; case VBI_EVENT_CAPTION: /* TODO: Handle subtitles in caption teletext pages */ GST_DEBUG_OBJECT (teletext, "Received caption page. Not implemented"); break; default: break; } return; }
static void ep_msg_send (EPassMsg *msg) { gint needidle = 0; G_LOCK (passwords); g_queue_push_tail (&message_queue, msg); if (!idle_id) { if (!msg->ismain) idle_id = g_idle_add (ep_idle_dispatch, NULL); else needidle = 1; } G_UNLOCK (passwords); if (msg->ismain) { if (needidle) ep_idle_dispatch (NULL); while (!e_flag_is_set (msg->done)) g_main_context_iteration (NULL, TRUE); } else e_flag_wait (msg->done); }
/** ******************************************************************************* * @brief Save a serial (token) in the queue and map. * * @attention locks the serial lock * * @param serial_info IN serial info * @param serial IN message serial (token) to save * @param lserror OUT set on error * * @retval true on success * @retval false on failure ******************************************************************************* */ bool _LSTransportSerialSave(_LSTransportSerial *serial_info, _LSTransportMessage *message, LSError *lserror) { LSMessageToken serial = _LSTransportMessageGetToken(message); _LSTransportSerialListItem *item = _LSTransportSerialListItemNew(serial, message); SERIAL_INFO_LOCK(&serial_info->lock); g_queue_push_tail(serial_info->queue, item); GList *list = g_queue_peek_tail_link(serial_info->queue); LS_ASSERT(list != NULL); _LSTransportSerialMapEntry *map_entry = _LSTransportSerialMapEntryNew(serial, list); LS_ASSERT(NULL == g_hash_table_lookup(serial_info->map, &map_entry->serial)); g_hash_table_insert(serial_info->map, &map_entry->serial, map_entry); SERIAL_INFO_UNLOCK(&serial_info->lock); return true; }
static GstFlowReturn gst_videoframe_audiolevel_vsink_chain (GstPad * pad, GstObject * parent, GstBuffer * inbuf) { GstClockTime timestamp; GstVideoFrameAudioLevel *self = GST_VIDEOFRAME_AUDIOLEVEL (parent); GstClockTime duration; GstClockTime *ptrtime = g_new (GstClockTime, 1); timestamp = GST_BUFFER_TIMESTAMP (inbuf); *ptrtime = gst_segment_to_running_time (&self->vsegment, GST_FORMAT_TIME, timestamp); g_mutex_lock (&self->mutex); self->vsegment.position = timestamp; duration = GST_BUFFER_DURATION (inbuf); if (duration != GST_CLOCK_TIME_NONE) self->vsegment.position += duration; g_queue_push_tail (&self->vtimeq, ptrtime); g_cond_signal (&self->cond); GST_DEBUG_OBJECT (pad, "Pushed a frame"); g_mutex_unlock (&self->mutex); return gst_pad_push (self->vsrcpad, inbuf); }
static void gegl_tile_backend_swap_push_queue (ThreadParams *params) { g_mutex_lock (&mutex); /* block if the queue has gotten too big */ while (queue_size > gegl_config ()->queue_size) g_cond_wait (&max_cond, &mutex); g_queue_push_tail (queue, params); if (params->operation == OP_WRITE) { params->entry->link = g_queue_peek_tail_link (queue); queue_size += params->length + sizeof (GList) + sizeof (ThreadParams); } /* wake up the writer thread */ g_cond_signal (&queue_cond); g_mutex_unlock (&mutex); }
static void on_send_data (GstDtlsConnection * connection, gconstpointer data, gint length, GstDtlsEnc * self) { GstBuffer *buffer; GST_DEBUG_OBJECT (self, "sending data from %s with length %d", self->connection_id, length); buffer = gst_buffer_new_wrapped (g_memdup (data, length), length); GST_TRACE_OBJECT (self, "send data: acquiring lock"); g_mutex_lock (&self->queue_lock); GST_TRACE_OBJECT (self, "send data: acquired lock"); g_queue_push_tail (&self->queue, buffer); GST_TRACE_OBJECT (self, "send data: signaling add"); g_cond_signal (&self->queue_cond_add); GST_TRACE_OBJECT (self, "send data: releasing lock"); g_mutex_unlock (&self->queue_lock); }
static void gst_buffer_copy_qdata (GstBuffer * dest, const GstBuffer * src) { GstBufferPrivate *priv; GQueue qdata_copy = G_QUEUE_INIT; GList *l; if (G_LIKELY (src->priv == NULL)) return; for (l = src->priv->qdata; l != NULL; l = l->next) { GstStructure *s = gst_structure_copy (l->data); gst_structure_set_parent_refcount (s, &dest->mini_object.refcount); g_queue_push_tail (&qdata_copy, s); GST_CAT_TRACE (GST_CAT_BUFFER, "copying qdata '%s' from buffer %p to %p", g_quark_to_string (s->name), src, dest); } priv = gst_buffer_ensure_priv (dest); priv->qdata = qdata_copy.head; }
void queue_generate(ThumbnailTask* regenerate_task) { ThumbnailTask* task; G_LOCK(queue); task = find_queued_task(&generator_queue, regenerate_task->fi); if(task) { task->flags |= regenerate_task->flags; task->requests = g_list_concat(task->requests, regenerate_task->requests); regenerate_task->requests = NULL; thumbnail_task_free(regenerate_task); G_UNLOCK(queue); return; } DEBUG("push into generator queue"); g_queue_push_tail(&generator_queue, regenerate_task); if(!generator_thread_id) generator_thread_id = g_thread_create(generate_thumbnail_thread, NULL, FALSE, NULL); G_UNLOCK(queue); }
static void file_builder_add_string (FileBuilder *fb, const gchar *string, guint32_le *start, guint16_le *size) { FileChunk *chunk; gsize length; length = strlen (string); chunk = g_slice_new (FileChunk); chunk->offset = fb->offset; chunk->size = length; chunk->data = g_malloc (length); memcpy (chunk->data, string, length); *start = guint32_to_le (fb->offset); *size = guint16_to_le (length); fb->offset += length; g_queue_push_tail (fb->chunks, chunk); }
/************************ *** Queue management *** ************************/ void queue_set_track(gboolean notif, sp_track* track) { sp_track_add_ref(track); if (!sp_track_is_loaded(track)) { sp_track_release(track); g_debug("Track not loaded."); return; } if (!track_available(track)) { sp_track_release(track); g_debug("Track is not available."); return; } g_debug("Setting track %p as queue.", track); queue_clear(FALSE); g_queue_push_tail(&g_queue, track); if (g_shuffle) queue_setup_shuffle(); g_shuffle_first = -1; if (notif) queue_notify(); }
static GstFlowReturn vorbis_parse_queue_buffer (GstVorbisParse * parse, GstBuffer * buf) { GstFlowReturn ret = GST_FLOW_OK; long blocksize; ogg_packet packet; GstMapInfo map; buf = gst_buffer_make_writable (buf); gst_buffer_map (buf, &map, GST_MAP_READ); packet.packet = map.data; packet.bytes = map.size; GST_DEBUG ("%p, %" G_GSIZE_FORMAT, map.data, map.size); packet.granulepos = GST_BUFFER_OFFSET_END (buf); packet.packetno = parse->packetno + parse->buffer_queue->length; packet.e_o_s = 0; blocksize = vorbis_packet_blocksize (&parse->vi, &packet); gst_buffer_unmap (buf, &map); /* temporarily store the sample count in OFFSET -- we overwrite this later */ if (parse->prev_blocksize < 0) GST_BUFFER_OFFSET (buf) = 0; else GST_BUFFER_OFFSET (buf) = (blocksize + parse->prev_blocksize) / 4; parse->prev_blocksize = blocksize; g_queue_push_tail (parse->buffer_queue, buf); if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) ret = vorbis_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf)); return ret; }
static size_t rtsp_client_socket_data(const void *_data, size_t length, void *ctx) { struct rtspcl_data *rtspcld = ctx; g_mutex_lock(rtspcld->mutex); if (rtspcld->tcp_socket == NULL) { g_mutex_unlock(rtspcld->mutex); return 0; } const bool was_empty = g_queue_is_empty(rtspcld->received_lines); bool added = false; const char *data = _data, *end = data + length, *p = data, *eol; while ((eol = memchr(p, '\n', end - p)) != NULL) { const char *next = eol + 1; if (rtspcld->received_lines->length < 64) { if (eol > p && eol[-1] == '\r') --eol; g_queue_push_tail(rtspcld->received_lines, g_strndup(p, eol - p)); added = true; } p = next; } if (was_empty && added) g_cond_broadcast(rtspcld->cond); g_mutex_unlock(rtspcld->mutex); return p - data; }
static void missing_plugins_retry_cb (gpointer instance, gboolean installed, RhythmDBImportJob *job) { GSList *i; g_mutex_lock (&job->priv->lock); g_assert (job->priv->retried == FALSE); if (installed == FALSE) { rb_debug ("plugin installation was not successful; job complete"); job->priv->complete = TRUE; g_signal_emit (job, signals[COMPLETE], 0, job->priv->total); g_object_notify (G_OBJECT (job), "task-outcome"); } else { job->priv->retried = TRUE; /* reset the job state to just show the retry information */ job->priv->total = g_slist_length (job->priv->retry_entries); rb_debug ("plugin installation was successful, retrying %d entries", job->priv->total); job->priv->processed = 0; /* remove the import error entries and build the list of URIs to retry */ for (i = job->priv->retry_entries; i != NULL; i = i->next) { RhythmDBEntry *entry = (RhythmDBEntry *)i->data; char *uri; uri = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_LOCATION); rhythmdb_entry_delete (job->priv->db, entry); g_queue_push_tail (job->priv->outstanding, g_strdup (uri)); } rhythmdb_commit (job->priv->db); } maybe_start_more (job); g_mutex_unlock (&job->priv->lock); }
/// Append a ResourceCmd to a ResourceQueue FSTATIC gboolean _resource_queue_cmd_append(ResourceQueue* self, ResourceCmd* cmd , ResourceCmdCallback cb, gpointer user_data) { GQueue* q; RscQElem* qelem; gint64 requestid; requestid = cmd->request->getint(cmd->request, REQIDENTIFIERNAMEFIELD); if (requestid <= 0) { g_warning("%s.%d: Request rejected - no request id for resource %s." , __FUNCTION__, __LINE__, cmd->resourcename); return FALSE; } q = g_hash_table_lookup(self->resources, cmd->resourcename); if (NULL == q) { q = g_queue_new(); g_hash_table_insert(self->resources, g_strdup(cmd->resourcename), q); } qelem = _resource_queue_qelem_new(cmd, self, cb, user_data, q); cmd->user_data = qelem; qelem->requestid = requestid; if (g_queue_find_custom(q, qelem, _queue_compare_requestid)) { // This can happen if the CMA crashes and restarts and for other reasons. // But we shouldn't obey it in any case... g_info("%s:%d: Duplicate request id ["FMT_64BIT"d] for resource %s - ignored." , __FUNCTION__, __LINE__, requestid, cmd->resourcename); _resource_queue_qelem_finalize(qelem); qelem = NULL; return FALSE; } g_queue_push_tail(q, qelem); if (self->timerid < 0) { self->timerid = g_timeout_add_seconds(1, _resource_queue_runqueue, self); } return TRUE; }
static void __nominate_pairs(struct ice_agent *ag) { GQueue complete; GList *l; struct ice_candidate_pair *pair; ilog(LOG_DEBUG, "Start nominating ICE pairs"); AGENT_SET(ag, NOMINATING); ZERO(ag->start_nominating); __get_complete_succeeded_pairs(&complete, ag); for (l = complete.head; l; l = l->next) { pair = l->data; ilog(LOG_DEBUG, "Nominating ICE pair "PAIR_FORMAT, PAIR_FMT(pair)); PAIR_CLEAR(pair, IN_PROGRESS); PAIR_SET2(pair, NOMINATED, TO_USE); pair->retransmits = 0; __new_stun_transaction(pair); g_queue_push_tail(&ag->triggered, pair); } g_queue_clear(&complete); }
void janus_streaming_hangup_media(janus_plugin_session *handle) { JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n"); if(stopping || !initialized) return; janus_streaming_session *session = (janus_streaming_session *)handle->plugin_handle; if(!session) { JANUS_LOG(LOG_ERR, "No session associated with this handle...\n"); return; } if(session->destroy) return; /* FIXME Simulate a "stop" coming from the browser */ janus_streaming_message *msg = calloc(1, sizeof(janus_streaming_message)); if(msg == NULL) { JANUS_LOG(LOG_FATAL, "Memory error!\n"); return; } msg->handle = handle; msg->message = g_strdup("{\"request\":\"stop\"}"); msg->transaction = NULL; msg->sdp_type = NULL; msg->sdp = NULL; g_queue_push_tail(messages, msg); }
/* must be called with lock held */ static void maybe_start_more (RhythmDBImportJob *job) { if (g_cancellable_is_cancelled (job->priv->cancel)) { return; } while (g_queue_get_length (job->priv->processing) < PROCESSING_LIMIT) { char *uri; uri = g_queue_pop_head (job->priv->outstanding); if (uri == NULL) { return; } g_queue_push_tail (job->priv->processing, uri); rhythmdb_add_uri_with_types (job->priv->db, uri, job->priv->entry_type, job->priv->ignore_type, job->priv->error_type); } }
static void msn_soap_message_send_internal(MsnSession *session, MsnSoapMessage *message, const char *host, const char *path, gboolean secure, MsnSoapCallback cb, gpointer cb_data, gboolean first) { MsnSoapConnection *conn = msn_soap_get_connection(session, host); MsnSoapRequest *req = g_new0(MsnSoapRequest, 1); req->path = g_strdup(path); req->message = message; req->secure = secure; req->cb = cb; req->cb_data = cb_data; if (first) { g_queue_push_head(conn->queue, req); } else { g_queue_push_tail(conn->queue, req); } if (conn->run_timer == 0) conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn); }
static void unqueue_old_buffers(int stream) { audio_stream *s = g_streams[stream]; ALint old_buffers = 0; g_mutex_lock(s->mutex); // locking here because unqueue_old_buffers can be run called from // both the video thread and the emulation thread (consider changing this, // perhaps even have a separate thread for periodically unqueuing). alGetSourcei(s->source, AL_BUFFERS_PROCESSED, &old_buffers); check_al_error("alGetSourcei (AL_BUFFERS_PROCESSED)"); if (old_buffers > 0) { ALuint buffers[MAX_BUFFERS]; old_buffers = MIN(old_buffers, MAX_BUFFERS); alSourceUnqueueBuffers(s->source, old_buffers, buffers); if (check_al_error("alSourceUnqueueBuffers") != AL_NO_ERROR) { fs_log("while trying to unqueue %d buffers\n"); } for (int i = 0; i < old_buffers; i++) { g_queue_push_tail(s->queue, GUINT_TO_POINTER(buffers[i])); } s->buffers_queued -= old_buffers; } g_mutex_unlock(s->mutex); }
static gboolean kms_image_overlay_sink_events (GstBaseTransform * trans, GstEvent * event) { KmsImageOverlay *imageoverlay = KMS_IMAGE_OVERLAY (trans); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CUSTOM_DOWNSTREAM: { GstStructure *faces; GST_OBJECT_LOCK (imageoverlay); faces = gst_structure_copy (gst_event_get_structure (event)); g_queue_push_tail (imageoverlay->priv->events_queue, faces); GST_OBJECT_UNLOCK (imageoverlay); break; } default: break; } return gst_pad_event_default (trans->sinkpad, GST_OBJECT (trans), event); }
/* Returns: the id of the job within this queue */ guint32 queue_queue (Queue * queue, GThreadFunc async, GFunc destroy, gpointer user_data) { struct QueueJob* job; g_return_if_fail (async != NULL); g_return_if_fail (queue != NULL); job = queue_job_new (queue->last_job_id++, queue, async, destroy, user_data); if (G_UNLIKELY (queue->idle_threads)) { /* schedule immediately */ queue_schedule_job (queue, job); } else { /* queue for scheduling */ g_queue_push_tail (queue->jobs, job); } return job->id; }