mirror of
https://github.com/ashaduri/gsmartcontrol.git
synced 2026-09-25 13:25:37 +00:00
Increased main window size a bit to avoid the iconview shift down each time an
icon is selected. Added some scsi-output properties to full parser to avoid console warnings. Devices having only basic info can be displayed now in the info window.
This commit is contained in:
@@ -28,6 +28,12 @@ Bugs / patches:
|
||||
|
||||
TODO:
|
||||
|
||||
Don't rely on smartctl return code (2), parse the output instead.
|
||||
This will allow us to show the Info page.
|
||||
|
||||
Update to latest drivedb.
|
||||
|
||||
|
||||
Test Areca windows detection by installing CLI, then replacing it with a dummy
|
||||
program that prints something (with enclosures and without).
|
||||
|
||||
@@ -38,6 +44,10 @@ Fix not being able to quit while executing commands.
|
||||
https://developer.gnome.org/glib/2.34/glib-The-Main-Event-Loop.html#g-main-loop-quit
|
||||
|
||||
|
||||
In main window add multi-selection support and right-click menu with various
|
||||
tests, so that it's possible to run multiple tests in parallel from there.
|
||||
|
||||
|
||||
Areca detection
|
||||
Linux:
|
||||
Somehow differentiate between the cards with expanders (-d areca,N/E) and without (-d areca,N).
|
||||
|
||||
@@ -111,7 +111,7 @@ std::string execute_smartctl(const std::string& device, const std::string& devic
|
||||
+ " " + Glib::shell_quote(device));
|
||||
|
||||
if (!smartctl_ex->execute() || !smartctl_ex->get_error_msg().empty()) {
|
||||
debug_out_warn("app", DBG_FUNC_MSG << "Error while executing smartctl binary.\n");
|
||||
debug_out_warn("app", DBG_FUNC_MSG << "Smartctl binary did not execute cleanly.\n");
|
||||
|
||||
smartctl_output = hz::string_trim_copy(hz::string_any_to_unix_copy(smartctl_ex->get_stdout_str()));
|
||||
|
||||
|
||||
@@ -139,8 +139,12 @@ class SmartctlExecutorGeneric : public ExecutorSync {
|
||||
if (error_type == "exit") {
|
||||
int exit_code = 0;
|
||||
e->get_code(exit_code);
|
||||
// ignore everyone except these
|
||||
if ( !((exit_code & exit_cant_parse) || (exit_code & exit_open_failed)) )
|
||||
// Ignore everyone except this.
|
||||
// Note that we don't treat exit_open_failed as failure because:
|
||||
// * It may be returned from a DVD that returns product info but has no disk inside;
|
||||
// * It may be returned from a usb flash drive with -d scsi;
|
||||
// * exit_cant_parse is returned when opening unsupported usb drives without -d scsi.
|
||||
if ( !(exit_code & exit_cant_parse) )
|
||||
return;
|
||||
|
||||
// ignore giochannel errors - higher level errors will be triggered, and they more user-friendly.
|
||||
|
||||
@@ -412,11 +412,26 @@ bool SmartctlParser::parse_section_info_property(StorageProperty& p)
|
||||
p.value_type = StorageProperty::value_type_string;
|
||||
p.value_string = p.reported_value;
|
||||
|
||||
} else if (app_pcre_match("/^Device Model$/mi", p.reported_name)) {
|
||||
} else if (app_pcre_match("/^(?:Device Model|Device|Product)$/mi", p.reported_name)) { // "Device" and "Product" are from scsi/usb
|
||||
p.set_name(p.reported_name, "device_model", "Device Model");
|
||||
p.value_type = StorageProperty::value_type_string;
|
||||
p.value_string = p.reported_value;
|
||||
|
||||
} else if (app_pcre_match("/^Vendor$/mi", p.reported_name)) { // From scsi/usb
|
||||
p.set_name(p.reported_name, "vendor", "Vendor");
|
||||
p.value_type = StorageProperty::value_type_string;
|
||||
p.value_string = p.reported_value;
|
||||
|
||||
} else if (app_pcre_match("/^Revision$/mi", p.reported_name)) { // From scsi/usb
|
||||
p.set_name(p.reported_name, "revision", "Revision");
|
||||
p.value_type = StorageProperty::value_type_string;
|
||||
p.value_string = p.reported_value;
|
||||
|
||||
} else if (app_pcre_match("/^Device type$/mi", p.reported_name)) { // From scsi/usb
|
||||
p.set_name(p.reported_name, "device_type", "Device Type");
|
||||
p.value_type = StorageProperty::value_type_string;
|
||||
p.value_string = p.reported_value;
|
||||
|
||||
} else if (app_pcre_match("/^Serial Number$/mi", p.reported_name)) {
|
||||
p.set_name(p.reported_name, "serial_number", "Serial Number");
|
||||
p.value_type = StorageProperty::value_type_string;
|
||||
@@ -452,6 +467,11 @@ bool SmartctlParser::parse_section_info_property(StorageProperty& p)
|
||||
p.value_type = StorageProperty::value_type_string; // prints a single value (if it's not 512)
|
||||
p.value_string = p.reported_value;
|
||||
|
||||
} else if (app_pcre_match("/^Logical block size$/mi", p.reported_name)) { // from scsi/usb
|
||||
p.set_name(p.reported_name, "logical_block_size", "Logical Block Size");
|
||||
p.value_type = StorageProperty::value_type_string; // "512 bytes"
|
||||
p.value_string = p.reported_value;
|
||||
|
||||
} else if (app_pcre_match("/^Rotation Rate$/mi", p.reported_name)) {
|
||||
p.set_name(p.reported_name, "rotation_rate", "Rotation Rate");
|
||||
p.value_type = StorageProperty::value_type_string;
|
||||
@@ -514,6 +534,9 @@ bool SmartctlParser::parse_section_info_property(StorageProperty& p)
|
||||
p.value_bool = true; // let's be optimistic - just hope that it doesn't hurt.
|
||||
}
|
||||
|
||||
} else if (app_pcre_match("/^scsiMode/mi", p.reported_name)) { // these are some debug warnings from smartctl on usb flash drives
|
||||
p.show_in_ui = false;
|
||||
|
||||
} else {
|
||||
debug_out_warn("app", DBG_FUNC_MSG << "Unknown property \"" << p.reported_name << "\"\n");
|
||||
// this is not an error, just unknown attribute. treat it as string.
|
||||
|
||||
@@ -116,7 +116,7 @@ std::string get_scan_open_multiport_devices(std::vector<StorageDeviceRefPtr>& dr
|
||||
smartctl_def_options + "--scan-open");
|
||||
|
||||
if (!smartctl_ex->execute() || !smartctl_ex->get_error_msg().empty()) {
|
||||
debug_out_warn("app", DBG_FUNC_MSG << "Error while executing smartctl binary.\n");
|
||||
debug_out_warn("app", DBG_FUNC_MSG << "Smartctl binary did not execute cleanly.\n");
|
||||
return smartctl_ex->get_error_msg();
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ StorageDevice::StorageDevice(const string& dev_or_vfile, bool is_virtual)
|
||||
// force_type_ = false;
|
||||
is_virtual_ = is_virtual;
|
||||
is_manually_added_ = false;
|
||||
fully_parsed_ = false;
|
||||
parse_status_ = parse_status_none;
|
||||
test_is_active_ = false;
|
||||
|
||||
if (is_virtual) {
|
||||
@@ -82,7 +82,7 @@ StorageDevice::StorageDevice(const string& dev, const string& type_arg)
|
||||
// force_type_ = false;
|
||||
is_virtual_ = false;
|
||||
is_manually_added_ = false;
|
||||
fully_parsed_ = false;
|
||||
parse_status_ = parse_status_none;
|
||||
test_is_active_ = false;
|
||||
|
||||
device_ = dev;
|
||||
@@ -112,7 +112,7 @@ StorageDevice& StorageDevice::operator=(const StorageDevice& other)
|
||||
virtual_file_ = other.virtual_file_;
|
||||
is_manually_added_ = other.is_manually_added_;
|
||||
|
||||
fully_parsed_ = other.fully_parsed_;
|
||||
parse_status_ = other.parse_status_;
|
||||
test_is_active_ = other.test_is_active_;
|
||||
|
||||
detected_type_ = other.detected_type_;
|
||||
@@ -137,7 +137,7 @@ void StorageDevice::clear_fetched(bool including_outputs) {
|
||||
full_output_.clear();
|
||||
}
|
||||
|
||||
fully_parsed_ = false;
|
||||
parse_status_ = parse_status_none;
|
||||
test_is_active_ = false; // not sure
|
||||
|
||||
smart_supported_.reset();
|
||||
@@ -288,6 +288,8 @@ std::string StorageDevice::parse_basic_data(bool do_set_properties, bool emit_si
|
||||
}
|
||||
}
|
||||
|
||||
set_parse_status(parse_status_info);
|
||||
|
||||
if (emit_signal)
|
||||
signal_changed.emit(this); // notify listeners
|
||||
|
||||
@@ -350,13 +352,15 @@ std::string StorageDevice::parse_data()
|
||||
// but this one sets the StorageDevice class members, not properties.
|
||||
this->parse_basic_data(false, false); // don't emit signal, we're not complete yet.
|
||||
|
||||
// Call this after parse_basic_data(), since it sets parse status to "info".
|
||||
this->set_parse_status(StorageDevice::parse_status_full);
|
||||
|
||||
// set the full properties
|
||||
this->set_fully_parsed(true);
|
||||
this->set_properties(ps.get_properties()); // copy to our drive, overwriting old data
|
||||
|
||||
signal_changed.emit(this); // notify listeners
|
||||
|
||||
return "";
|
||||
return std::string();
|
||||
}
|
||||
|
||||
// Don't show any GUI warnings on parse failure - it may just be an unsupported
|
||||
@@ -364,22 +368,20 @@ std::string StorageDevice::parse_data()
|
||||
// parsed again in Info window, and we show the warnings there.
|
||||
debug_out_warn("app", DBG_FUNC_MSG << "Cannot parse smartctl output.\n");
|
||||
|
||||
this->set_fully_parsed(false);
|
||||
|
||||
// proper parsing failed. try to at least extract info section
|
||||
this->info_output_ = this->full_output_; // complete output here. sometimes it's only the info section
|
||||
if (!this->parse_basic_data(true).empty()) { // will add some properties too. this will emit signal_changed.
|
||||
return ps.get_error_msg(); // return full parser's error messages - they are more detailed.
|
||||
}
|
||||
|
||||
return ""; // return ok if at least the info was ok.
|
||||
return std::string(); // return ok if at least the info was ok.
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool StorageDevice::get_fully_parsed() const
|
||||
StorageDevice::parse_status_t StorageDevice::get_parse_status() const
|
||||
{
|
||||
return fully_parsed_;
|
||||
return parse_status_;
|
||||
}
|
||||
|
||||
|
||||
@@ -825,7 +827,7 @@ std::string StorageDevice::execute_device_smartctl(const std::string& command_op
|
||||
command_options, smartctl_ex, smartctl_output);
|
||||
|
||||
if (!error_msg.empty()) {
|
||||
debug_out_warn("app", DBG_FUNC_MSG << "Error while executing smartctl binary.\n");
|
||||
debug_out_warn("app", DBG_FUNC_MSG << "Smartctl binary did not execute cleanly.\n");
|
||||
|
||||
// Smartctl 5.39 cvs/svn version defaults to usb type on at least linux and windows.
|
||||
// This means that the old SCSI identify command isn't executed by default,
|
||||
@@ -844,9 +846,9 @@ std::string StorageDevice::execute_device_smartctl(const std::string& command_op
|
||||
|
||||
|
||||
|
||||
void StorageDevice::set_fully_parsed(bool b)
|
||||
void StorageDevice::set_parse_status(parse_status_t value)
|
||||
{
|
||||
fully_parsed_ = b;
|
||||
parse_status_ = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -67,6 +67,14 @@ class StorageDevice : public hz::intrusive_ptr_referenced {
|
||||
static bool order_less_than(const StorageDeviceRefPtr& a, const StorageDeviceRefPtr& b);
|
||||
|
||||
|
||||
/// Statuses of various parse states
|
||||
enum parse_status_t {
|
||||
parse_status_full, ///< Fully parsed
|
||||
parse_status_info, ///< Only info section available
|
||||
parse_status_none, ///< No data
|
||||
};
|
||||
|
||||
|
||||
/// Constructor
|
||||
StorageDevice(const std::string& dev_or_vfile, bool is_virtual = false);
|
||||
|
||||
@@ -100,7 +108,7 @@ class StorageDevice : public hz::intrusive_ptr_referenced {
|
||||
std::string parse_data();
|
||||
|
||||
/// Get the "fully parsed" flag
|
||||
bool get_fully_parsed() const;
|
||||
parse_status_t get_parse_status() const;
|
||||
|
||||
|
||||
/// Try to enable SMART.
|
||||
@@ -239,7 +247,7 @@ class StorageDevice : public hz::intrusive_ptr_referenced {
|
||||
protected:
|
||||
|
||||
/// Set the "fully parsed" flag
|
||||
void set_fully_parsed(bool b);
|
||||
void set_parse_status(parse_status_t value);
|
||||
|
||||
/// Set parsed properties
|
||||
void set_properties(const SmartctlParser::prop_list_t& props);
|
||||
@@ -258,7 +266,7 @@ class StorageDevice : public hz::intrusive_ptr_referenced {
|
||||
std::string virtual_file_; ///< A file (smartctl data) the virtual device was loaded from
|
||||
bool is_manually_added_; ///< StorageDevice doesn't use it, but it's useful for its users.
|
||||
|
||||
bool fully_parsed_; ///< "Fully parsed" flag
|
||||
parse_status_t parse_status_; ///< "Fully parsed" flag
|
||||
|
||||
/// Sort of a "lock". If true, the device is not allowed to perform any commands
|
||||
/// except "-l selftest" and maybe "--capabilities" and "--info" (not sure).
|
||||
|
||||
@@ -354,7 +354,7 @@ class StorageProperty {
|
||||
/// Constructor
|
||||
StorageProperty()
|
||||
: section(section_unknown), subsection(subsection_unknown),
|
||||
value_type(value_type_unknown), warning(warning_none)
|
||||
value_type(value_type_unknown), warning(warning_none), show_in_ui(true)
|
||||
{
|
||||
// value_from_db = false;
|
||||
value_integer = 0; // this should nullify all union members
|
||||
@@ -435,6 +435,8 @@ class StorageProperty {
|
||||
warning_t warning; ///< Warning severity for this property
|
||||
std::string warning_reason; // Warning reason (displayable)
|
||||
|
||||
bool show_in_ui; ///< Whether to show this property in UI or not
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -408,6 +408,10 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
int row = 1; // row 0 is always empty. this way it's much easier.
|
||||
|
||||
for (prop_iterator iter = id_props.begin(); iter != id_props.end(); ++iter) {
|
||||
if (!iter->show_in_ui) {
|
||||
continue; // hide debug messages from smartctl
|
||||
}
|
||||
|
||||
if (iter->generic_name == "overall_health") // a little distance for this one
|
||||
++row;
|
||||
|
||||
@@ -1302,7 +1306,12 @@ void GscInfoWindow::on_view_output_button_clicked()
|
||||
GscTextWindow<SmartctlOutputInstance>* win = GscTextWindow<SmartctlOutputInstance>::create();
|
||||
// make save visible and enable monospace font
|
||||
|
||||
win->set_text("Smartctl Output", this->drive->get_full_output(), true, true);
|
||||
std::string output = this->drive->get_full_output();
|
||||
if (output.empty()) {
|
||||
output = this->drive->get_info_output();
|
||||
}
|
||||
|
||||
win->set_text("Smartctl Output", output, true, true);
|
||||
|
||||
std::string filename = drive->get_save_filename();
|
||||
if (!filename.empty())
|
||||
|
||||
@@ -1189,8 +1189,8 @@ GscInfoWindow* GscMainWindow::show_device_info_window(StorageDeviceRefPtr drive)
|
||||
|
||||
|
||||
// Virtual drives are parsed at load time.
|
||||
// Parse non-virtual drives here.
|
||||
if (!drive->get_is_virtual()) {
|
||||
// Parse non-virtual, smart-supporting drives here.
|
||||
if (!drive->get_is_virtual() && drive->get_smart_status() != StorageDevice::status_unsupported) {
|
||||
SmartctlExecutorGuiRefPtr ex(new SmartctlExecutorGui());
|
||||
ex->create_running_dialog(this, "Running %s on " + drive->get_device_with_type() + "...");
|
||||
std::string error_msg = drive->fetch_data_and_parse(ex); // run it with GUI support
|
||||
@@ -1205,7 +1205,7 @@ GscInfoWindow* GscMainWindow::show_device_info_window(StorageDeviceRefPtr drive)
|
||||
// If the drive output wasn't fully parsed (happens with e.g. scsi and
|
||||
// usb devices), only very basic info is available and there's no point
|
||||
// in showing this window. - for both virtual and non-virtual.
|
||||
if (!drive->get_fully_parsed()) {
|
||||
if (drive->get_parse_status() == StorageDevice::parse_status_none) {
|
||||
gsc_no_info_dialog_show("No additional information is available for this drive.",
|
||||
"", this, false, drive->get_info_output(), "Smartctl Output", drive->get_save_filename());
|
||||
return 0;
|
||||
|
||||
@@ -20,128 +20,243 @@ Glib-based policy.
|
||||
*/
|
||||
|
||||
|
||||
/// Lock GStaticMutex
|
||||
#define hz_glib_static_mutex_lock(mutex) \
|
||||
g_mutex_lock(g_static_mutex_get_mutex(mutex))
|
||||
|
||||
/// Try locking GStaticMutex
|
||||
#define hz_glib_static_mutex_trylock(mutex) \
|
||||
g_mutex_trylock(g_static_mutex_get_mutex(mutex))
|
||||
|
||||
/// Unlock GStaticMutex
|
||||
#define hz_glib_static_mutex_unlock(mutex) \
|
||||
g_mutex_unlock(g_static_mutex_get_mutex(mutex))
|
||||
|
||||
|
||||
|
||||
|
||||
namespace hz {
|
||||
|
||||
|
||||
/// C++ Wrapper for Glib mutex
|
||||
class MutexGlib : public hz::noncopyable {
|
||||
public:
|
||||
typedef GStaticMutex native_type;
|
||||
|
||||
static void native_lock(native_type& mutex)
|
||||
{
|
||||
hz_glib_static_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
static bool native_trylock(native_type& mutex)
|
||||
{
|
||||
return hz_glib_static_mutex_trylock(&mutex);
|
||||
}
|
||||
|
||||
static void native_unlock(native_type& mutex)
|
||||
{
|
||||
hz_glib_static_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
MutexGlib() { g_static_mutex_init(&mutex_); }
|
||||
~MutexGlib() { g_static_mutex_free(&mutex_); }
|
||||
|
||||
void lock() { native_lock(mutex_); }
|
||||
bool trylock() { return native_trylock(mutex_); }
|
||||
void unlock() { native_unlock(mutex_); }
|
||||
|
||||
private:
|
||||
GStaticMutex mutex_; // use StaticMutex, I think it uses less heap memory
|
||||
};
|
||||
#if GLIB_CHECK_VERSION(2, 32, 0)
|
||||
|
||||
|
||||
/// C++ Wrapper for Glib mutex
|
||||
class MutexGlib : public hz::noncopyable {
|
||||
public:
|
||||
typedef GMutex native_type;
|
||||
|
||||
/// C++ Wrapper for Glib recursive mutex
|
||||
class RecMutexGlib : public hz::noncopyable {
|
||||
public:
|
||||
typedef GStaticRecMutex native_type;
|
||||
|
||||
static void native_lock(native_type& mutex)
|
||||
{
|
||||
g_static_rec_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
static bool native_trylock(native_type& mutex)
|
||||
{
|
||||
return g_static_rec_mutex_trylock(&mutex);
|
||||
}
|
||||
|
||||
static void native_unlock(native_type& mutex)
|
||||
{
|
||||
g_static_rec_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
RecMutexGlib() { g_static_rec_mutex_init(&mutex_); }
|
||||
~RecMutexGlib() { g_static_rec_mutex_free(&mutex_); }
|
||||
|
||||
void lock() { native_lock(mutex_); }
|
||||
bool trylock() { return native_trylock(mutex_); }
|
||||
void unlock() { native_unlock(mutex_); }
|
||||
|
||||
private:
|
||||
GStaticRecMutex mutex_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// C++ Wrapper for Glib RW lock
|
||||
class RWMutexGlib : public hz::noncopyable {
|
||||
public:
|
||||
typedef GStaticRWLock native_type;
|
||||
|
||||
static void native_lock(native_type& mutex, bool for_write = false)
|
||||
{
|
||||
if (for_write) {
|
||||
g_static_rw_lock_writer_lock(&mutex);
|
||||
} else {
|
||||
g_static_rw_lock_reader_lock(&mutex);
|
||||
static void native_lock(native_type& mutex)
|
||||
{
|
||||
g_mutex_lock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static bool native_trylock(native_type& mutex, bool for_write = false)
|
||||
{
|
||||
return (for_write ? g_static_rw_lock_writer_trylock(&mutex) : g_static_rw_lock_reader_trylock(&mutex));
|
||||
}
|
||||
|
||||
static void native_unlock(native_type& mutex, bool for_write = false)
|
||||
{
|
||||
if (for_write) {
|
||||
g_static_rw_lock_writer_unlock(&mutex);
|
||||
} else {
|
||||
g_static_rw_lock_reader_unlock(&mutex);
|
||||
static bool native_trylock(native_type& mutex)
|
||||
{
|
||||
return g_mutex_trylock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
RWMutexGlib() { g_static_rw_lock_init(&mutex_); }
|
||||
~RWMutexGlib() { g_static_rw_lock_free(&mutex_); }
|
||||
static void native_unlock(native_type& mutex)
|
||||
{
|
||||
g_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void lock(bool for_write = false) { native_lock(mutex_, for_write); }
|
||||
bool trylock(bool for_write = false) { return native_trylock(mutex_, for_write); }
|
||||
void unlock(bool for_write = false) { native_unlock(mutex_, for_write); }
|
||||
MutexGlib() { g_mutex_init(&mutex_); }
|
||||
~MutexGlib() { g_mutex_clear(&mutex_); }
|
||||
|
||||
private:
|
||||
GStaticRWLock mutex_;
|
||||
};
|
||||
void lock() { native_lock(mutex_); }
|
||||
bool trylock() { return native_trylock(mutex_); }
|
||||
void unlock() { native_unlock(mutex_); }
|
||||
|
||||
private:
|
||||
GMutex mutex_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// C++ Wrapper for Glib recursive mutex
|
||||
class RecMutexGlib : public hz::noncopyable {
|
||||
public:
|
||||
typedef GRecMutex native_type;
|
||||
|
||||
static void native_lock(native_type& mutex)
|
||||
{
|
||||
g_rec_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
static bool native_trylock(native_type& mutex)
|
||||
{
|
||||
return g_rec_mutex_trylock(&mutex);
|
||||
}
|
||||
|
||||
static void native_unlock(native_type& mutex)
|
||||
{
|
||||
g_rec_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
RecMutexGlib() { g_rec_mutex_init(&mutex_); }
|
||||
~RecMutexGlib() { g_rec_mutex_clear(&mutex_); }
|
||||
|
||||
void lock() { native_lock(mutex_); }
|
||||
bool trylock() { return native_trylock(mutex_); }
|
||||
void unlock() { native_unlock(mutex_); }
|
||||
|
||||
private:
|
||||
GRecMutex mutex_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// C++ Wrapper for Glib RW lock
|
||||
class RWMutexGlib : public hz::noncopyable {
|
||||
public:
|
||||
typedef GRWLock native_type;
|
||||
|
||||
static void native_lock(native_type& mutex, bool for_write = false)
|
||||
{
|
||||
if (for_write) {
|
||||
g_rw_lock_writer_lock(&mutex);
|
||||
} else {
|
||||
g_rw_lock_reader_lock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static bool native_trylock(native_type& mutex, bool for_write = false)
|
||||
{
|
||||
return (for_write ? g_rw_lock_writer_trylock(&mutex) : g_rw_lock_reader_trylock(&mutex));
|
||||
}
|
||||
|
||||
static void native_unlock(native_type& mutex, bool for_write = false)
|
||||
{
|
||||
if (for_write) {
|
||||
g_rw_lock_writer_unlock(&mutex);
|
||||
} else {
|
||||
g_rw_lock_reader_unlock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
RWMutexGlib() { g_rw_lock_init(&mutex_); }
|
||||
~RWMutexGlib() { g_rw_lock_clear(&mutex_); }
|
||||
|
||||
void lock(bool for_write = false) { native_lock(mutex_, for_write); }
|
||||
bool trylock(bool for_write = false) { return native_trylock(mutex_, for_write); }
|
||||
void unlock(bool for_write = false) { native_unlock(mutex_, for_write); }
|
||||
|
||||
private:
|
||||
GRWLock mutex_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#else // older glib
|
||||
|
||||
|
||||
/// Lock GStaticMutex
|
||||
#define hz_glib_static_mutex_lock(mutex) \
|
||||
g_mutex_lock(g_static_mutex_get_mutex(mutex))
|
||||
|
||||
/// Try locking GStaticMutex
|
||||
#define hz_glib_static_mutex_trylock(mutex) \
|
||||
g_mutex_trylock(g_static_mutex_get_mutex(mutex))
|
||||
|
||||
/// Unlock GStaticMutex
|
||||
#define hz_glib_static_mutex_unlock(mutex) \
|
||||
g_mutex_unlock(g_static_mutex_get_mutex(mutex))
|
||||
|
||||
|
||||
|
||||
/// C++ Wrapper for Glib mutex
|
||||
class MutexGlib : public hz::noncopyable {
|
||||
public:
|
||||
typedef GStaticMutex native_type;
|
||||
|
||||
static void native_lock(native_type& mutex)
|
||||
{
|
||||
hz_glib_static_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
static bool native_trylock(native_type& mutex)
|
||||
{
|
||||
return hz_glib_static_mutex_trylock(&mutex);
|
||||
}
|
||||
|
||||
static void native_unlock(native_type& mutex)
|
||||
{
|
||||
hz_glib_static_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
MutexGlib() { g_static_mutex_init(&mutex_); }
|
||||
~MutexGlib() { g_static_mutex_free(&mutex_); }
|
||||
|
||||
void lock() { native_lock(mutex_); }
|
||||
bool trylock() { return native_trylock(mutex_); }
|
||||
void unlock() { native_unlock(mutex_); }
|
||||
|
||||
private:
|
||||
GStaticMutex mutex_; // use StaticMutex, I think it uses less heap memory
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// C++ Wrapper for Glib recursive mutex
|
||||
class RecMutexGlib : public hz::noncopyable {
|
||||
public:
|
||||
typedef GStaticRecMutex native_type;
|
||||
|
||||
static void native_lock(native_type& mutex)
|
||||
{
|
||||
g_static_rec_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
static bool native_trylock(native_type& mutex)
|
||||
{
|
||||
return g_static_rec_mutex_trylock(&mutex);
|
||||
}
|
||||
|
||||
static void native_unlock(native_type& mutex)
|
||||
{
|
||||
g_static_rec_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
RecMutexGlib() { g_static_rec_mutex_init(&mutex_); }
|
||||
~RecMutexGlib() { g_static_rec_mutex_free(&mutex_); }
|
||||
|
||||
void lock() { native_lock(mutex_); }
|
||||
bool trylock() { return native_trylock(mutex_); }
|
||||
void unlock() { native_unlock(mutex_); }
|
||||
|
||||
private:
|
||||
GStaticRecMutex mutex_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// C++ Wrapper for Glib RW lock
|
||||
class RWMutexGlib : public hz::noncopyable {
|
||||
public:
|
||||
typedef GStaticRWLock native_type;
|
||||
|
||||
static void native_lock(native_type& mutex, bool for_write = false)
|
||||
{
|
||||
if (for_write) {
|
||||
g_static_rw_lock_writer_lock(&mutex);
|
||||
} else {
|
||||
g_static_rw_lock_reader_lock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static bool native_trylock(native_type& mutex, bool for_write = false)
|
||||
{
|
||||
return (for_write ? g_static_rw_lock_writer_trylock(&mutex) : g_static_rw_lock_reader_trylock(&mutex));
|
||||
}
|
||||
|
||||
static void native_unlock(native_type& mutex, bool for_write = false)
|
||||
{
|
||||
if (for_write) {
|
||||
g_static_rw_lock_writer_unlock(&mutex);
|
||||
} else {
|
||||
g_static_rw_lock_reader_unlock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
RWMutexGlib() { g_static_rw_lock_init(&mutex_); }
|
||||
~RWMutexGlib() { g_static_rw_lock_free(&mutex_); }
|
||||
|
||||
void lock(bool for_write = false) { native_lock(mutex_, for_write); }
|
||||
bool trylock(bool for_write = false) { return native_trylock(mutex_, for_write); }
|
||||
void unlock(bool for_write = false) { native_unlock(mutex_, for_write); }
|
||||
|
||||
private:
|
||||
GStaticRWLock mutex_;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -198,7 +313,12 @@ struct SyncPolicyGlib : public SyncScopedLockProvider<SyncPolicyGlib> {
|
||||
// Static methods
|
||||
|
||||
/// If glib threads are unavailable, this will abort.
|
||||
|
||||
#if GLIB_CHECK_VERSION(2, 32, 0)
|
||||
static bool init() { return true; } // g_thread_init() does nothing and is deprecated since 2.32.
|
||||
#else
|
||||
static bool init() { if (!g_thread_supported()) g_thread_init(NULL); return true; }
|
||||
#endif
|
||||
|
||||
static void lock(Mutex& m) { m.lock(); }
|
||||
static bool trylock(Mutex& m) { return m.trylock(); }
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<requires-version lib="gtk+" version="2.8"/>
|
||||
<widget class="GtkWindow" id="gsc_main_window">
|
||||
<property name="title" translatable="yes">GSmartControl</property>
|
||||
<property name="default_width">460</property>
|
||||
<property name="default_height">350</property>
|
||||
<property name="default_width">580</property>
|
||||
<property name="default_height">400</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
|
||||
Reference in New Issue
Block a user