/* * fm-job.h * * Copyright 2009 PCMan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __FM_JOB_H__ #define __FM_JOB_H__ #include #include #include G_BEGIN_DECLS #define FM_TYPE_JOB (fm_job_get_type()) #define FM_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ FM_TYPE_JOB, FmJob)) #define FM_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\ FM_TYPE_JOB, FmJobClass)) #define FM_IS_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\ FM_TYPE_JOB)) #define FM_IS_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ FM_TYPE_JOB)) typedef struct _FmJob FmJob; typedef struct _FmJobClass FmJobClass; typedef gpointer (*FmJobCallMainThreadFunc)(FmJob* job, gpointer user_data); typedef enum _FmJobErrorSeverity FmJobErrorSeverity; enum _FmJobErrorSeverity { FM_JOB_ERROR_WARNING, /* not an error, just a warning */ FM_JOB_ERROR_MILD, /* no big deal, can be ignored most of the time */ FM_JOB_ERROR_MODERATE, /* moderate errors */ FM_JOB_ERROR_SEVERE, /* severe errors, whether to abort operation depends on error handlers */ FM_JOB_ERROR_CRITICAL /* critical errors, the operation is aborted */ }; typedef enum _FmJobErrorAction FmJobErrorAction; enum _FmJobErrorAction { FM_JOB_CONTINUE, /* ignore the error and continue remaining work */ FM_JOB_RETRY, /* retry the previously failed operation. (not every kind of job support this) */ FM_JOB_ABORT /* abort the whole job */ }; struct _FmJob { GObject parent; gboolean cancel : 1; gboolean running : 1; /* optional, should be created if the job uses gio */ GCancellable* cancellable; /* optional, used when blocking the job to call a callback in * main thread is needed. */ GMutex* mutex; GCond* cond; }; struct _FmJobClass { GObjectClass parent_class; void (*finished)(FmJob* job); FmJobErrorAction (*error)(FmJob* job, GError* err, FmJobErrorSeverity severity); void (*cancelled)(FmJob* job); gint (*ask)(FmJob* job, const char* question, gint options); gboolean (*run_async)(FmJob* job); gboolean (*run)(FmJob* job); void (*cancel)(FmJob* job); }; /* Base type of all file I/O jobs. * not directly called by applications. */ /* FmJob* fm_job_new (void); */ GType fm_job_get_type (void); /* return TRUE if the job is already cancelled */ gboolean fm_job_is_cancelled(FmJob* job); /* return TRUE if the job is still running */ gboolean fm_job_is_running(FmJob* job); /* FIXME: requiring g_object_unref() is actually a better idea * due to API consistency. Need to re-think this part. */ /* Run a job asynchronously in another working thread, and * emit 'finished' signal in the main thread after its termination. * There is no need to call g_object_unref on a job running in * async fashion. The job object will be unrefed in idle handler * automatically shortly after its termination. * The default implementation of FmJob::run_async() create a working * thread in thread pool, and calls FmJob::run() in it. */ gboolean fm_job_run_async(FmJob* job); /* Run a job in current thread in a blocking fashion. * A job running synchronously with this function should be unrefed * later with g_object_unref when no longer needed. */ gboolean fm_job_run_sync(FmJob* job); /* Run a job in current thread in a blocking fashion and an additional * mainloop being created to prevent blocking of user interface. * A job running synchronously with this function should be unrefed * later with g_object_unref when no longer needed. */ gboolean fm_job_run_sync_with_mainloop(FmJob* job); /* Cancel the running job. can be called from any thread. */ void fm_job_cancel(FmJob* job); /* Following APIs are private to FmJob and should only be used in the * implementation of classes derived from FmJob. * Besides, they should be called from working thread only */ gpointer fm_job_call_main_thread(FmJob* job, FmJobCallMainThreadFunc func, gpointer user_data); /* Used by derived classes to implement FmJob::run() using gio inside. * This API tried to initialize a GCancellable object for use with gio and * should only be called once in the constructor of derived classes which * require the use of GCancellable. */ void fm_job_init_cancellable(FmJob* job); /* Used to implement FmJob::run() using gio inside. * This API tried to initialize a GCancellable object for use with gio. * Prior to calling this API, fm_job_init_cancellable() should be * called first to initiate GCancellable object. Otherwise NULL is returned. */ GCancellable* fm_job_get_cancellable(FmJob* job); /* Let the job use an existing cancellable object. * This can be used when you wish to share a cancellable object * among different jobs. * This should only be called before the job is launched. */ void fm_job_set_cancellable(FmJob* job, GCancellable* cancellable); /* only call this at the end of working thread if you're going to * override FmJob::run() and use your own multi-threading mechnism. */ void fm_job_finish(FmJob* job); void fm_job_emit_finished(FmJob* job); void fm_job_emit_cancelled(FmJob* job); /* Emit an 'error' signal to notify the main thread when an error occurs. * The return value of this function is the return value returned by * the connected signal handlers. * If severity is FM_JOB_ERROR_CRITICAL, the returned value is ignored and * fm_job_cancel() is called to abort the job. Otherwise, the signal * handler of this error can return FM_JOB_RETRY to ask for retrying the * failed operation, return FM_JOB_CONTINUE to ignore the error and * continue the remaining job, or return FM_JOB_ABORT to abort the job. * If FM_JOB_ABORT is returned by the signal handler, fm_job_cancel * will be called in fm_job_emit_error(). */ FmJobErrorAction fm_job_emit_error(FmJob* job, GError* err, FmJobErrorSeverity severity); gint fm_job_ask(FmJob* job, const char* question, ...); gint fm_job_askv(FmJob* job, const char* question, const char** options); gint fm_job_ask_valist(FmJob* job, const char* question, va_list options); G_END_DECLS #endif /* __FM-JOB_H__ */