void dt_lua_lock() { if(!darktable.lua_state.ending && pthread_equal(darktable.control->gui_thread, pthread_self()) != 0) { dt_print(DT_DEBUG_LUA, "LUA WARNING locking from the gui thread should be avoided\n"); //g_assert(false); } dt_pthread_mutex_lock(&darktable.lua_state.mutex); }
static gboolean _dt_ctl_log_message_timeout_callback(gpointer data) { dt_pthread_mutex_lock(&darktable.control->log_mutex); if(darktable.control->log_ack != darktable.control->log_pos) darktable.control->log_ack = (darktable.control->log_ack + 1) % DT_CTL_LOG_SIZE; darktable.control->log_message_timeout_id = 0; dt_pthread_mutex_unlock(&darktable.control->log_mutex); dt_control_queue_redraw_center(); return FALSE; }
void dt_control_progress_set_progress(dt_control_t *control, dt_progress_t *progress, double value) { // set the value dt_pthread_mutex_lock(&progress->mutex); progress->progress = value; dt_pthread_mutex_unlock(&progress->mutex); // tell the gui dt_pthread_mutex_lock(&control->progress_system.mutex); if(control->progress_system.proxy.module != NULL) control->progress_system.proxy.updated(control->progress_system.proxy.module, progress->gui_data, value); dt_pthread_mutex_unlock(&control->progress_system.mutex); #ifdef HAVE_UNITY if(progress->has_progress_bar) unity_launcher_entry_set_progress(progress->darktable_launcher, CLAMP(value, 0, 1.0)); #endif }
void dt_lua_init_lock() { pthread_mutexattr_t a; pthread_mutexattr_init(&a); pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE); dt_pthread_mutex_init(&darktable.lua_state.mutex, &a); pthread_mutexattr_destroy(&a); // we want our lock initialized locked dt_pthread_mutex_lock(&darktable.lua_state.mutex); }
void dt_dev_module_remove(dt_develop_t *dev, dt_iop_module_t *module) { //if(darktable.gui->reset) return; dt_pthread_mutex_lock(&dev->history_mutex); int del = 0; if(dev->gui_attached) { int nb = g_list_length(dev->history); int pos = 0; for (int i=0; i<nb; i++) { GList *elem = g_list_nth(dev->history,pos); dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(elem->data); if (module->instance == hist->module->instance && module->multi_priority == hist->module->multi_priority) { free(hist->params); free(hist->blend_params); free(hist); dev->history = g_list_delete_link(dev->history, elem); dev->history_end--; del = 1; } else { pos++; } } } dt_pthread_mutex_unlock(&dev->history_mutex); //and we remove it from the list GList *modules = g_list_first(dev->iop); while(modules) { dt_iop_module_t *mod = (dt_iop_module_t *)modules->data; if(mod == module) { dev->iop = g_list_remove_link(dev->iop,modules); break; } modules = g_list_next(modules); } if(dev->gui_attached && del) { /* signal that history has changed */ dt_control_signal_raise(darktable.signals, DT_SIGNAL_DEVELOP_HISTORY_CHANGE); /* redraw */ dt_control_queue_redraw_center(); } }
void gui_update(struct dt_iop_module_t *self) { dt_iop_exposure_gui_data_t *g = (dt_iop_exposure_gui_data_t *)self->gui_data; dt_iop_exposure_params_t *p = (dt_iop_exposure_params_t *)self->params; if(!dt_image_is_raw(&self->dev->image_storage)) { gtk_widget_hide(GTK_WIDGET(g->mode)); p->mode = EXPOSURE_MODE_MANUAL; dt_dev_add_history_item(darktable.develop, self, TRUE); } else { gtk_widget_show(GTK_WIDGET(g->mode)); } dt_bauhaus_combobox_set(g->mode, g_list_index(g->modes, GUINT_TO_POINTER(p->mode))); dt_bauhaus_slider_set_soft(g->black, p->black); dt_bauhaus_slider_set_soft(g->exposure, p->exposure); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoexp), FALSE); dt_bauhaus_slider_set(g->autoexpp, 0.01); gtk_widget_set_sensitive(GTK_WIDGET(g->autoexpp), FALSE); dt_bauhaus_slider_set(g->deflicker_percentile, p->deflicker_percentile); dt_bauhaus_slider_set(g->deflicker_target_level, p->deflicker_target_level); dt_bauhaus_combobox_set( g->deflicker_histogram_source, g_list_index(g->deflicker_histogram_sources, GUINT_TO_POINTER(p->deflicker_histogram_source))); self->request_color_pick = DT_REQUEST_COLORPICK_OFF; free(g->deflicker_histogram); g->deflicker_histogram = NULL; gtk_label_set_text(g->deflicker_used_EC, ""); dt_pthread_mutex_lock(&g->lock); g->deflicker_computed_exposure = NAN; dt_pthread_mutex_unlock(&g->lock); switch(p->mode) { case EXPOSURE_MODE_DEFLICKER: autoexp_disable(self); gtk_stack_set_visible_child_name(GTK_STACK(g->mode_stack), "deflicker"); if(p->deflicker_histogram_source == DEFLICKER_HISTOGRAM_SOURCE_SOURCEFILE) deflicker_prepare_histogram(self, &g->deflicker_histogram, &g->deflicker_histogram_stats); break; case EXPOSURE_MODE_MANUAL: default: gtk_stack_set_visible_child_name(GTK_STACK(g->mode_stack), "manual"); break; } }
void _camera_configuration_update(const dt_camctl_t *c,const dt_camera_t *camera) { // dt_camctl_t *camctl=(dt_camctl_t *)c; dt_camera_t *cam=(dt_camera_t *)camera; dt_pthread_mutex_lock(&cam->config_lock); CameraWidget *remote; // Copy of remote configuration gp_camera_get_config( camera->gpcam, &remote, c->gpcontext ); // merge remote copy with cache and notify on changed properties to host application _camera_configuration_merge(c, camera, remote, camera->configuration, FALSE ); dt_pthread_mutex_unlock(&cam->config_lock); }
static int32_t dt_control_run_job(dt_control_t *control) { _dt_job_t *job = dt_control_schedule_job(control); if(!job) return -1; /* change state to running */ dt_pthread_mutex_lock(&job->wait_mutex); if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED) { dt_print(DT_DEBUG_CONTROL, "[run_job+] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(), dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); dt_control_job_set_state(job, DT_JOB_STATE_RUNNING); /* execute job */ job->result = job->execute(job); dt_control_job_set_state(job, DT_JOB_STATE_FINISHED); dt_print(DT_DEBUG_CONTROL, "[run_job-] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(), dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); } dt_pthread_mutex_unlock(&job->wait_mutex); // remove the job from scheduled job array (for job deduping) dt_pthread_mutex_lock(&control->queue_mutex); control->job[dt_control_get_threadid()] = NULL; if(job->queue == DT_JOB_QUEUE_USER_EXPORT) control->export_scheduled = FALSE; dt_pthread_mutex_unlock(&control->queue_mutex); // and free it dt_control_job_dispose(job); return 0; }
void dt_control_job_wait(dt_job_t *j) { int state = dt_control_job_get_state (j); /* if job execution not is finished let's wait for signal */ if (state==DT_JOB_STATE_RUNNING || state==DT_JOB_STATE_CANCELLED) { dt_pthread_mutex_lock (&j->wait_mutex); dt_pthread_mutex_unlock (&j->wait_mutex); } }
void dt_control_job_wait(_dt_job_t *job) { if(!job) return; dt_job_state_t state = dt_control_job_get_state(job); /* if job execution is not finished let's wait for signal */ if(state == DT_JOB_STATE_RUNNING || state == DT_JOB_STATE_CANCELLED) { dt_pthread_mutex_lock(&job->wait_mutex); dt_pthread_mutex_unlock(&job->wait_mutex); } }
static void *dt_control_worker_kicker(void *ptr) { dt_control_t *control = (dt_control_t *)ptr; while(dt_control_running()) { sleep(2); dt_pthread_mutex_lock(&control->cond_mutex); pthread_cond_broadcast(&control->cond); dt_pthread_mutex_unlock(&control->cond_mutex); } return NULL; }
void dt_control_shutdown(dt_control_t *s) { dt_pthread_mutex_lock(&s->cond_mutex); dt_pthread_mutex_lock(&s->run_mutex); s->running = 0; dt_pthread_mutex_unlock(&s->run_mutex); dt_pthread_mutex_unlock(&s->cond_mutex); pthread_cond_broadcast(&s->cond); /* first wait for kick_on_workers_thread */ pthread_join(s->kick_on_workers_thread, NULL); int k; for(k = 0; k < s->num_threads; k++) // pthread_kill(s->thread[k], 9); pthread_join(s->thread[k], NULL); for(k = 0; k < DT_CTL_WORKER_RESERVED; k++) // pthread_kill(s->thread_res[k], 9); pthread_join(s->thread_res[k], NULL); }
void dt_control_set_mouse_over_id(int32_t value) { dt_pthread_mutex_lock(&(darktable.control->global_mutex)); if(darktable.control->mouse_over_id != value) { darktable.control->mouse_over_id = value; dt_pthread_mutex_unlock(&(darktable.control->global_mutex)); dt_control_signal_raise(darktable.signals, DT_SIGNAL_MOUSE_OVER_IMAGE_CHANGE); } else dt_pthread_mutex_unlock(&(darktable.control->global_mutex)); }
int dt_cache_remove(dt_cache_t *cache, const uint32_t key) { gpointer orig_key, value; gboolean res; int result; dt_cache_entry_t *entry; restart: dt_pthread_mutex_lock(&cache->lock); res = g_hash_table_lookup_extended( cache->hashtable, GINT_TO_POINTER(key), &orig_key, &value); entry = (dt_cache_entry_t *)value; if(!res) { // not found in cache, not deleting. dt_pthread_mutex_unlock(&cache->lock); return 1; } // need write lock to be able to delete: result = dt_pthread_rwlock_trywrlock(&entry->lock); if(result) { dt_pthread_mutex_unlock(&cache->lock); g_usleep(5); goto restart; } if(entry->_lock_demoting) { // oops, we are currently demoting (rw -> r) lock to this entry in some thread. do not touch! dt_pthread_rwlock_unlock(&entry->lock); dt_pthread_mutex_unlock(&cache->lock); g_usleep(5); goto restart; } gboolean removed = g_hash_table_remove(cache->hashtable, GINT_TO_POINTER(key)); (void)removed; // make non-assert compile happy assert(removed); cache->lru = g_list_delete_link(cache->lru, entry->link); if(cache->cleanup) cache->cleanup(cache->cleanup_data, entry); else dt_free_align(entry->data); dt_pthread_rwlock_unlock(&entry->lock); dt_pthread_rwlock_destroy(&entry->lock); cache->cost -= entry->cost; g_slice_free1(sizeof(*entry), entry); dt_pthread_mutex_unlock(&cache->lock); return 0; }
gboolean dt_lua_lock() { gboolean had_lock = dt_control_gdk_haslock(); if(had_lock){ dt_control_gdk_unlock(); } if(!darktable.lua_state.ending && pthread_equal(darktable.control->gui_thread,pthread_self()) != 0) { dt_print(DT_DEBUG_LUA,"LUA WARNING locking from the gui thread should be avoided\n"); } dt_pthread_mutex_lock(&darktable.lua_state.mutex); return had_lock; }
gpointer _camera_get_job( const dt_camctl_t *c,const dt_camera_t *camera ) { dt_camera_t *cam=(dt_camera_t *)camera; dt_pthread_mutex_lock(&cam->jobqueue_lock); gpointer job=NULL; if( g_list_length(cam->jobqueue) > 0 ) { job = g_list_nth_data(cam->jobqueue,0); cam->jobqueue = g_list_remove(cam->jobqueue,job); } dt_pthread_mutex_unlock(&cam->jobqueue_lock); return job; }
void dt_lua_lock_internal(const char *function, const char *file, int line, gboolean silent) { if(!silent && !darktable.lua_state.ending && pthread_equal(darktable.control->gui_thread, pthread_self()) != 0) { dt_print(DT_DEBUG_LUA, "LUA WARNING locking from the gui thread should be avoided\n"); //g_assert(false); } dt_pthread_mutex_lock(&darktable.lua_state.mutex); #ifdef _DEBUG dt_print(DT_DEBUG_LUA,"LUA DEBUG : %s called from %s:%d (%s)\n", __FUNCTION__, file, line, function); #endif }
void _camera_configuration_commit(const dt_camctl_t *c,const dt_camera_t *camera) { g_assert( camera != NULL ); dt_camera_t *cam=(dt_camera_t *)camera; dt_pthread_mutex_lock(&cam->config_lock); if( gp_camera_set_config( camera->gpcam, camera->configuration, c->gpcontext) != GP_OK ) dt_print(DT_DEBUG_CAMCTL,"[camera_control] Failed to commit configuration changes to camera\n"); cam->config_changed=FALSE; dt_pthread_mutex_unlock(&cam->config_lock); }
void dt_opencl_free_kernel(const int kernel) { dt_opencl_t *cl = darktable.opencl; if(!cl->inited) return; if(kernel < 0 || kernel >= DT_OPENCL_MAX_KERNELS) return; dt_pthread_mutex_lock(&cl->lock); for(int dev=0; dev<cl->num_devs; dev++) { cl->dev[dev].kernel_used [kernel] = 0; (cl->dlocl->symbols->dt_clReleaseKernel) (cl->dev[dev].kernel [kernel]); } dt_pthread_mutex_unlock(&cl->lock); }
void dt_camctl_register_listener( const dt_camctl_t *c, dt_camctl_listener_t *listener) { dt_camctl_t *camctl=(dt_camctl_t *)c; // Just locking mutex and prevent signalling CAMERA_CONTROL_BUSY dt_pthread_mutex_lock(&camctl->lock); if( g_list_find(camctl->listeners,listener) == NULL ) { camctl->listeners=g_list_append(camctl->listeners,listener); dt_print(DT_DEBUG_CAMCTL,"[camera_control] registering listener %lx\n",(unsigned long int)listener); } else dt_print(DT_DEBUG_CAMCTL,"[camera_control] registering already registered listener %lx\n",(unsigned long int)listener); dt_pthread_mutex_unlock(&camctl->lock); }
void dt_control_gdk_unlock() { /* check if current thread has a lock and remove if exists */ dt_pthread_mutex_lock(&_control_gdk_lock_threads_mutex); if(_control_gdk_lock_mine) { /* remove lock */ _control_gdk_lock_mine = FALSE; /* leave critical section */ gdk_threads_leave(); } dt_pthread_mutex_unlock(&_control_gdk_lock_threads_mutex); }
int32_t dt_film_import1_run(dt_job_t *job) { dt_film_import1_t *t = (dt_film_import1_t *)job->param; dt_film_import1(t->film); dt_pthread_mutex_lock(&t->film->images_mutex); t->film->ref--; dt_pthread_mutex_unlock(&t->film->images_mutex); if(t->film->ref <= 0) { dt_film_cleanup(t->film); free(t->film); } return 0; }
static void dt_control_job_set_state(_dt_job_t *job, dt_job_state_t state) { if(!job) return; dt_pthread_mutex_lock(&job->state_mutex); if(state >= DT_JOB_STATE_FINISHED && job->state != DT_JOB_STATE_RUNNING && job->progress) { dt_control_progress_destroy(darktable.control, job->progress); job->progress = NULL; } job->state = state; /* pass state change to callback */ if(job->state_changed_cb) job->state_changed_cb(job, state); dt_pthread_mutex_unlock(&job->state_mutex); }
static int32_t dt_control_run_job_res(dt_control_t *control, int32_t res) { if(((unsigned int)res) >= DT_CTL_WORKER_RESERVED) return -1; _dt_job_t *job = NULL; dt_pthread_mutex_lock(&control->queue_mutex); if(control->new_res[res]) { job = control->job_res[res]; control->job_res[res] = NULL; // this job belongs to us now, the queue may not touch it any longer } control->new_res[res] = 0; dt_pthread_mutex_unlock(&control->queue_mutex); if(!job) return -1; /* change state to running */ dt_pthread_mutex_lock(&job->wait_mutex); if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED) { dt_print(DT_DEBUG_CONTROL, "[run_job+] %02d %f ", res, dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); dt_control_job_set_state(job, DT_JOB_STATE_RUNNING); /* execute job */ job->result = job->execute(job); dt_control_job_set_state(job, DT_JOB_STATE_FINISHED); dt_print(DT_DEBUG_CONTROL, "[run_job-] %02d %f ", res, dt_get_wtime()); dt_control_job_print(job); dt_print(DT_DEBUG_CONTROL, "\n"); } dt_pthread_mutex_unlock(&job->wait_mutex); dt_control_job_dispose(job); return 0; }
int dt_film_new(dt_film_t *film, const char *directory) { // Try open filmroll for folder if exists film->id = -1; int rc; sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from film_rolls where folder = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, directory, strlen(directory), SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) film->id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); if(film->id <= 0) { // create a new filmroll sqlite3_stmt *stmt; char datetime[20]; dt_gettime(datetime); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into film_rolls (id, datetime_accessed, folder) " "values (null, ?1, ?2)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, datetime, strlen(datetime), SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, directory, strlen(directory), SQLITE_STATIC); dt_pthread_mutex_lock(&darktable.db_insert); rc = sqlite3_step(stmt); if(rc != SQLITE_DONE) fprintf(stderr, "[film_new] failed to insert film roll! %s\n", sqlite3_errmsg(dt_database_get(darktable.db))); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from film_rolls where folder=?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, directory, strlen(directory), SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) film->id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); dt_pthread_mutex_unlock(&darktable.db_insert); } if(film->id<=0) return 0; g_strlcpy(film->dirname,directory,sizeof(film->dirname)); film->last_loaded = 0; return film->id; }
static int32_t dt_control_run_job(dt_control_t *control) { _dt_job_t *job = dt_control_schedule_job(control); if(!job) return -1; /* change state to running */ dt_pthread_mutex_lock(&job->wait_mutex); if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED) dt_control_job_execute(job); dt_pthread_mutex_unlock(&job->wait_mutex); // remove the job from scheduled job array (for job deduping) dt_pthread_mutex_lock(&control->queue_mutex); control->job[dt_control_get_threadid()] = NULL; if(job->queue == DT_JOB_QUEUE_USER_EXPORT) control->export_scheduled = FALSE; dt_pthread_mutex_unlock(&control->queue_mutex); // and free it dt_control_job_dispose(job); return 0; }
void dt_control_log(const char *msg, ...) { dt_pthread_mutex_lock(&darktable.control->log_mutex); va_list ap; va_start(ap, msg); vsnprintf(darktable.control->log_message[darktable.control->log_pos], DT_CTL_LOG_MSG_SIZE, msg, ap); va_end(ap); if(darktable.control->log_message_timeout_id) g_source_remove(darktable.control->log_message_timeout_id); darktable.control->log_ack = darktable.control->log_pos; darktable.control->log_pos = (darktable.control->log_pos + 1) % DT_CTL_LOG_SIZE; darktable.control->log_message_timeout_id = g_timeout_add(DT_CTL_LOG_TIMEOUT, _dt_ctl_log_message_timeout_callback, NULL); dt_pthread_mutex_unlock(&darktable.control->log_mutex); dt_control_queue_redraw_center(); }
void dt_control_progress_cancel(dt_control_t *control, dt_progress_t *progress) { dt_pthread_mutex_lock(&progress->mutex); if(progress->cancel == NULL) { dt_pthread_mutex_unlock(&progress->mutex); return; } // call the cancel callback progress->cancel(progress, progress->cancel_data); dt_pthread_mutex_unlock(&progress->mutex); // the gui doesn't need to know I guess, it wouldn't to anything with that bit of information }
static int32_t dt_film_import1_run(dt_job_t *job) { dt_film_import1_t *params = dt_control_job_get_params(job); dt_film_import1(job, params->film); dt_pthread_mutex_lock(¶ms->film->images_mutex); params->film->ref--; dt_pthread_mutex_unlock(¶ms->film->images_mutex); if(params->film->ref <= 0) { if(dt_film_is_empty(params->film->id)) { dt_film_remove(params->film->id); } } return 0; }
static void _lib_history_change_callback(gpointer instance, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_history_t *d = (dt_lib_history_t *)self->data; /* first destroy all buttons in list */ gtk_container_foreach(GTK_CONTAINER(d->history_box), (GtkCallback)gtk_widget_destroy, 0); /* add default which always should be */ int num = -1; gtk_box_pack_start(GTK_BOX(d->history_box), _lib_history_create_button(self, num, _("original"), FALSE, darktable.develop->history_end == 0), TRUE, TRUE, 0); num++; /* lock history mutex */ dt_pthread_mutex_lock(&darktable.develop->history_mutex); /* iterate over history items and add them to list*/ GList *history = g_list_first(darktable.develop->history); while(history) { dt_dev_history_item_t *hitem = (dt_dev_history_item_t *)(history->data); gchar *label; if(!hitem->multi_name[0] || strcmp(hitem->multi_name, "0") == 0) label = g_strdup_printf("%s", hitem->module->name()); else label = g_strdup_printf("%s %s", hitem->module->name(), hitem->multi_name); gboolean selected = (num == darktable.develop->history_end - 1); GtkWidget *widget = _lib_history_create_button(self, num, label, hitem->enabled, selected); g_free(label); gtk_box_pack_start(GTK_BOX(d->history_box), widget, TRUE, TRUE, 0); gtk_box_reorder_child(GTK_BOX(d->history_box), widget, 0); num++; history = g_list_next(history); } /* show all widgets */ gtk_widget_show_all(d->history_box); dt_pthread_mutex_unlock(&darktable.develop->history_mutex); }