Merge "Merge remote branch 'gerrit/master' into refactor" into refactor
This commit is contained in:
commit
673160b9fd
340
bin/qtmodule-configtests
Executable file
340
bin/qtmodule-configtests
Executable file
@ -0,0 +1,340 @@
|
||||
#!/usr/bin/perl
|
||||
######################################################################
|
||||
#
|
||||
# Runs any module configuration tests
|
||||
#
|
||||
# Called (currently) from syncqt, and expects a few arguments
|
||||
#
|
||||
# configtests $basedir $out_basedir $qtbasedir $quietmode
|
||||
#
|
||||
# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
# Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
#
|
||||
######################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# use packages -------------------------------------------------------
|
||||
use File::Basename;
|
||||
use File::Path 'mkpath';
|
||||
use File::Spec::Functions;
|
||||
use Cwd;
|
||||
use Cwd 'abs_path';
|
||||
use Config;
|
||||
|
||||
# Which file to look for the %configtests variable in
|
||||
my $configTestSource = "sync.profile";
|
||||
|
||||
if ($#ARGV < 3) {
|
||||
warn "Usage:\n";
|
||||
warn " $0 <module base directory> <module output directory> <QtBase directory> <generator spec>\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# These might be needed in sync.profile
|
||||
our $basedir = $ARGV[0];
|
||||
our $out_basedir = $ARGV[1];
|
||||
our $qtbasedir = $ARGV[2];
|
||||
my $generator = $ARGV[3];
|
||||
|
||||
our %configtests;
|
||||
|
||||
my $qmakeCachePath = catfile($out_basedir, ".qmake.cache");
|
||||
|
||||
my $QMAKE = catfile($qtbasedir, "bin", ($^O =~ /win32/i) ? 'qmake.exe' : 'qmake');
|
||||
if (!-x $QMAKE) {
|
||||
# try the qmake from the path (e.g. this is a shadow build)
|
||||
$QMAKE = 'qmake';
|
||||
}
|
||||
|
||||
# Need to use the right make
|
||||
# SYMBIAN_UNIX/MINGW should fall back to the non SYMBIAN ones
|
||||
my $MAKE = 'make'; # default, only works on unix
|
||||
if ($generator =~ /UNIX|XCODE/i) { # XCODE = make?
|
||||
$MAKE = 'make';
|
||||
} elsif ($generator =~ /MINGW/i) {
|
||||
$MAKE = 'mingw32-make';
|
||||
} elsif ($generator =~ /MSVC.NET|MSBUILD/i) {
|
||||
$MAKE = 'nmake';
|
||||
} else {
|
||||
# Unhandled (at least): BMAKE, GBUILD, SYMBIAN_ABLD, SYMBIAN_SBSV2
|
||||
warn "Unrecognized generator spec ($generator) - assuming '$MAKE'\n";
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Syntax: fileContents(filename)
|
||||
# Params: filename, string, filename of file to return contents
|
||||
#
|
||||
# Purpose: Get the contents of a file.
|
||||
# Returns: String with contents of the file, or empty string if file
|
||||
# doens't exist.
|
||||
# Warning: Dies if it does exist but script cannot get read access.
|
||||
######################################################################
|
||||
sub fileContents {
|
||||
my ($filename) = @_;
|
||||
my $filecontents = "";
|
||||
if (-e $filename) {
|
||||
open(I, "< $filename") || die "Could not open $filename for reading, read block?";
|
||||
local $/;
|
||||
binmode I;
|
||||
$filecontents = <I>;
|
||||
close I;
|
||||
}
|
||||
return $filecontents;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Syntax: loadConfigTests()
|
||||
#
|
||||
# Purpose: Loads the config tests from the source basedir into %configtests.
|
||||
# Returns: Nothing
|
||||
######################################################################
|
||||
sub loadConfigTests {
|
||||
my $configprofile = catfile($basedir, $configTestSource);
|
||||
my $result;
|
||||
unless ($result = do $configprofile) {
|
||||
die "configtests couldn't parse $configprofile: $@\n" if $@;
|
||||
# We don't check for non null output, since that is valid
|
||||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Syntax: hashesAreDifferent
|
||||
#
|
||||
# Purpose: Compares two hashes. (must have same key=value for everything)
|
||||
# Returns: 0 if they are the same, 1 otherwise
|
||||
######################################################################
|
||||
sub hashesAreDifferent {
|
||||
my %a = %{$_[0]};
|
||||
my %b = %{$_[1]};
|
||||
|
||||
if (keys %a != keys %b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
my %cmp = map { $_ => 1 } keys %a;
|
||||
for my $key (keys %b) {
|
||||
last unless exists $cmp{$key};
|
||||
last unless $a{$key} eq $b{$key};
|
||||
delete $cmp{$key};
|
||||
}
|
||||
if (%cmp) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Syntax: executeSomething
|
||||
# Params: A list of things.
|
||||
#
|
||||
# Purpose: Executes the first arg, passing the list.
|
||||
# stderr is redirected to stdout, and the output is captured.
|
||||
# Returns: The output.
|
||||
######################################################################
|
||||
sub executeSomething {
|
||||
my ($program, @args) = @_;
|
||||
|
||||
my $pid = open(KID_TO_READ, "-|");
|
||||
|
||||
my $output;
|
||||
|
||||
if ($pid) { # parent
|
||||
while (<KID_TO_READ>) {
|
||||
$output = $output . $_;
|
||||
}
|
||||
close(KID_TO_READ) || $! == 0 || warn "\nFailed to execute $program: exited $?";
|
||||
} else {
|
||||
# redirect STDERR to STDOUT
|
||||
open STDERR, ">&STDOUT";
|
||||
|
||||
# Exec something
|
||||
exec ($program, @args) || die "\nCan't exec $program: $!\n";
|
||||
# NOTREACHED
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Syntax: executeTest()
|
||||
# Params: testName
|
||||
#
|
||||
# The testName variable controls the actual config test run - the
|
||||
# source is assumed to be in $basedir/config.tests/$testName, and
|
||||
# when 'qmake; make clean; make' is run, is expected to produce a file
|
||||
# $out_basedir/config.tests/$testName/$testName. If this test passes,
|
||||
# then 'config_test_$testName = yes' will be written to $out_basedir/.qmake.cache
|
||||
#
|
||||
# Purpose: Runs a configuration time test.
|
||||
# Returns: 0 if the test fails, 1 if it passes, 2 if the test is skipped
|
||||
# (e.g. .pro file has requires(x) and x is not satisfied)
|
||||
######################################################################
|
||||
sub executeTest {
|
||||
my ($testName) = @_;
|
||||
|
||||
my $oldWorkingDir = getcwd();
|
||||
my $ret = 0;
|
||||
|
||||
my @QMAKEARGS = ('CONFIG-=debug_and_release');
|
||||
|
||||
my $testOutDir = catdir($out_basedir, 'config.tests', $testName);
|
||||
|
||||
# Since we might be cross compiling, look for barename (Linux) and .exe (Win32/Symbian)
|
||||
my $testOutFile1 = catfile($testOutDir, "$testName.exe");
|
||||
my $testOutFile2 = catfile($testOutDir, $testName);
|
||||
|
||||
if (abs_path($basedir) eq abs_path($out_basedir)) {
|
||||
chdir $testOutDir or die "\nUnable to change to config test directory ($testOutDir): $!\n";
|
||||
} else { # shadow build
|
||||
if (! -e $testOutDir) {
|
||||
mkpath $testOutDir or die "\nUnable to create shadow build config test directory ($testOutDir): $!\n";
|
||||
}
|
||||
chdir $testOutDir or die "\nUnable to change to config test directory ($testOutDir): $!\n";
|
||||
|
||||
push (@QMAKEARGS, catdir($basedir, 'config.tests', $testName));
|
||||
}
|
||||
|
||||
# First remove existing stuff (XXX this probably needs generator specific code, but hopefully
|
||||
# the target removal below will suffice)
|
||||
if (-e "Makefile") {
|
||||
executeSomething($MAKE, 'distclean');
|
||||
}
|
||||
|
||||
# and any targets that we might find that weren't distcleaned
|
||||
unlink $testOutFile1, $testOutFile2;
|
||||
|
||||
# Run qmake && make
|
||||
executeSomething($QMAKE, @QMAKEARGS);
|
||||
my $makeOutput = executeSomething(($MAKE));
|
||||
|
||||
# If make prints "blah blah blah\nSkipped." we consider this a skipped test
|
||||
if ($makeOutput !~ qr(^Skipped\.$)ms) {
|
||||
# Check the test exists (can't reliably execute, especially for cross compilation)
|
||||
if (-e $testOutFile1 or -e $testOutFile2) {
|
||||
$ret = 1;
|
||||
}
|
||||
} else {
|
||||
$ret = 2;
|
||||
}
|
||||
|
||||
chdir $oldWorkingDir or die "\nUnable to restore working directory: $!\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# Now run configuration tests
|
||||
# %configtests is a map from config test name to a map of parameters
|
||||
# e.g:
|
||||
#
|
||||
# %configtests = (
|
||||
# "simple" => {fatal => 1, message => "Missing required 'simple' component\n"},
|
||||
# "failed" => {message => "You need to install the FAILED sdk for this to work\n"}
|
||||
# );
|
||||
#
|
||||
# Parameters and their defaults:
|
||||
# - fatal [false] - whether failing this test should abort everything
|
||||
# - message [""] - A special message to display if this test fails
|
||||
#
|
||||
loadConfigTests();
|
||||
|
||||
# Only do this step for modules that have config tests
|
||||
# (qtbase doesn't). We try to preserve existing contents (and furthermore
|
||||
# only write to .qmake.cache if the tests change)
|
||||
if (abs_path($out_basedir) ne abs_path($qtbasedir)) {
|
||||
# Read any existing content
|
||||
my $existingContents = fileContents($qmakeCachePath);
|
||||
my %oldTestResults;
|
||||
my %newTestResults;
|
||||
my @fatalTestsEncountered;
|
||||
|
||||
# Parse the existing results so we can check if we change them
|
||||
while ($existingContents =~ /^config_test_(.*) = (yes|no)$/gm) {
|
||||
$oldTestResults{$1} = $2;
|
||||
}
|
||||
|
||||
# Get the longest length test name so we can pretty print
|
||||
use List::Util qw(max);
|
||||
my $maxNameLength = max map { length $_ } keys %configtests;
|
||||
|
||||
# Turn off buffering
|
||||
$| = 1;
|
||||
|
||||
# Now run the configuration tests
|
||||
print "Configuration tests:\n";
|
||||
|
||||
while ((my $testName, my $testParameters) = each %configtests) {
|
||||
printf " % *s: ", $maxNameLength, $testName; # right aligned, yes/no lines up
|
||||
|
||||
my $fatalTest = $testParameters->{"fatal"} // 0;
|
||||
my $message = $testParameters->{"message"};
|
||||
|
||||
my $testResult = executeTest($testName);
|
||||
my @testResultStrings = ("no\n","yes\n","skipped\n");
|
||||
|
||||
$newTestResults{$testName} = (($testResult == 1) ? "yes" : "no"); # skipped = no
|
||||
|
||||
if ($testResult == 0) {
|
||||
# Failed test
|
||||
if ($fatalTest) {
|
||||
print "no (fatal)\n";
|
||||
# Report the fatality at the end, too
|
||||
push (@fatalTestsEncountered, $testName);
|
||||
} else {
|
||||
print "no\n";
|
||||
}
|
||||
if (defined($message)) {
|
||||
print $message;
|
||||
print "\n" unless chop $message eq "\n";
|
||||
}
|
||||
} else {
|
||||
# yes or skipped
|
||||
print $testResultStrings[$testResult];
|
||||
}
|
||||
}
|
||||
|
||||
# Check if the test results are different
|
||||
if (hashesAreDifferent(\%oldTestResults, \%newTestResults)) {
|
||||
# Generate the new contents
|
||||
my $newContents = $existingContents;
|
||||
|
||||
# Strip out any existing config test results
|
||||
$newContents =~ s/^config_test_.*$//gms;
|
||||
$newContents =~ s/^# Compile time test results.*$//gms;
|
||||
|
||||
# Add any remaining content and make sure we start on a new line
|
||||
if ($newContents and chop $newContents ne '\n') {
|
||||
$newContents = $newContents . "\n";
|
||||
}
|
||||
|
||||
# Results and header
|
||||
if (%newTestResults) {
|
||||
$newContents = $newContents . '# Compile time test results ('.(localtime).")\n";
|
||||
|
||||
# Results
|
||||
while ((my $testName, my $testResult) = each %newTestResults) {
|
||||
$newContents = $newContents . "config_test_$testName = $testResult\n";
|
||||
}
|
||||
}
|
||||
|
||||
# and open the file
|
||||
open my $cacheFileHandle, ">$qmakeCachePath" or die "Unable to open $qmakeCachePath for writing: $!\n";
|
||||
|
||||
print $cacheFileHandle $newContents;
|
||||
|
||||
close $cacheFileHandle or die "Unable to close $qmakeCachePath: $!\n";
|
||||
}
|
||||
|
||||
# Now see if we have to die
|
||||
if (@fatalTestsEncountered) {
|
||||
if ($#fatalTestsEncountered == 0) {
|
||||
warn "Mandatory configuration test (".$fatalTestsEncountered[0].") failed.\n\n";
|
||||
} else {
|
||||
warn "Mandatory configuration tests (". join (", ", @fatalTestsEncountered) . ") failed.\n\n";
|
||||
}
|
||||
exit -1;
|
||||
}
|
||||
}
|
||||
|
||||
exit 0;
|
155
bin/syncqt
155
bin/syncqt
@ -15,6 +15,7 @@ use Cwd;
|
||||
use Cwd 'abs_path';
|
||||
use Config;
|
||||
use strict;
|
||||
use English qw(-no_match_vars );
|
||||
|
||||
# set output basedir to be where ever syncqt is run from
|
||||
our $out_basedir = getcwd();
|
||||
@ -38,7 +39,7 @@ our (%modules, %moduleheaders, %classnames, %mastercontent, %modulepris);
|
||||
my $isunix = 0;
|
||||
my $module = 0;
|
||||
my $showonly = 0;
|
||||
my $quiet = 0;
|
||||
my $verbose_level = 1;
|
||||
my $remove_stale = 1;
|
||||
my $force_win = 0;
|
||||
my $force_relative = 0;
|
||||
@ -50,6 +51,7 @@ my $module_fwd = "";
|
||||
my $cache_module_fwd = 0;
|
||||
my $developer_build = 0;
|
||||
my $no_module_version_header = 0;
|
||||
my $makefile_generator = "";
|
||||
my @modules_to_sync ;
|
||||
$force_relative = 1 if ( -d "/System/Library/Frameworks" );
|
||||
|
||||
@ -75,7 +77,9 @@ sub showUsage
|
||||
print " -showonly Show action but not perform (default: " . ($showonly ? "yes" : "no") . ")\n";
|
||||
print " -outdir <PATH> Specify output directory for sync (default: $out_basedir)\n";
|
||||
print " -qtdir <PATH> Set the path to QtBase (detected: " . (defined $qtbasedir ? $qtbasedir : "-none-") . ")\n";
|
||||
print " -quiet Only report problems, not activity (default: " . ($quiet ? "yes" : "no") . ")\n";
|
||||
print " -quiet Only report problems, not activity (same as -verbose 0)\n";
|
||||
print " -v, -verbose <level> Sets the verbosity level (max. 4) (default: $verbose_level)\n";
|
||||
print " The short form increases the level by +1\n";
|
||||
print " -separate-module <NAME>:<PROFILEDIR>:<HEADERDIR>\n";
|
||||
print " Create headers for <NAME> with original headers in\n";
|
||||
print " <HEADERDIR> relative to <PROFILEDIR> \n";
|
||||
@ -88,6 +92,7 @@ sub showUsage
|
||||
print " easy development\n";
|
||||
print " -no-module-version-header\n";
|
||||
print " Don't create module version header file\n";
|
||||
print " -generator <PATH> Specify the makefile generator setting (e.g. 'UNIX')\n";
|
||||
print " -help This help\n";
|
||||
exit 0;
|
||||
}
|
||||
@ -273,6 +278,15 @@ sub classNames {
|
||||
return @ret;
|
||||
}
|
||||
|
||||
sub make_path {
|
||||
my ($dir, $lib, $be_verbose) = @_;
|
||||
unless(-e $dir) {
|
||||
mkpath $dir;
|
||||
$dir = "<outbase>" . substr($dir, length($out_basedir)) if ($be_verbose < 3);
|
||||
print "$lib: mkpath $dir\n" if ($be_verbose > 1);
|
||||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Syntax: syncHeader(header, iheader, copy, timestamp)
|
||||
# Params: header, string, filename to create "symlink" for
|
||||
@ -284,14 +298,14 @@ sub classNames {
|
||||
# Returns: 1 if successful, else 0.
|
||||
######################################################################
|
||||
sub syncHeader {
|
||||
my ($header, $iheader, $copy, $ts) = @_;
|
||||
my ($lib, $header, $iheader, $copy, $ts) = @_;
|
||||
$iheader =~ s=\\=/=g;
|
||||
$header =~ s=\\=/=g;
|
||||
return copyFile($iheader, $header) if($copy);
|
||||
return copyFile($lib, $iheader, $header) if($copy);
|
||||
|
||||
unless(-e $header) {
|
||||
my $header_dir = dirname($header);
|
||||
mkpath $header_dir, !$quiet;
|
||||
make_path($header_dir, $lib, $verbose_level);
|
||||
|
||||
#write it
|
||||
my $iheader_out = fixPaths($iheader, $header_dir);
|
||||
@ -412,7 +426,7 @@ sub fileCompare {
|
||||
######################################################################
|
||||
sub copyFile
|
||||
{
|
||||
my ($file,$ifile, $copy,$knowdiff,$filecontents,$ifilecontents) = @_;
|
||||
my ($lib, $file,$ifile, $copy,$knowdiff,$filecontents,$ifilecontents) = @_;
|
||||
# Bi-directional synchronization
|
||||
open( I, "< " . $file ) || die "Could not open $file for reading";
|
||||
local $/;
|
||||
@ -434,7 +448,7 @@ sub copyFile
|
||||
if ( $knowdiff || ($filecontents ne $ifilecontents) ) {
|
||||
if ( $copy > 0 ) {
|
||||
my $file_dir = dirname($file);
|
||||
mkpath $file_dir, !$quiet unless(-e $file_dir);
|
||||
make_path($file_dir, $lib, $verbose_level);
|
||||
open(O, "> " . $file) || die "Could not open $file for writing (no write permission?)";
|
||||
local $/;
|
||||
binmode O;
|
||||
@ -444,7 +458,7 @@ sub copyFile
|
||||
return 1;
|
||||
} elsif ( $copy < 0 ) {
|
||||
my $ifile_dir = dirname($ifile);
|
||||
mkpath $ifile_dir, !$quiet unless(-e $ifile_dir);
|
||||
make_path($ifile_dir, $lib, $verbose_level);
|
||||
open(O, "> " . $ifile) || die "Could not open $ifile for writing (no write permission?)";
|
||||
local $/;
|
||||
binmode O;
|
||||
@ -468,10 +482,10 @@ sub copyFile
|
||||
######################################################################
|
||||
sub symlinkFile
|
||||
{
|
||||
my ($file,$ifile) = @_;
|
||||
my ($lib, $file, $ifile) = @_;
|
||||
|
||||
if ($isunix) {
|
||||
print "symlink created for $file " unless $quiet;
|
||||
print "$lib: symlink created for $file " if ($verbose_level);
|
||||
if ( $force_relative && ($ifile =~ /^$quoted_basedir/)) {
|
||||
my $t = getcwd();
|
||||
my $c = -1;
|
||||
@ -479,12 +493,12 @@ sub symlinkFile
|
||||
$t =~ s-^$quoted_basedir/--;
|
||||
$p .= "../" while( ($c = index( $t, "/", $c + 1)) != -1 );
|
||||
$file =~ s-^$quoted_basedir/-$p-;
|
||||
print " ($file)\n" unless $quiet;
|
||||
print " ($file)\n" if($verbose_level);
|
||||
}
|
||||
print "\n" unless $quiet;
|
||||
print "\n" if($verbose_level);
|
||||
return symlink($file, $ifile);
|
||||
}
|
||||
return copyFile($file, $ifile);
|
||||
return copyFile($lib, $file, $ifile);
|
||||
}
|
||||
|
||||
######################################################################
|
||||
@ -534,8 +548,10 @@ sub findFiles {
|
||||
######################################################################
|
||||
sub loadSyncProfile {
|
||||
my ($srcbase, $outbase) = @_;
|
||||
print("srcbase = $$srcbase \n");
|
||||
print("outbase = $$outbase \n");
|
||||
if ($verbose_level) {
|
||||
print("<srcbase> = $$srcbase \n");
|
||||
print("<outbase> = $$outbase \n");
|
||||
}
|
||||
|
||||
my $syncprofile = "$$srcbase/sync.profile";
|
||||
my $result;
|
||||
@ -627,8 +643,14 @@ while ( @ARGV ) {
|
||||
$var = "showonly";
|
||||
$val = "yes";
|
||||
} elsif($arg eq "-quiet") {
|
||||
$var = "quiet";
|
||||
$var = "verbose";
|
||||
$val = "0";
|
||||
} elsif($arg eq "-v") {
|
||||
$var = "verbose";
|
||||
$val = "yes";
|
||||
} elsif($arg eq "-verbose") {
|
||||
$var = "verbose";
|
||||
$val = shift @ARGV;
|
||||
} elsif($arg eq "-private") {
|
||||
$var = "create_private_headers";
|
||||
$val = "yes";
|
||||
@ -639,6 +661,9 @@ while ( @ARGV ) {
|
||||
# skip, it's been dealt with at the top of the file
|
||||
shift @ARGV;
|
||||
next;
|
||||
} elsif($arg eq "-generator") {
|
||||
$var = "makefile_generator";
|
||||
$val = shift @ARGV;
|
||||
} elsif($arg =~/^-/) {
|
||||
print "Unknown option: $arg\n\n" if(!$var);
|
||||
showUsage();
|
||||
@ -667,11 +692,13 @@ while ( @ARGV ) {
|
||||
} elsif($showonly) {
|
||||
$showonly--;
|
||||
}
|
||||
} elsif ($var eq "quiet") {
|
||||
} elsif ($var eq "verbose") {
|
||||
if($val eq "yes") {
|
||||
$quiet++;
|
||||
} elsif($quiet) {
|
||||
$quiet--;
|
||||
$verbose_level++;
|
||||
} elsif($val eq "no" && $verbose_level) {
|
||||
$verbose_level--;
|
||||
} else {
|
||||
$verbose_level = int($val);
|
||||
}
|
||||
} elsif ($var eq "check-includes") {
|
||||
if($val eq "yes") {
|
||||
@ -698,7 +725,7 @@ while ( @ARGV ) {
|
||||
$force_relative--;
|
||||
}
|
||||
} elsif ($var eq "module") {
|
||||
print "module :$val:\n" unless $quiet;
|
||||
print "module :$val:\n" if($verbose_level);
|
||||
die "No such module: $val" unless(defined $modules{$val});
|
||||
push @modules_to_sync, $val;
|
||||
} elsif ($var eq "separate-module") {
|
||||
@ -720,6 +747,8 @@ while ( @ARGV ) {
|
||||
$cache_module_fwd = 1;
|
||||
} elsif ($var eq "developer_build") {
|
||||
$developer_build = 1;
|
||||
} elsif ($var eq "makefile_generator") {
|
||||
$makefile_generator = $val;
|
||||
} elsif ($var eq "no_module_version_header") {
|
||||
$no_module_version_header = 1;
|
||||
} elsif ($var eq "output") {
|
||||
@ -766,9 +795,7 @@ loadSyncProfile(\$basedir, \$out_basedir);
|
||||
$isunix = checkUnix; #cache checkUnix
|
||||
|
||||
# create path
|
||||
mkpath "$out_basedir/include", !$quiet;
|
||||
mkpath "$out_basedir/include/Qt", !$quiet;
|
||||
|
||||
make_path("$out_basedir/include/Qt", "<outdir>", $verbose_level);
|
||||
|
||||
foreach my $lib (@modules_to_sync) {
|
||||
#iteration info
|
||||
@ -796,7 +823,7 @@ foreach my $lib (@modules_to_sync) {
|
||||
chomp $module_patch_version;
|
||||
}
|
||||
}
|
||||
print "WARNING: Module $lib\'s pri missing QT.<module>.VERSION variable! Private headers not versioned!\n" if (!$module_version);
|
||||
print "$lib: WARNING: Module\'s pri missing QT.<module>.VERSION variable! Private headers not versioned!\n" if (!$module_version);
|
||||
|
||||
my $pathtoheaders = "";
|
||||
$pathtoheaders = $moduleheaders{$lib} if ($moduleheaders{$lib});
|
||||
@ -870,6 +897,7 @@ foreach my $lib (@modules_to_sync) {
|
||||
my $modulepri = $modulepris{$lib};
|
||||
if (-e $modulepri) {
|
||||
my $modulepriname = basename($modulepri);
|
||||
# FIXME: this creates a file in the source location for shadow-builds
|
||||
my $moduleversionheader = "$modules{$lib}/" . lc($lib) . "version.h";
|
||||
my $modulehexstring = sprintf("0x%02X%02X%02X", int($module_major_version), int($module_minor_version), int($module_patch_version));
|
||||
open MODULE_VERSION_HEADER_FILE, ">$moduleversionheader";
|
||||
@ -882,8 +910,11 @@ foreach my $lib (@modules_to_sync) {
|
||||
print MODULE_VERSION_HEADER_FILE "#define " .uc($lib) . "_VERSION $modulehexstring\n", ;
|
||||
print MODULE_VERSION_HEADER_FILE "\n";
|
||||
print MODULE_VERSION_HEADER_FILE "#endif // QT_". uc($lib) . "_VERSION_H\n";
|
||||
close MODULE_VERSION_HEADER_FILE;
|
||||
$moduleversionheader = "<srcbase>" . substr($moduleversionheader, length($basedir)) if ($verbose_level < 2);
|
||||
print "$lib: created version header $moduleversionheader\n" if($verbose_level);
|
||||
} elsif ($modulepri) {
|
||||
print "WARNING: Module $lib\'s pri file '$modulepri' not found.\nSkipped creating module version header for $lib.\n";
|
||||
print "$lib: WARNING: Module\'s pri file '$modulepri' not found.\n$lib: Skipped creating module version header.\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -913,6 +944,7 @@ foreach my $lib (@modules_to_sync) {
|
||||
push @headers, "*".$if;
|
||||
}
|
||||
}
|
||||
my $header_dirname = "";
|
||||
foreach my $header (@headers) {
|
||||
my $shadow = ($header =~ s/^\*//);
|
||||
$header = 0 if($header =~ /^ui_.*.h/);
|
||||
@ -979,11 +1011,11 @@ foreach my $lib (@modules_to_sync) {
|
||||
# class =~ s,::,/,g;
|
||||
# }
|
||||
$class_lib_map_contents .= "QT_CLASS_LIB($full_class, $lib, $header_base)\n";
|
||||
$header_copies++ if(syncHeader("$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts));
|
||||
$header_copies++ if(syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts));
|
||||
|
||||
# KDE-Compat headers for Phonon
|
||||
if ($lib eq "phonon") {
|
||||
$header_copies++ if (syncHeader("$out_basedir/include/phonon_compat/Phonon/$class", "$out_basedir/include/$lib/$header", 0, $ts));
|
||||
$header_copies++ if (syncHeader($lib, "$out_basedir/include/phonon_compat/Phonon/$class", "$out_basedir/include/$lib/$header", 0, $ts));
|
||||
}
|
||||
}
|
||||
} elsif ($create_private_headers) {
|
||||
@ -994,7 +1026,7 @@ foreach my $lib (@modules_to_sync) {
|
||||
}
|
||||
}
|
||||
foreach(@headers) { #sync them
|
||||
$header_copies++ if(syncHeader($_, $iheader, $copy_headers && !$shadow, $ts));
|
||||
$header_copies++ if(syncHeader($lib, $_, $iheader, $copy_headers && !$shadow, $ts));
|
||||
}
|
||||
|
||||
if($public_header) {
|
||||
@ -1023,9 +1055,29 @@ foreach my $lib (@modules_to_sync) {
|
||||
$pri_install_pfiles.= "$pri_install_iheader ";;
|
||||
}
|
||||
}
|
||||
print "header created for $iheader ($header_copies)\n" if($header_copies > 0 && !$quiet);
|
||||
|
||||
if ($verbose_level && $header_copies) {
|
||||
my $new_header_dirname = dirname($iheader);
|
||||
$new_header_dirname = "<srcbase>" . substr($new_header_dirname, length($basedir)) if ($new_header_dirname && $verbose_level < 2);
|
||||
my $header_base = basename($iheader);
|
||||
if ($verbose_level < 3) {
|
||||
my $line_prefix = ",";
|
||||
if ($new_header_dirname ne $header_dirname) {
|
||||
$line_prefix = "$lib: created fwd-include header(s) for $new_header_dirname/ {";
|
||||
$line_prefix = " }\n".$line_prefix if ($header_dirname);
|
||||
$header_dirname = $new_header_dirname;
|
||||
} else {
|
||||
$line_prefix = ",";
|
||||
}
|
||||
print "$line_prefix $header_base ($header_copies)";
|
||||
} else { # $verbose_level >= 3
|
||||
$iheader = "<srcbase>" . substr($iheader, length($basedir)) if ($verbose_level == 3);
|
||||
print "$lib: created $header_copies fwd-include headers for $iheader\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
print " }\n" if ($header_dirname && $verbose_level > 0 && $verbose_level < 3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1051,11 +1103,11 @@ foreach my $lib (@modules_to_sync) {
|
||||
}
|
||||
if($master_include && $master_contents) {
|
||||
my $master_dir = dirname($master_include);
|
||||
mkpath $master_dir, !$quiet;
|
||||
print "header (master) created for $lib\n" unless $quiet;
|
||||
make_path($master_dir, $lib, $verbose_level);
|
||||
open MASTERINCLUDE, ">$master_include";
|
||||
print MASTERINCLUDE $master_contents;
|
||||
close MASTERINCLUDE;
|
||||
print "$lib: created header (master) file\n" if($verbose_level);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1076,11 +1128,11 @@ foreach my $lib (@modules_to_sync) {
|
||||
}
|
||||
if($headers_pri_file && $master_contents) {
|
||||
my $headers_pri_dir = dirname($headers_pri_file);
|
||||
mkpath $headers_pri_dir, !$quiet;
|
||||
print "headers.pri file created for $lib\n" unless $quiet;
|
||||
make_path($headers_pri_dir, $lib, $verbose_level);
|
||||
open HEADERS_PRI_FILE, ">$headers_pri_file";
|
||||
print HEADERS_PRI_FILE $headers_pri_contents;
|
||||
close HEADERS_PRI_FILE;
|
||||
print "$lib: created headers.pri file\n" if($verbose_level);
|
||||
}
|
||||
|
||||
# create forwarding module pri in qtbase/mkspecs/modules
|
||||
@ -1088,7 +1140,7 @@ foreach my $lib (@modules_to_sync) {
|
||||
my $modulepri = $modulepris{$lib};
|
||||
if (-e $modulepri) {
|
||||
my $modulepriname = basename($modulepri);
|
||||
mkpath($module_fwd);
|
||||
make_path($module_fwd, $lib, $verbose_level);
|
||||
my $moduleprifwd = "$module_fwd/$modulepriname";
|
||||
my $mod_base = $developer_build ? $basedir : $out_basedir;
|
||||
my $mod_component_base = $developer_build ? $qtbasedir : $out_basedir;
|
||||
@ -1114,7 +1166,7 @@ foreach my $lib (@modules_to_sync) {
|
||||
}
|
||||
}
|
||||
} elsif ($modulepri) {
|
||||
print "WARNING: Module $lib\'s pri file '$modulepri' not found.\nSkipped creating forwarding pri for $lib.\n";
|
||||
print "$lib: WARNING: Module\'s pri file '$modulepri' not found.\n$lib: Skipped creating forwarding pri.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1132,7 +1184,7 @@ unless($showonly || !$create_uic_class_map) {
|
||||
}
|
||||
if($class_lib_map) {
|
||||
my $class_lib_map_dir = dirname($class_lib_map);
|
||||
mkpath $class_lib_map_dir, !$quiet;
|
||||
make_path($class_lib_map_dir, "<outdir>", $verbose_level);
|
||||
open CLASS_LIB_MAP, ">$class_lib_map";
|
||||
print CLASS_LIB_MAP $class_lib_map_contents;
|
||||
close CLASS_LIB_MAP;
|
||||
@ -1216,7 +1268,7 @@ if($check_includes) {
|
||||
if($include) {
|
||||
for my $trylib (keys(%modules)) {
|
||||
if(-e "$out_basedir/include/$trylib/$include") {
|
||||
print "WARNING: $iheader includes $include when it should include $trylib/$include\n";
|
||||
print "$lib: WARNING: $iheader includes $include when it should include $trylib/$include\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1234,27 +1286,27 @@ if($check_includes) {
|
||||
}
|
||||
if ($header_skip_qt_begin_header_test == 0) {
|
||||
if ($qt_begin_header_found == 0) {
|
||||
print "WARNING: $iheader does not include QT_BEGIN_HEADER\n";
|
||||
print "$lib: WARNING: $iheader does not include QT_BEGIN_HEADER\n";
|
||||
}
|
||||
|
||||
if ($qt_begin_header_found && $qt_end_header_found == 0) {
|
||||
print "WARNING: $iheader has QT_BEGIN_HEADER but no QT_END_HEADER\n";
|
||||
print "$lib: WARNING: $iheader has QT_BEGIN_HEADER but no QT_END_HEADER\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($header_skip_qt_begin_namespace_test == 0) {
|
||||
if ($qt_begin_namespace_found == 0) {
|
||||
print "WARNING: $iheader does not include QT_BEGIN_NAMESPACE\n";
|
||||
print "$lib: WARNING: $iheader does not include QT_BEGIN_NAMESPACE\n";
|
||||
}
|
||||
|
||||
if ($qt_begin_namespace_found && $qt_end_namespace_found == 0) {
|
||||
print "WARNING: $iheader has QT_BEGIN_NAMESPACE but no QT_END_NAMESPACE\n";
|
||||
print "$lib: WARNING: $iheader has QT_BEGIN_NAMESPACE but no QT_END_NAMESPACE\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($header_skip_qt_module_test == 0) {
|
||||
if ($qt_module_found == 0) {
|
||||
print "WARNING: $iheader does not include QT_MODULE\n";
|
||||
print "$lib: WARNING: $iheader does not include QT_MODULE\n";
|
||||
}
|
||||
}
|
||||
close(F);
|
||||
@ -1266,4 +1318,21 @@ if($check_includes) {
|
||||
}
|
||||
}
|
||||
|
||||
# Do configure tests now (pass some things along)
|
||||
# fatal tests have a non zero return
|
||||
# If the generator is not set (e.g. someone invoking syncqt as part of configure etc, then don't run tests either)
|
||||
unless ($showonly || $makefile_generator eq '') {
|
||||
my $configtests = dirname($0)."/qtmodule-configtests";
|
||||
if (! -f $configtests) {
|
||||
$configtests = $qtbasedir."/bin/qtmodule-configtests";
|
||||
}
|
||||
if (! -f $configtests) {
|
||||
warn "Unable to locate qtmodule-configtests script - config tests disabled.\n";
|
||||
} else {
|
||||
if (system($EXECUTABLE_NAME, $configtests, $basedir, $out_basedir, $qtbasedir, $makefile_generator)) {
|
||||
die "$configtests exited with status $?";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit 0;
|
||||
|
10
configure
vendored
10
configure
vendored
@ -2577,7 +2577,7 @@ if [ "$OPT_SHADOW" = "yes" ]; then
|
||||
chmod 755 "$outpath/bin/syncqt"
|
||||
fi
|
||||
|
||||
for i in elf2e32_qtwrapper createpackage patch_capabilities; do
|
||||
for i in elf2e32_qtwrapper createpackage patch_capabilities qtmodule-configtests; do
|
||||
rm -f "$outpath/bin/$i"
|
||||
if [ -x "$relpath/bin/$i" ]; then
|
||||
mkdir -p "$outpath/bin"
|
||||
@ -2970,7 +2970,7 @@ if [ '!' -f "${XQMAKESPEC}/qplatformdefs.h" ]; then
|
||||
echo
|
||||
echo " $XQMAKESPEC/qplatformdefs.h"
|
||||
echo
|
||||
echo " Please contact qt-bugs@trolltech.com."
|
||||
echo " Please contact qt-info@nokia.com."
|
||||
echo
|
||||
exit 2
|
||||
fi
|
||||
@ -6911,7 +6911,7 @@ fi
|
||||
# For "-carbon" builds: 32 bit x86/ppc.
|
||||
# For builds on snow leopard : compiler default (64-bit).
|
||||
# For builds on leopard : compiler default (32-bit).
|
||||
if [ "$PLATFORM_MAC" = "yes" ] && [ "$CFG_MAC_ARCHS" = "" ]; then
|
||||
if [ "$CFG_ARCH" = "macosx" ] && [ "$CFG_MAC_ARCHS" = "" ]; then
|
||||
source "$mactests/defaultarch.test" "$TEST_COMPILER" "$OPT_VERBOSE" "$mactests"
|
||||
|
||||
if [ "$CFG_MAC_CARBON" = "yes" ]; then
|
||||
@ -7150,7 +7150,7 @@ fi
|
||||
[ "$CFG_AVX" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG avx"
|
||||
[ "$CFG_IWMMXT" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG iwmmxt"
|
||||
[ "$CFG_NEON" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG neon"
|
||||
[ "$PLATFORM_MAC" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG $CFG_MAC_ARCHS"
|
||||
[ "$CFG_ARCH" = "macosx" ] && QMAKE_CONFIG="$QMAKE_CONFIG $CFG_MAC_ARCHS"
|
||||
if [ "$CFG_CLOCK_GETTIME" = "yes" ]; then
|
||||
QT_CONFIG="$QT_CONFIG clock-gettime"
|
||||
fi
|
||||
@ -8617,7 +8617,7 @@ else
|
||||
echo "Building for: $XPLATFORM"
|
||||
fi
|
||||
|
||||
if [ "$PLATFORM_MAC" = "yes" ]; then
|
||||
if [ ! -z "$CFG_MAC_ARCHS" ]; then
|
||||
echo "Architecture: $CFG_ARCH ($CFG_MAC_ARCHS )"
|
||||
else
|
||||
echo "Architecture: $CFG_ARCH"
|
||||
|
3
dist/changes-5.0.0
vendored
3
dist/changes-5.0.0
vendored
@ -17,6 +17,9 @@ information about a particular change.
|
||||
- Unite clipping support has been removed from QPainter. The alternative is
|
||||
to unite QRegion's and using the result on QPainter.
|
||||
|
||||
- QLibrary::resolve() now returns a function pointer instead of a void
|
||||
pointer.
|
||||
|
||||
****************************************************************************
|
||||
* General *
|
||||
****************************************************************************
|
||||
|
@ -316,7 +316,7 @@
|
||||
Now we construct the \c FlippablePad item, passing its column-row count to
|
||||
its constructor.
|
||||
|
||||
The pad is constrolled by three transformations, and we create one
|
||||
The pad is controlled by three transformations, and we create one
|
||||
QGraphicsRotation object for each of these.
|
||||
|
||||
\list
|
||||
|
@ -54,7 +54,7 @@ LocationDialog::LocationDialog(QWidget *parent)
|
||||
scopeComboBox->addItem(tr("System"));
|
||||
|
||||
organizationComboBox = new QComboBox;
|
||||
organizationComboBox->addItem(tr("Trolltech"));
|
||||
organizationComboBox->addItem(tr("Qt"));
|
||||
organizationComboBox->setEditable(true);
|
||||
|
||||
applicationComboBox = new QComboBox;
|
||||
|
@ -39,4 +39,4 @@ qmake -spec macx-xcode
|
||||
|
||||
Then open the generated Xcode project in Xcode and build it.
|
||||
|
||||
Feel free to send comments about the tutorial to qt-bugs@trolltech.com.
|
||||
Feel free to send comments about the tutorial to qt-info@nokia.com.
|
||||
|
@ -39,4 +39,4 @@ qmake -spec macx-xcode
|
||||
|
||||
Then open the generated Xcode project in Xcode and build it.
|
||||
|
||||
Feel free to send comments about the tutorial to qt-bugs@trolltech.com.
|
||||
Feel free to send comments about the tutorial to qt-info@nokia.com.
|
||||
|
1
mkspecs/features/declarative_debug.prf
Normal file
1
mkspecs/features/declarative_debug.prf
Normal file
@ -0,0 +1 @@
|
||||
contains(QT, declarative):DEFINES += QT_DECLARATIVE_DEBUG
|
@ -2,7 +2,7 @@ load(exclusive_builds)
|
||||
### Qt 5: remove "uic" and "resources" - or add "qt"
|
||||
CONFIG = lex yacc warn_on debug uic resources $$CONFIG
|
||||
|
||||
exists($$_PRO_FILE_PWD_/sync.profile) {
|
||||
!build_pass:exists($$_PRO_FILE_PWD_/sync.profile) {
|
||||
PRO_BASENAME = $$basename(_PRO_FILE_)
|
||||
|
||||
# Try to detect proper QTDIR path. We require QTDIR, as syncqt uses that to create qt_module.pri
|
||||
@ -31,7 +31,7 @@ exists($$_PRO_FILE_PWD_/sync.profile) {
|
||||
|
||||
qtPrepareTool(QMAKE_SYNCQT, syncqt)
|
||||
|
||||
MSG = $$quote($$QMAKE_SYNCQT $$QTFWD -outdir $$OUT_PWD $$_PRO_FILE_PWD_)
|
||||
MSG = $$quote($$QMAKE_SYNCQT $$QTFWD -generator $$MAKEFILE_GENERATOR -outdir $$OUT_PWD $$_PRO_FILE_PWD_)
|
||||
!silent:message($$MSG)
|
||||
system($$MSG) {
|
||||
# success! Nothing to do
|
||||
|
@ -140,7 +140,7 @@ defineTest(qtAddModule) {
|
||||
}
|
||||
isEmpty(LINKAGE) {
|
||||
# Make sure we can link to uninstalled libraries
|
||||
!isEqual(MODULE_LIBS, $[QT_INSTALL_LIBS]) {
|
||||
!isEqual(MODULE_LIBS, $$[QT_INSTALL_LIBS]) {
|
||||
QMAKE_LIBDIR *= $$MODULE_LIBS
|
||||
unix:!mac:QMAKE_LFLAGS *= "-Wl,-rpath-link,$$MODULE_LIBS"
|
||||
}
|
||||
|
@ -186,6 +186,9 @@ DEFINES *= QT_USE_QSTRINGBUILDER
|
||||
|
||||
TARGET = $$qtLibraryTarget($$TARGET$$QT_LIBINFIX) #do this towards the end
|
||||
|
||||
qtPrepareTool(QMAKE_MOC, moc)
|
||||
qtPrepareTool(QMAKE_UIC, uic)
|
||||
qtPrepareTool(QMAKE_RCC, rcc)
|
||||
qtPrepareTool(QMAKE_LUPDATE, lupdate)
|
||||
qtPrepareTool(QMAKE_LRELEASE, lrelease)
|
||||
|
||||
|
@ -1382,16 +1382,15 @@ QMakeProject::read(uchar cmd)
|
||||
read(Option::mkfile::cachefile, base_vars);
|
||||
}
|
||||
}
|
||||
|
||||
if(cmd & ReadFeatures) {
|
||||
debug_msg(1, "Processing default_pre: %s", vars["CONFIG"].join("::").toLatin1().constData());
|
||||
if(doProjectInclude("default_pre", IncludeFlagFeature, base_vars) == IncludeNoExist)
|
||||
doProjectInclude("default", IncludeFlagFeature, base_vars);
|
||||
}
|
||||
}
|
||||
|
||||
vars = base_vars; // start with the base
|
||||
|
||||
if(cmd & ReadFeatures) {
|
||||
debug_msg(1, "Processing default_pre: %s", vars["CONFIG"].join("::").toLatin1().constData());
|
||||
doProjectInclude("default_pre", IncludeFlagFeature, vars);
|
||||
}
|
||||
|
||||
//get a default
|
||||
if(pfile != "-" && vars["TARGET"].isEmpty())
|
||||
vars["TARGET"].append(QFileInfo(pfile).baseName());
|
||||
|
@ -135,6 +135,11 @@ syncqt.files=$$QT_BUILD_TREE/bin/syncqt
|
||||
win32:syncqt.files=$$QT_BUILD_TREE/bin/syncqt.bat
|
||||
INSTALLS += syncqt
|
||||
|
||||
#qtmodule-configtests
|
||||
configtests.path=$$[QT_INSTALL_BINS]
|
||||
configtests.files=$$QT_BUILD_TREE/bin/qtmodule-configtests
|
||||
INSTALLS += configtests
|
||||
|
||||
#mkspecs
|
||||
mkspecs.path=$$[QT_INSTALL_DATA]/mkspecs
|
||||
mkspecs.files=$$QT_BUILD_TREE/mkspecs/qconfig.pri $$files($$QT_SOURCE_TREE/mkspecs/*)
|
||||
|
@ -144,7 +144,7 @@ HB_CharCategory HB_GetUnicodeCharCategory(HB_UChar32 ch);
|
||||
int HB_GetUnicodeCharCombiningClass(HB_UChar32 ch);
|
||||
HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch);
|
||||
|
||||
void *HB_Library_Resolve(const char *library, int version, const char *symbol);
|
||||
void (*HB_Library_Resolve(const char *library, int version, const char *symbol))();
|
||||
|
||||
HB_END_HEADER
|
||||
|
||||
|
@ -79,7 +79,7 @@ void HB_GetGraphemeAndLineBreakClass(HB_UChar32 ch, HB_GraphemeClass *grapheme,
|
||||
*lineBreak = (HB_LineBreakClass) prop->line_break_class;
|
||||
}
|
||||
|
||||
void *HB_Library_Resolve(const char *library, int version, const char *symbol)
|
||||
void (*HB_Library_Resolve(const char *library, int version, const char *symbol))()
|
||||
{
|
||||
return QLibrary::resolve(library, version, symbol);
|
||||
}
|
||||
|
@ -75,13 +75,34 @@ inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
|
||||
return testAndSetOrdered(expectedValue, newValue);
|
||||
}
|
||||
|
||||
inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
|
||||
inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
|
||||
{
|
||||
return testAndSetOrdered(expectedValue, newValue);
|
||||
}
|
||||
|
||||
inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
|
||||
{
|
||||
int returnValue = _q_value;
|
||||
_q_value += valueToAdd;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
|
||||
{
|
||||
return fetchAndAddOrdered(valueToAdd);
|
||||
}
|
||||
|
||||
inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
|
||||
{
|
||||
return fetchAndAddOrdered(valueToAdd);
|
||||
}
|
||||
|
||||
inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
|
||||
{
|
||||
return fetchAndAddOrdered(valueToAdd);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
|
||||
{
|
||||
|
@ -718,6 +718,13 @@ QT_BEGIN_NAMESPACE
|
||||
\sa QtMsgHandler, qInstallMsgHandler()
|
||||
*/
|
||||
|
||||
/*! \typedef QFunctionPointer
|
||||
\relates <QtGlobal>
|
||||
|
||||
This is a typedef for \c{void (*)()}, a pointer to a function that takes
|
||||
no arguments and returns void.
|
||||
*/
|
||||
|
||||
/*! \macro qint64 Q_INT64_C(literal)
|
||||
\relates <QtGlobal>
|
||||
|
||||
|
@ -281,7 +281,7 @@ namespace QT_NAMESPACE {}
|
||||
# define Q_OS_VXWORKS
|
||||
#elif defined(__MAKEDEPEND__)
|
||||
#else
|
||||
# error "Qt has not been ported to this OS - talk to qt-bugs@trolltech.com"
|
||||
# error "Qt has not been ported to this OS - talk to qt-info@nokia.com"
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINCE)
|
||||
@ -794,7 +794,7 @@ namespace QT_NAMESPACE {}
|
||||
# define Q_CC_NOKIAX86
|
||||
|
||||
#else
|
||||
# error "Qt has not been tested with this compiler - talk to qt-bugs@trolltech.com"
|
||||
# error "Qt has not been tested with this compiler - talk to qt-info@nokia.com"
|
||||
#endif
|
||||
|
||||
|
||||
@ -1807,6 +1807,8 @@ Q_CORE_EXPORT void qt_message_output(QtMsgType, const char *buf);
|
||||
typedef void (*QtMsgHandler)(QtMsgType, const char *);
|
||||
Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
|
||||
|
||||
typedef void (*QFunctionPointer)();
|
||||
|
||||
#if !defined(Q_UNIMPLEMENTED)
|
||||
# define Q_UNIMPLEMENTED() qWarning("%s:%d: %s: Unimplemented code.", __FILE__, __LINE__, Q_FUNC_INFO)
|
||||
#endif
|
||||
|
@ -131,7 +131,7 @@
|
||||
# define __NR_inotify_rm_watch 286
|
||||
# define __NR_inotify_init1 328
|
||||
#else
|
||||
# error "This architecture is not supported. Please talk to qt-bugs@trolltech.com"
|
||||
# error "This architecture is not supported. Please talk to qt-info@nokia.com"
|
||||
#endif
|
||||
|
||||
#if !defined(IN_CLOEXEC) && defined(O_CLOEXEC) && defined(__NR_inotify_init1)
|
||||
|
@ -45,109 +45,10 @@
|
||||
#include "qthread.h"
|
||||
#include <private/qthread_p.h>
|
||||
#include <private/qcoreapplication_p.h>
|
||||
#include <private/qfreelist_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
|
||||
static const int TimerIdMask = 0x00ffffff;
|
||||
static const int TimerSerialMask = ~TimerIdMask & ~0x80000000;
|
||||
static const int TimerSerialCounter = TimerIdMask + 1;
|
||||
static const int MaxTimerId = TimerIdMask;
|
||||
|
||||
static int FirstBucket[] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
|
||||
};
|
||||
|
||||
enum {
|
||||
FirstBucketOffset = 0,
|
||||
SecondBucketOffset = sizeof(FirstBucket) / sizeof(FirstBucket[0]),
|
||||
ThirdBucketOffset = 0x100,
|
||||
FourthBucketOffset = 0x1000,
|
||||
FifthBucketOffset = 0x10000,
|
||||
SixthBucketOffset = 0x100000
|
||||
};
|
||||
|
||||
enum {
|
||||
FirstBucketSize = SecondBucketOffset,
|
||||
SecondBucketSize = ThirdBucketOffset - SecondBucketOffset,
|
||||
ThirdBucketSize = FourthBucketOffset - ThirdBucketOffset,
|
||||
FourthBucketSize = FifthBucketOffset - FourthBucketOffset,
|
||||
FifthBucketSize = SixthBucketOffset - FifthBucketOffset,
|
||||
SixthBucketSize = MaxTimerId - SixthBucketOffset
|
||||
};
|
||||
|
||||
static const int BucketSize[] = {
|
||||
FirstBucketSize, SecondBucketSize, ThirdBucketSize,
|
||||
FourthBucketSize, FifthBucketSize, SixthBucketSize
|
||||
};
|
||||
enum { NumberOfBuckets = sizeof(BucketSize) / sizeof(BucketSize[0]) };
|
||||
|
||||
static const int BucketOffset[] = {
|
||||
FirstBucketOffset, SecondBucketOffset, ThirdBucketOffset,
|
||||
FourthBucketOffset, FifthBucketOffset, SixthBucketOffset
|
||||
};
|
||||
|
||||
static QBasicAtomicPointer<int> timerIds[] =
|
||||
{ Q_BASIC_ATOMIC_INITIALIZER(FirstBucket),
|
||||
Q_BASIC_ATOMIC_INITIALIZER(0),
|
||||
Q_BASIC_ATOMIC_INITIALIZER(0),
|
||||
Q_BASIC_ATOMIC_INITIALIZER(0),
|
||||
Q_BASIC_ATOMIC_INITIALIZER(0),
|
||||
Q_BASIC_ATOMIC_INITIALIZER(0) };
|
||||
|
||||
static void timerIdsDestructorFunction()
|
||||
{
|
||||
// start at one, the first bucket is pre-allocated
|
||||
for (int i = 1; i < NumberOfBuckets; ++i)
|
||||
delete [] static_cast<int *>(timerIds[i]);
|
||||
}
|
||||
Q_DESTRUCTOR_FUNCTION(timerIdsDestructorFunction)
|
||||
|
||||
static QBasicAtomicInt nextFreeTimerId = Q_BASIC_ATOMIC_INITIALIZER(1);
|
||||
|
||||
// avoid the ABA-problem by using 7 of the top 8 bits of the timerId as a serial number
|
||||
static inline int prepareNewValueWithSerialNumber(int oldId, int newId)
|
||||
{
|
||||
return (newId & TimerIdMask) | ((oldId + TimerSerialCounter) & TimerSerialMask);
|
||||
}
|
||||
|
||||
namespace {
|
||||
template<bool> struct QStaticAssertType;
|
||||
template<> struct QStaticAssertType<true> { enum { Value = 1 }; };
|
||||
}
|
||||
#define q_static_assert(expr) (void)QStaticAssertType<expr>::Value
|
||||
|
||||
static inline int bucketOffset(int timerId)
|
||||
{
|
||||
q_static_assert(sizeof BucketSize == sizeof BucketOffset);
|
||||
q_static_assert(sizeof(timerIds) / sizeof(timerIds[0]) == NumberOfBuckets);
|
||||
|
||||
for (int i = 0; i < NumberOfBuckets; ++i) {
|
||||
if (timerId < BucketSize[i])
|
||||
return i;
|
||||
timerId -= BucketSize[i];
|
||||
}
|
||||
qFatal("QAbstractEventDispatcher: INTERNAL ERROR, timer ID %d is too large", timerId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int bucketIndex(int bucket, int timerId)
|
||||
{
|
||||
return timerId - BucketOffset[bucket];
|
||||
}
|
||||
|
||||
static inline int *allocateBucket(int bucket)
|
||||
{
|
||||
// allocate a new bucket
|
||||
const int size = BucketSize[bucket];
|
||||
const int offset = BucketOffset[bucket];
|
||||
int *b = new int[size];
|
||||
for (int i = 0; i != size; ++i)
|
||||
b[i] = offset + i + 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
void QAbstractEventDispatcherPrivate::init()
|
||||
{
|
||||
Q_Q(QAbstractEventDispatcher);
|
||||
@ -158,79 +59,54 @@ void QAbstractEventDispatcherPrivate::init()
|
||||
}
|
||||
}
|
||||
|
||||
// Timer IDs are implemented using a free-list;
|
||||
// there's a vector initialized with:
|
||||
// X[i] = i + 1
|
||||
// and nextFreeTimerId starts with 1.
|
||||
//
|
||||
// Allocating a timer ID involves taking the ID from
|
||||
// X[nextFreeTimerId]
|
||||
// updating nextFreeTimerId to this value and returning the old value
|
||||
//
|
||||
// When the timer ID is allocated, its cell in the vector is unused (it's a
|
||||
// free list). As an added protection, we use the cell to store an invalid
|
||||
// (negative) value that we can later check for integrity.
|
||||
//
|
||||
// (continues below).
|
||||
// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
|
||||
struct QtTimerIdFreeListConstants : public QFreeListDefaultConstants
|
||||
{
|
||||
enum
|
||||
{
|
||||
InitialNextValue = 1,
|
||||
BlockCount = 6,
|
||||
};
|
||||
|
||||
static const int Sizes[BlockCount];
|
||||
};
|
||||
|
||||
enum {
|
||||
Offset0 = 0x00000000,
|
||||
Offset1 = 0x00000040,
|
||||
Offset2 = 0x00000100,
|
||||
Offset3 = 0x00001000,
|
||||
Offset4 = 0x00010000,
|
||||
Offset5 = 0x00100000,
|
||||
|
||||
Size0 = Offset1 - Offset0,
|
||||
Size1 = Offset2 - Offset1,
|
||||
Size2 = Offset3 - Offset2,
|
||||
Size3 = Offset4 - Offset3,
|
||||
Size4 = Offset5 - Offset4,
|
||||
Size5 = QtTimerIdFreeListConstants::MaxIndex - Offset5
|
||||
};
|
||||
|
||||
const int QtTimerIdFreeListConstants::Sizes[QtTimerIdFreeListConstants::BlockCount] = {
|
||||
Size0,
|
||||
Size1,
|
||||
Size2,
|
||||
Size3,
|
||||
Size4,
|
||||
Size5
|
||||
};
|
||||
|
||||
typedef QFreeList<void, QtTimerIdFreeListConstants> QtTimerIdFreeList;
|
||||
Q_GLOBAL_STATIC(QtTimerIdFreeList, timerIdFreeList)
|
||||
|
||||
int QAbstractEventDispatcherPrivate::allocateTimerId()
|
||||
{
|
||||
int timerId, newTimerId;
|
||||
int at, *b;
|
||||
do {
|
||||
timerId = nextFreeTimerId; //.loadAcquire(); // ### FIXME Proper memory ordering semantics
|
||||
|
||||
// which bucket are we looking in?
|
||||
int which = timerId & TimerIdMask;
|
||||
int bucket = bucketOffset(which);
|
||||
at = bucketIndex(bucket, which);
|
||||
b = timerIds[bucket];
|
||||
|
||||
if (!b) {
|
||||
// allocate a new bucket
|
||||
b = allocateBucket(bucket);
|
||||
if (!timerIds[bucket].testAndSetRelease(0, b)) {
|
||||
// another thread won the race to allocate the bucket
|
||||
delete [] b;
|
||||
b = timerIds[bucket];
|
||||
}
|
||||
}
|
||||
|
||||
newTimerId = prepareNewValueWithSerialNumber(timerId, b[at]);
|
||||
} while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId));
|
||||
|
||||
b[at] = -timerId;
|
||||
|
||||
return timerId;
|
||||
return timerIdFreeList()->next();
|
||||
}
|
||||
|
||||
// Releasing a timer ID requires putting the current ID back in the vector;
|
||||
// we do it by setting:
|
||||
// X[timerId] = nextFreeTimerId;
|
||||
// then we update nextFreeTimerId to the timer we've just released
|
||||
//
|
||||
// The extra code in allocateTimerId and releaseTimerId are ABA prevention
|
||||
// and bucket memory. The buckets are simply to make sure we allocate only
|
||||
// the necessary number of timers. See above.
|
||||
//
|
||||
// ABA prevention simply adds a value to 7 of the top 8 bits when resetting
|
||||
// nextFreeTimerId.
|
||||
void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
|
||||
{
|
||||
int which = timerId & TimerIdMask;
|
||||
int bucket = bucketOffset(which);
|
||||
int at = bucketIndex(bucket, which);
|
||||
int *b = timerIds[bucket];
|
||||
|
||||
Q_ASSERT_X(timerId == -b[at], "QAbstractEventDispatcher::releaseTimerId",
|
||||
"Internal error: timer ID not found");
|
||||
|
||||
int freeId, newTimerId;
|
||||
do {
|
||||
freeId = nextFreeTimerId;//.loadAcquire(); // ### FIXME Proper memory ordering semantics
|
||||
b[at] = freeId & TimerIdMask;
|
||||
|
||||
newTimerId = prepareNewValueWithSerialNumber(freeId, timerId);
|
||||
} while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId));
|
||||
timerIdFreeList()->release(timerId);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -859,20 +859,31 @@ QMetaProperty QMetaObject::property(int index) const
|
||||
if (flags & EnumOrFlag) {
|
||||
result.menum = enumerator(indexOfEnumerator(type));
|
||||
if (!result.menum.isValid()) {
|
||||
QByteArray enum_name = type;
|
||||
QByteArray scope_name = d.stringdata;
|
||||
int s = enum_name.lastIndexOf("::");
|
||||
if (s > 0) {
|
||||
scope_name = enum_name.left(s);
|
||||
enum_name = enum_name.mid(s + 2);
|
||||
const char *enum_name = type;
|
||||
const char *scope_name = d.stringdata;
|
||||
char *scope_buffer = 0;
|
||||
|
||||
const char *colon = strrchr(enum_name, ':');
|
||||
// ':' will always appear in pairs
|
||||
Q_ASSERT(colon <= enum_name || *(colon-1) == ':');
|
||||
if (colon > enum_name) {
|
||||
int len = colon-enum_name-1;
|
||||
scope_buffer = (char *)qMalloc(len+1);
|
||||
qMemCopy(scope_buffer, enum_name, len);
|
||||
scope_buffer[len] = '\0';
|
||||
scope_name = scope_buffer;
|
||||
enum_name = colon+1;
|
||||
}
|
||||
|
||||
const QMetaObject *scope = 0;
|
||||
if (scope_name == "Qt")
|
||||
if (qstrcmp(scope_name, "Qt") == 0)
|
||||
scope = &QObject::staticQtMetaObject;
|
||||
else
|
||||
scope = QMetaObject_findMetaObject(this, scope_name);
|
||||
if (scope)
|
||||
result.menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
|
||||
if (scope_buffer)
|
||||
qFree(scope_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,8 @@ enum MethodFlags {
|
||||
};
|
||||
|
||||
enum MetaObjectFlags {
|
||||
DynamicMetaObject = 0x01
|
||||
DynamicMetaObject = 0x01,
|
||||
RequiresVariantMetaObject = 0x02
|
||||
};
|
||||
|
||||
class QMutex;
|
||||
|
@ -60,7 +60,6 @@
|
||||
#include <qsharedpointer.h>
|
||||
|
||||
#include <private/qorderedmutexlocker_p.h>
|
||||
#include <private/qmutexpool_p.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
@ -95,35 +94,22 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
|
||||
return types;
|
||||
}
|
||||
|
||||
static QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
static QBasicMutex _q_ObjectMutexPool[131];
|
||||
|
||||
/** \internal
|
||||
* mutex to be locked when accessing the connectionlists or the senders list
|
||||
*/
|
||||
static inline QMutex *signalSlotLock(const QObject *o)
|
||||
{
|
||||
if (!signalSlotMutexes) {
|
||||
QMutexPool *mp = new QMutexPool;
|
||||
if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
|
||||
delete mp;
|
||||
}
|
||||
}
|
||||
return signalSlotMutexes->get(o);
|
||||
return static_cast<QMutex *>(&_q_ObjectMutexPool[
|
||||
uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]);
|
||||
}
|
||||
|
||||
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
|
||||
{
|
||||
objectCount.ref();
|
||||
}
|
||||
{}
|
||||
|
||||
extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
|
||||
{
|
||||
if(!objectCount.deref()) {
|
||||
QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0);
|
||||
delete old;
|
||||
}
|
||||
}
|
||||
{}
|
||||
|
||||
struct QConnectionSenderSwitcher {
|
||||
QObject *receiver;
|
||||
@ -879,7 +865,7 @@ QObject::~QObject()
|
||||
if (c->next) c->next->prev = c->prev;
|
||||
}
|
||||
if (needToUnlock)
|
||||
m->unlockInline();
|
||||
m->unlock();
|
||||
|
||||
connectionList.first = c->nextConnectionList;
|
||||
delete c;
|
||||
@ -903,7 +889,7 @@ QObject::~QObject()
|
||||
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
|
||||
//the node has maybe been removed while the mutex was unlocked in relock?
|
||||
if (!node || node->sender != sender) {
|
||||
m->unlockInline();
|
||||
m->unlock();
|
||||
continue;
|
||||
}
|
||||
node->receiver = 0;
|
||||
@ -913,7 +899,7 @@ QObject::~QObject()
|
||||
|
||||
node = node->next;
|
||||
if (needToUnlock)
|
||||
m->unlockInline();
|
||||
m->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3077,7 +3063,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
|
||||
}
|
||||
|
||||
if (needToUnlock)
|
||||
receiverMutex->unlockInline();
|
||||
receiverMutex->unlock();
|
||||
|
||||
c->receiver = 0;
|
||||
|
||||
|
@ -447,7 +447,7 @@ QLibraryPrivate::~QLibraryPrivate()
|
||||
}
|
||||
}
|
||||
|
||||
void *QLibraryPrivate::resolve(const char *symbol)
|
||||
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
|
||||
{
|
||||
if (!pHnd)
|
||||
return 0;
|
||||
@ -1129,7 +1129,7 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver
|
||||
Note: In Symbian resolving with symbol names works only if the loaded
|
||||
library was built as STDDLL. Otherwise, the ordinals must be used.
|
||||
*/
|
||||
void *QLibrary::resolve(const char *symbol)
|
||||
QFunctionPointer QLibrary::resolve(const char *symbol)
|
||||
{
|
||||
if (!isLoaded() && !load())
|
||||
return 0;
|
||||
@ -1152,7 +1152,7 @@ void *QLibrary::resolve(const char *symbol)
|
||||
|
||||
\sa resolve()
|
||||
*/
|
||||
void *QLibrary::resolve(const QString &fileName, const char *symbol)
|
||||
QFunctionPointer QLibrary::resolve(const QString &fileName, const char *symbol)
|
||||
{
|
||||
QLibrary library(fileName);
|
||||
return library.resolve(symbol);
|
||||
@ -1175,7 +1175,7 @@ void *QLibrary::resolve(const QString &fileName, const char *symbol)
|
||||
|
||||
\sa resolve()
|
||||
*/
|
||||
void *QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
|
||||
QFunctionPointer QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
|
||||
{
|
||||
QLibrary library(fileName, verNum);
|
||||
return library.resolve(symbol);
|
||||
@ -1199,7 +1199,7 @@ void *QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
|
||||
|
||||
\sa resolve()
|
||||
*/
|
||||
void *QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
|
||||
QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
|
||||
{
|
||||
QLibrary library(fileName, version);
|
||||
return library.resolve(symbol);
|
||||
|
@ -79,10 +79,10 @@ public:
|
||||
explicit QLibrary(const QString& fileName, const QString &version, QObject *parent = 0);
|
||||
~QLibrary();
|
||||
|
||||
void *resolve(const char *symbol);
|
||||
static void *resolve(const QString &fileName, const char *symbol);
|
||||
static void *resolve(const QString &fileName, int verNum, const char *symbol);
|
||||
static void *resolve(const QString &fileName, const QString &version, const char *symbol);
|
||||
QFunctionPointer resolve(const char *symbol);
|
||||
static QFunctionPointer resolve(const QString &fileName, const char *symbol);
|
||||
static QFunctionPointer resolve(const QString &fileName, int verNum, const char *symbol);
|
||||
static QFunctionPointer resolve(const QString &fileName, const QString &version, const char *symbol);
|
||||
|
||||
bool load();
|
||||
bool unload();
|
||||
|
@ -87,7 +87,7 @@ public:
|
||||
bool loadPlugin(); // loads and resolves instance
|
||||
bool unload();
|
||||
void release();
|
||||
void *resolve(const char *);
|
||||
QFunctionPointer resolve(const char *);
|
||||
|
||||
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
|
||||
|
||||
@ -108,7 +108,7 @@ private:
|
||||
|
||||
bool load_sys();
|
||||
bool unload_sys();
|
||||
void *resolve_sys(const char *);
|
||||
QFunctionPointer resolve_sys(const char *);
|
||||
|
||||
QAtomicInt libraryRefCount;
|
||||
QAtomicInt libraryUnloadCount;
|
||||
|
@ -267,29 +267,29 @@ bool QLibraryPrivate::unload_sys()
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
Q_CORE_EXPORT void *qt_mac_resolve_sys(void *handle, const char *symbol)
|
||||
Q_CORE_EXPORT QFunctionPointer qt_mac_resolve_sys(void *handle, const char *symbol)
|
||||
{
|
||||
return dlsym(handle, symbol);
|
||||
return QFunctionPointer(dlsym(handle, symbol));
|
||||
}
|
||||
#endif
|
||||
|
||||
void* QLibraryPrivate::resolve_sys(const char* symbol)
|
||||
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
|
||||
{
|
||||
#if defined(QT_AOUT_UNDERSCORE)
|
||||
// older a.out systems add an underscore in front of symbols
|
||||
char* undrscr_symbol = new char[strlen(symbol)+2];
|
||||
undrscr_symbol[0] = '_';
|
||||
strcpy(undrscr_symbol+1, symbol);
|
||||
void* address = dlsym(pHnd, undrscr_symbol);
|
||||
QFunctionPointer address = QFunctionPointer(dlsym(pHnd, undrscr_symbol));
|
||||
delete [] undrscr_symbol;
|
||||
#elif defined(QT_HPUX_LD)
|
||||
void* address = 0;
|
||||
QFunctionPointer address = 0;
|
||||
if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0)
|
||||
address = 0;
|
||||
#elif defined (QT_NO_DYNAMIC_LIBRARY)
|
||||
void *address = 0;
|
||||
QFunctionPointer address = 0;
|
||||
#else
|
||||
void* address = dlsym(pHnd, symbol);
|
||||
QFunctionPointer address = QFunctionPointer(dlsym(pHnd, symbol));
|
||||
#endif
|
||||
if (!address) {
|
||||
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
|
||||
|
@ -113,12 +113,12 @@ bool QLibraryPrivate::unload_sys()
|
||||
return true;
|
||||
}
|
||||
|
||||
void* QLibraryPrivate::resolve_sys(const char* symbol)
|
||||
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
|
||||
{
|
||||
#ifdef Q_OS_WINCE
|
||||
void* address = (void*)GetProcAddress(pHnd, (const wchar_t*)QString::fromLatin1(symbol).utf16());
|
||||
FARPROC address = GetProcAddress(pHnd, (const wchar_t*)QString::fromLatin1(symbol).utf16());
|
||||
#else
|
||||
void* address = (void*)GetProcAddress(pHnd, symbol);
|
||||
FARPROC address = GetProcAddress(pHnd, symbol);
|
||||
#endif
|
||||
if (!address) {
|
||||
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
|
||||
@ -126,6 +126,6 @@ void* QLibraryPrivate::resolve_sys(const char* symbol)
|
||||
} else {
|
||||
errorString.clear();
|
||||
}
|
||||
return address;
|
||||
return QFunctionPointer(address);
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
@ -78,20 +78,20 @@ public:
|
||||
return (m_handle != 0);
|
||||
}
|
||||
|
||||
void *resolve(const char *symbol)
|
||||
QFunctionPointer resolve(const char *symbol)
|
||||
{
|
||||
if (!m_didLoad)
|
||||
load();
|
||||
if (!m_handle)
|
||||
return 0;
|
||||
#ifdef Q_OS_WINCE
|
||||
return (void*)GetProcAddress(m_handle, (const wchar_t*)QString::fromLatin1(symbol).utf16());
|
||||
return QFunctionPointer(GetProcAddress(m_handle, (const wchar_t*)QString::fromLatin1(symbol).utf16()));
|
||||
#else
|
||||
return (void*)GetProcAddress(m_handle, symbol);
|
||||
return QFunctionPointer(GetProcAddress(m_handle, symbol));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *resolve(const QString &libraryName, const char *symbol)
|
||||
static QFunctionPointer resolve(const QString &libraryName, const char *symbol)
|
||||
{
|
||||
return QSystemLibrary(libraryName).resolve(symbol);
|
||||
}
|
||||
|
@ -49,8 +49,25 @@
|
||||
#include "qthread.h"
|
||||
#include "qmutex_p.h"
|
||||
|
||||
#ifndef Q_OS_LINUX
|
||||
#include "private/qfreelist_p.h"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QBasicMutex
|
||||
\brief QMutex POD
|
||||
\internal
|
||||
|
||||
\ingroup thread
|
||||
|
||||
- Can be used as global static object.
|
||||
- Always non-recursive
|
||||
- Do not use tryLock with timeout > 0, else you can have a leak (see the ~QMutex destructor)
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\class QMutex
|
||||
\brief The QMutex class provides access serialization between threads.
|
||||
@ -122,8 +139,12 @@ QT_BEGIN_NAMESPACE
|
||||
\sa lock(), unlock()
|
||||
*/
|
||||
QMutex::QMutex(RecursionMode mode)
|
||||
: d(new QMutexPrivate(mode))
|
||||
{ }
|
||||
{
|
||||
if (mode == Recursive)
|
||||
d = new QRecursiveMutexPrivate;
|
||||
else
|
||||
d = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the mutex.
|
||||
@ -131,9 +152,18 @@ QMutex::QMutex(RecursionMode mode)
|
||||
\warning Destroying a locked mutex may result in undefined behavior.
|
||||
*/
|
||||
QMutex::~QMutex()
|
||||
{ delete static_cast<QMutexPrivate *>(d); }
|
||||
{
|
||||
if (isRecursive())
|
||||
delete static_cast<QRecursiveMutexPrivate *>(d._q_value);
|
||||
else if (d) {
|
||||
#ifndef Q_OS_LINUX
|
||||
if (d->possiblyUnlocked && tryLock()) { unlock(); return; }
|
||||
#endif
|
||||
qWarning("QMutex: destroying locked mutex");
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
/*! \fn void QMutex::lock()
|
||||
Locks the mutex. If another thread has locked the mutex then this
|
||||
call will block until that thread has unlocked it.
|
||||
|
||||
@ -145,40 +175,8 @@ QMutex::~QMutex()
|
||||
|
||||
\sa unlock()
|
||||
*/
|
||||
void QMutex::lock()
|
||||
{
|
||||
QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
|
||||
Qt::HANDLE self;
|
||||
|
||||
if (d->recursive) {
|
||||
self = QThread::currentThreadId();
|
||||
if (d->owner == self) {
|
||||
++d->count;
|
||||
Q_ASSERT_X(d->count != 0, "QMutex::lock", "Overflow in recursion counter");
|
||||
return;
|
||||
}
|
||||
|
||||
bool isLocked = d->contenders.testAndSetAcquire(0, 1);
|
||||
if (!isLocked) {
|
||||
// didn't get the lock, wait for it
|
||||
isLocked = d->wait();
|
||||
Q_ASSERT_X(isLocked, "QMutex::lock",
|
||||
"Internal error, infinite wait has timed out.");
|
||||
}
|
||||
|
||||
d->owner = self;
|
||||
++d->count;
|
||||
Q_ASSERT_X(d->count != 0, "QMutex::lock", "Overflow in recursion counter");
|
||||
return;
|
||||
}
|
||||
|
||||
bool isLocked = d->contenders.testAndSetAcquire(0, 1);
|
||||
if (!isLocked) {
|
||||
lockInternal();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
/*!\fn bool QMutex::trylock()
|
||||
Attempts to lock the mutex. If the lock was obtained, this function
|
||||
returns true. If another thread has locked the mutex, this
|
||||
function returns false immediately.
|
||||
@ -195,36 +193,9 @@ void QMutex::lock()
|
||||
|
||||
\sa lock(), unlock()
|
||||
*/
|
||||
bool QMutex::tryLock()
|
||||
{
|
||||
QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
|
||||
Qt::HANDLE self;
|
||||
|
||||
if (d->recursive) {
|
||||
self = QThread::currentThreadId();
|
||||
if (d->owner == self) {
|
||||
++d->count;
|
||||
Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isLocked = d->contenders.testAndSetAcquire(0, 1);
|
||||
if (!isLocked) {
|
||||
// some other thread has the mutex locked, or we tried to
|
||||
// recursively lock an non-recursive mutex
|
||||
return isLocked;
|
||||
}
|
||||
|
||||
d->owner = self;
|
||||
++d->count;
|
||||
Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
|
||||
return isLocked;
|
||||
}
|
||||
|
||||
return d->contenders.testAndSetAcquire(0, 1);
|
||||
}
|
||||
|
||||
/*! \overload
|
||||
/*! \fn bool QMutex::tryLock(int timeout)
|
||||
\overload
|
||||
|
||||
Attempts to lock the mutex. This function returns true if the lock
|
||||
was obtained; otherwise it returns false. If another thread has
|
||||
@ -247,81 +218,30 @@ bool QMutex::tryLock()
|
||||
|
||||
\sa lock(), unlock()
|
||||
*/
|
||||
bool QMutex::tryLock(int timeout)
|
||||
{
|
||||
QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
|
||||
Qt::HANDLE self;
|
||||
|
||||
if (d->recursive) {
|
||||
self = QThread::currentThreadId();
|
||||
if (d->owner == self) {
|
||||
++d->count;
|
||||
Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isLocked = d->contenders.testAndSetAcquire(0, 1);
|
||||
if (!isLocked) {
|
||||
// didn't get the lock, wait for it
|
||||
isLocked = d->wait(timeout);
|
||||
if (!isLocked)
|
||||
return false;
|
||||
}
|
||||
|
||||
d->owner = self;
|
||||
++d->count;
|
||||
Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
|
||||
return true;
|
||||
}
|
||||
|
||||
return (d->contenders.testAndSetAcquire(0, 1)
|
||||
// didn't get the lock, wait for it
|
||||
|| d->wait(timeout));
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
/*! \fn void QMutex::unlock()
|
||||
Unlocks the mutex. Attempting to unlock a mutex in a different
|
||||
thread to the one that locked it results in an error. Unlocking a
|
||||
mutex that is not locked results in undefined behavior.
|
||||
|
||||
\sa lock()
|
||||
*/
|
||||
void QMutex::unlock()
|
||||
{
|
||||
QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
|
||||
if (d->recursive) {
|
||||
if (!--d->count) {
|
||||
d->owner = 0;
|
||||
if (!d->contenders.testAndSetRelease(1, 0))
|
||||
d->wakeUp();
|
||||
}
|
||||
} else {
|
||||
if (!d->contenders.testAndSetRelease(1, 0))
|
||||
d->wakeUp();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn bool QMutex::locked()
|
||||
\fn void QMutex::isRecursive()
|
||||
\since 5.0
|
||||
|
||||
Returns true if the mutex is locked by another thread; otherwise
|
||||
returns false.
|
||||
Returns true if the mutex is recursive
|
||||
|
||||
It is generally a bad idea to use this function, because code
|
||||
that uses it has a race condition. Use tryLock() and unlock()
|
||||
instead.
|
||||
|
||||
\oldcode
|
||||
bool isLocked = mutex.locked();
|
||||
\newcode
|
||||
bool isLocked = true;
|
||||
if (mutex.tryLock()) {
|
||||
mutex.unlock();
|
||||
isLocked = false;
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
bool QBasicMutex::isRecursive() {
|
||||
QMutexPrivate *d = this->d;
|
||||
if (quintptr(d) <= 0x3)
|
||||
return false;
|
||||
return d->recursive;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\class QMutexLocker
|
||||
@ -418,96 +338,217 @@ void QMutex::unlock()
|
||||
\sa unlock()
|
||||
*/
|
||||
|
||||
#ifndef Q_OS_LINUX //linux implementation is in qmutex_linux.cpp
|
||||
/*!
|
||||
\fn QMutex::QMutex(bool recursive)
|
||||
|
||||
Use the constructor that takes a RecursionMode parameter instead.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal helper for lockInline()
|
||||
\internal helper for lock()
|
||||
*/
|
||||
void QMutex::lockInternal()
|
||||
bool QBasicMutex::lockInternal(int timeout)
|
||||
{
|
||||
QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
|
||||
while (!fastTryLock()) {
|
||||
QMutexPrivate *d = this->d;
|
||||
if (!d) // if d is 0, the mutex is unlocked
|
||||
continue;
|
||||
|
||||
if (QThread::idealThreadCount() == 1) {
|
||||
// don't spin on single cpu machines
|
||||
bool isLocked = d->wait();
|
||||
Q_ASSERT_X(isLocked, "QMutex::lock",
|
||||
"Internal error, infinite wait has timed out.");
|
||||
Q_UNUSED(isLocked);
|
||||
return;
|
||||
}
|
||||
|
||||
QElapsedTimer elapsedTimer;
|
||||
elapsedTimer.start();
|
||||
do {
|
||||
qint64 spinTime = elapsedTimer.nsecsElapsed();
|
||||
if (spinTime > d->maximumSpinTime) {
|
||||
// didn't get the lock, wait for it, since we're not going to gain anything by spinning more
|
||||
elapsedTimer.start();
|
||||
bool isLocked = d->wait();
|
||||
Q_ASSERT_X(isLocked, "QMutex::lock",
|
||||
"Internal error, infinite wait has timed out.");
|
||||
Q_UNUSED(isLocked);
|
||||
|
||||
qint64 maximumSpinTime = d->maximumSpinTime;
|
||||
qint64 averageWaitTime = d->averageWaitTime;
|
||||
qint64 actualWaitTime = elapsedTimer.nsecsElapsed();
|
||||
if (actualWaitTime < (QMutexPrivate::MaximumSpinTimeThreshold * 3 / 2)) {
|
||||
// measure the wait times
|
||||
averageWaitTime = d->averageWaitTime = qMin((averageWaitTime + actualWaitTime) / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
|
||||
if (d == dummyLocked()) {
|
||||
if (timeout == 0)
|
||||
return false;
|
||||
QMutexPrivate *newD = QMutexPrivate::allocate();
|
||||
if (!this->d.testAndSetOrdered(d, newD)) {
|
||||
//Either the mutex is already unlocked, or another thread already set it.
|
||||
newD->deref();
|
||||
continue;
|
||||
}
|
||||
|
||||
// adjust the spin count when spinning does not benefit contention performance
|
||||
if ((spinTime + actualWaitTime) - qint64(QMutexPrivate::MaximumSpinTimeThreshold) >= qint64(QMutexPrivate::MaximumSpinTimeThreshold)) {
|
||||
// long waits, stop spinning
|
||||
d->maximumSpinTime = 0;
|
||||
} else {
|
||||
// allow spinning if wait times decrease, but never spin more than the average wait time (otherwise we may perform worse)
|
||||
d->maximumSpinTime = qBound(qint64(averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
|
||||
}
|
||||
return;
|
||||
d = newD;
|
||||
//the d->refCount is already 1 the deref will occurs when we unlock
|
||||
} else if (d->recursive) {
|
||||
return static_cast<QRecursiveMutexPrivate *>(d)->lock(timeout);
|
||||
}
|
||||
// be a good citizen... yielding lets something else run if there is something to run, but may also relieve memory pressure if not
|
||||
QThread::yieldCurrentThread();
|
||||
} while (d->contenders != 0 || !d->contenders.testAndSetAcquire(0, 1));
|
||||
|
||||
// spinning is working, do not change the spin time (unless we are using much less time than allowed to spin)
|
||||
qint64 maximumSpinTime = d->maximumSpinTime;
|
||||
qint64 spinTime = elapsedTimer.nsecsElapsed();
|
||||
if (spinTime < maximumSpinTime / 2) {
|
||||
// we are using much less time than we need, adjust the limit
|
||||
d->maximumSpinTime = qBound(qint64(d->averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
|
||||
if (timeout == 0 && !d->possiblyUnlocked)
|
||||
return false;
|
||||
|
||||
if (!d->ref())
|
||||
continue; //that QMutexPrivate was already released
|
||||
|
||||
if (d != this->d) {
|
||||
//Either the mutex is already unlocked, or relocked with another mutex
|
||||
d->deref();
|
||||
continue;
|
||||
}
|
||||
|
||||
int old_waiters;
|
||||
do {
|
||||
old_waiters = d->waiters;
|
||||
if (old_waiters == -QMutexPrivate::BigNumber) {
|
||||
// we are unlocking, and the thread that unlocks is about to change d to 0
|
||||
// we try to aquire the mutex by changing to dummyLocked()
|
||||
if (this->d.testAndSetAcquire(d, dummyLocked())) {
|
||||
// Mutex aquired
|
||||
Q_ASSERT(d->waiters == -QMutexPrivate::BigNumber || d->waiters == 0);
|
||||
d->waiters = 0;
|
||||
d->deref();
|
||||
return true;
|
||||
} else {
|
||||
Q_ASSERT(d != this->d); //else testAndSetAcquire should have succeeded
|
||||
// Mutex is likely to bo 0, we should continue the outer-loop,
|
||||
// set old_waiters to the magic value of BigNumber
|
||||
old_waiters = QMutexPrivate::BigNumber;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!d->waiters.testAndSetRelaxed(old_waiters, old_waiters + 1));
|
||||
|
||||
if (d != this->d) {
|
||||
// Mutex was unlocked.
|
||||
if (old_waiters != QMutexPrivate::BigNumber) {
|
||||
//we did not break the previous loop
|
||||
Q_ASSERT(d->waiters >= 1);
|
||||
d->waiters.deref();
|
||||
}
|
||||
d->deref();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (d->wait(timeout)) {
|
||||
if (d->possiblyUnlocked && d->possiblyUnlocked.testAndSetRelaxed(true, false))
|
||||
d->deref();
|
||||
d->derefWaiters(1);
|
||||
//we got the lock. (do not deref)
|
||||
Q_ASSERT(d == this->d);
|
||||
return true;
|
||||
} else {
|
||||
Q_ASSERT(timeout >= 0);
|
||||
//timeout
|
||||
d->derefWaiters(1);
|
||||
//There may be a race in which the mutex is unlocked right after we timed out,
|
||||
// and before we deref the waiters, so maybe the mutex is actually unlocked.
|
||||
if (!d->possiblyUnlocked.testAndSetRelaxed(false, true))
|
||||
d->deref();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Q_ASSERT(this->d);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QMutex::unlockInternal()
|
||||
void QBasicMutex::unlockInternal()
|
||||
{
|
||||
static_cast<QMutexPrivate *>(d)->wakeUp();
|
||||
QMutexPrivate *d = this->d;
|
||||
Q_ASSERT(d); //we must be locked
|
||||
Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
|
||||
|
||||
if (d->recursive) {
|
||||
static_cast<QRecursiveMutexPrivate *>(d)->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->waiters.fetchAndAddRelease(-QMutexPrivate::BigNumber) == 0) {
|
||||
//there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0)
|
||||
if (this->d.testAndSetRelease(d, 0)) {
|
||||
if (d->possiblyUnlocked && d->possiblyUnlocked.testAndSetRelaxed(true, false))
|
||||
d->deref();
|
||||
}
|
||||
d->derefWaiters(0);
|
||||
} else {
|
||||
d->derefWaiters(0);
|
||||
//there are thread waiting, transfer the lock.
|
||||
d->wakeUp();
|
||||
}
|
||||
d->deref();
|
||||
}
|
||||
|
||||
//The freelist managment
|
||||
namespace {
|
||||
struct FreeListConstants : QFreeListDefaultConstants {
|
||||
enum { BlockCount = 4, MaxIndex=0xffff };
|
||||
static const int Sizes[BlockCount];
|
||||
};
|
||||
const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
|
||||
16,
|
||||
128,
|
||||
1024,
|
||||
FreeListConstants::MaxIndex - (16-128-1024)
|
||||
};
|
||||
|
||||
typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList;
|
||||
Q_GLOBAL_STATIC(FreeList, freelist);
|
||||
}
|
||||
|
||||
QMutexPrivate *QMutexPrivate::allocate()
|
||||
{
|
||||
int i = freelist()->next();
|
||||
QMutexPrivate *d = &(*freelist())[i];
|
||||
d->id = i;
|
||||
Q_ASSERT(d->refCount == 0);
|
||||
Q_ASSERT(!d->recursive);
|
||||
Q_ASSERT(!d->possiblyUnlocked);
|
||||
Q_ASSERT(d->waiters == 0);
|
||||
d->refCount = 1;
|
||||
return d;
|
||||
}
|
||||
|
||||
void QMutexPrivate::release()
|
||||
{
|
||||
Q_ASSERT(!recursive);
|
||||
Q_ASSERT(refCount == 0);
|
||||
Q_ASSERT(!possiblyUnlocked);
|
||||
Q_ASSERT(waiters == 0);
|
||||
freelist()->release(id);
|
||||
}
|
||||
|
||||
// atomically substract "value" to the waiters, and remove the QMutexPrivate::BigNumber flag
|
||||
void QMutexPrivate::derefWaiters(int value)
|
||||
{
|
||||
int old_waiters;
|
||||
int new_waiters;
|
||||
do {
|
||||
old_waiters = waiters;
|
||||
new_waiters = old_waiters;
|
||||
if (new_waiters < 0) {
|
||||
new_waiters += QMutexPrivate::BigNumber;
|
||||
}
|
||||
new_waiters -= value;
|
||||
} while (!waiters.testAndSetRelaxed(old_waiters, new_waiters));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QRecursiveMutexPrivate::lock(int timeout) {
|
||||
Qt::HANDLE self = QThread::currentThreadId();
|
||||
if (owner == self) {
|
||||
++count;
|
||||
Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
|
||||
return true;
|
||||
}
|
||||
bool success = true;
|
||||
if (timeout == -1) {
|
||||
mutex.lock();
|
||||
} else {
|
||||
success = mutex.tryLock(timeout);
|
||||
}
|
||||
|
||||
if (success)
|
||||
owner = self;
|
||||
return success;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QMutex::lockInline()
|
||||
\internal
|
||||
inline version of QMutex::lock()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QMutex::unlockInline()
|
||||
\internal
|
||||
inline version of QMutex::unlock()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QMutex::tryLockInline()
|
||||
\internal
|
||||
inline version of QMutex::tryLock()
|
||||
*/
|
||||
*/
|
||||
void QRecursiveMutexPrivate::unlock()
|
||||
{
|
||||
if (count > 0) {
|
||||
count--;
|
||||
} else {
|
||||
owner = 0;
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -52,47 +52,64 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
QT_MODULE(Core)
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
#if !defined(QT_NO_THREAD) && !defined(qdoc)
|
||||
|
||||
class QAtomicInt;
|
||||
class QMutexData;
|
||||
class QMutexPrivate;
|
||||
|
||||
class Q_CORE_EXPORT QMutex
|
||||
class Q_CORE_EXPORT QBasicMutex
|
||||
{
|
||||
friend class QWaitCondition;
|
||||
friend class QWaitConditionPrivate;
|
||||
|
||||
public:
|
||||
enum RecursionMode { NonRecursive, Recursive };
|
||||
inline void lock() {
|
||||
if (!fastTryLock())
|
||||
lockInternal();
|
||||
}
|
||||
|
||||
explicit QMutex(RecursionMode mode = NonRecursive);
|
||||
~QMutex();
|
||||
inline void unlock() {
|
||||
Q_ASSERT(d); //mutex must be locked
|
||||
if (!d.testAndSetRelease(dummyLocked(), 0))
|
||||
unlockInternal();
|
||||
}
|
||||
|
||||
void lock(); //### Qt5: make inline;
|
||||
inline void lockInline();
|
||||
bool tryLock(); //### Qt5: make inline;
|
||||
bool tryLock(int timeout);
|
||||
inline bool tryLockInline();
|
||||
void unlock(); //### Qt5: make inline;
|
||||
inline void unlockInline();
|
||||
bool tryLock(int timeout = 0) {
|
||||
return fastTryLock() || lockInternal(timeout);
|
||||
}
|
||||
|
||||
bool isRecursive();
|
||||
|
||||
private:
|
||||
void lockInternal();
|
||||
inline bool fastTryLock() {
|
||||
return d.testAndSetAcquire(0, dummyLocked());
|
||||
}
|
||||
bool lockInternal(int timeout = -1);
|
||||
void unlockInternal();
|
||||
Q_DISABLE_COPY(QMutex)
|
||||
|
||||
QMutexData *d;
|
||||
QBasicAtomicPointer<QMutexPrivate> d;
|
||||
static inline QMutexPrivate *dummyLocked() {
|
||||
return reinterpret_cast<QMutexPrivate *>(quintptr(1));
|
||||
}
|
||||
|
||||
friend class QMutex;
|
||||
friend class QMutexPrivate;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QMutex : public QBasicMutex {
|
||||
public:
|
||||
enum RecursionMode { NonRecursive, Recursive };
|
||||
explicit QMutex(RecursionMode mode = NonRecursive);
|
||||
~QMutex();
|
||||
private:
|
||||
Q_DISABLE_COPY(QMutex)
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QMutexLocker
|
||||
{
|
||||
public:
|
||||
inline explicit QMutexLocker(QMutex *m)
|
||||
inline explicit QMutexLocker(QBasicMutex *m)
|
||||
{
|
||||
Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0),
|
||||
"QMutexLocker", "QMutex pointer is misaligned");
|
||||
if (m) {
|
||||
m->lockInline();
|
||||
m->lock();
|
||||
val = reinterpret_cast<quintptr>(m) | quintptr(1u);
|
||||
} else {
|
||||
val = 0;
|
||||
@ -104,7 +121,7 @@ public:
|
||||
{
|
||||
if ((val & quintptr(1u)) == quintptr(1u)) {
|
||||
val &= ~quintptr(1u);
|
||||
mutex()->unlockInline();
|
||||
mutex()->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +129,7 @@ public:
|
||||
{
|
||||
if (val) {
|
||||
if ((val & quintptr(1u)) == quintptr(0u)) {
|
||||
mutex()->lockInline();
|
||||
mutex()->lock();
|
||||
val |= quintptr(1u);
|
||||
}
|
||||
}
|
||||
@ -138,54 +155,9 @@ private:
|
||||
quintptr val;
|
||||
};
|
||||
|
||||
class QMutexData
|
||||
{
|
||||
public:
|
||||
QAtomicInt contenders;
|
||||
const uint recursive : 1;
|
||||
uint reserved : 31;
|
||||
protected:
|
||||
QMutexData(QMutex::RecursionMode mode);
|
||||
~QMutexData();
|
||||
};
|
||||
|
||||
#ifdef QT_NO_DEBUG
|
||||
inline void QMutex::unlockInline()
|
||||
{
|
||||
if (d->recursive) {
|
||||
unlock();
|
||||
} else if (!d->contenders.testAndSetRelease(1, 0)) {
|
||||
unlockInternal();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool QMutex::tryLockInline()
|
||||
{
|
||||
if (d->recursive) {
|
||||
return tryLock();
|
||||
} else {
|
||||
return d->contenders.testAndSetAcquire(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
inline void QMutex::lockInline()
|
||||
{
|
||||
if (d->recursive) {
|
||||
lock();
|
||||
} else if(!tryLockInline()) {
|
||||
lockInternal();
|
||||
}
|
||||
}
|
||||
#else // QT_NO_DEBUG
|
||||
//in debug we do not use inline calls in order to allow debugging tools
|
||||
// to hook the mutex locking functions.
|
||||
inline void QMutex::unlockInline() { unlock(); }
|
||||
inline bool QMutex::tryLockInline() { return tryLock(); }
|
||||
inline void QMutex::lockInline() { lock(); }
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
|
||||
#else // QT_NO_THREAD
|
||||
#else // QT_NO_THREAD or qdoc
|
||||
|
||||
|
||||
class Q_CORE_EXPORT QMutex
|
||||
@ -194,14 +166,11 @@ public:
|
||||
enum RecursionMode { NonRecursive, Recursive };
|
||||
|
||||
inline explicit QMutex(RecursionMode mode = NonRecursive) { Q_UNUSED(mode); }
|
||||
inline ~QMutex() {}
|
||||
|
||||
static inline void lock() {}
|
||||
static inline void lockInline() {}
|
||||
static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; }
|
||||
static inline bool tryLockInline() { return true; }
|
||||
static inline void unlock() {}
|
||||
static inline void unlockInline() {}
|
||||
static inline bool isRecursive() { return true; }
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QMutex)
|
||||
@ -221,7 +190,9 @@ private:
|
||||
Q_DISABLE_COPY(QMutexLocker)
|
||||
};
|
||||
|
||||
#endif // QT_NO_THREAD
|
||||
typedef QMutex QBasicMutex;
|
||||
|
||||
#endif // QT_NO_THREAD or qdoc
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
138
src/corelib/thread/qmutex_linux.cpp
Normal file
138
src/corelib/thread/qmutex_linux.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include "qmutex.h"
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
#include "qatomic.h"
|
||||
#include "qmutex_p.h"
|
||||
# include "qelapsedtimer.h"
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static inline int _q_futex(QMutexPrivate *volatile *addr, int op, int val, const struct timespec *timeout)
|
||||
{
|
||||
volatile int *int_addr = reinterpret_cast<volatile int *>(addr);
|
||||
#if Q_BYTE_ORDER == Q_BIG_ENDIAN && QT_POINTER_SIZE == 8
|
||||
int_addr++; //We want a pointer to the 32 least significant bit of QMutex::d
|
||||
#endif
|
||||
int *addr2 = 0;
|
||||
int val2 = 0;
|
||||
return syscall(SYS_futex, int_addr, op, val, timeout, addr2, val2);
|
||||
}
|
||||
|
||||
static inline QMutexPrivate *dummyFutexValue()
|
||||
{
|
||||
return reinterpret_cast<QMutexPrivate *>(quintptr(3));
|
||||
}
|
||||
|
||||
|
||||
QMutexPrivate::~QMutexPrivate() {}
|
||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
||||
: recursive(mode == QMutex::Recursive) {}
|
||||
|
||||
bool QBasicMutex::lockInternal(int timeout)
|
||||
{
|
||||
QElapsedTimer elapsedTimer;
|
||||
if (timeout >= 1)
|
||||
elapsedTimer.start();
|
||||
|
||||
while (!fastTryLock()) {
|
||||
QMutexPrivate *d = this->d;
|
||||
if (!d) // if d is 0, the mutex is unlocked
|
||||
continue;
|
||||
|
||||
if (quintptr(d) <= 0x3) { //d == dummyLocked() || d == dummyFutexValue()
|
||||
if (timeout == 0)
|
||||
return false;
|
||||
while (this->d.fetchAndStoreAcquire(dummyFutexValue()) != 0) {
|
||||
struct timespec ts, *pts = 0;
|
||||
if (timeout >= 1) {
|
||||
// recalculate the timeout
|
||||
qint64 xtimeout = timeout * 1000 * 1000;
|
||||
xtimeout -= elapsedTimer.nsecsElapsed();
|
||||
if (xtimeout <= 0) {
|
||||
// timer expired after we returned
|
||||
return false;
|
||||
}
|
||||
ts.tv_sec = xtimeout / Q_INT64_C(1000) / 1000 / 1000;
|
||||
ts.tv_nsec = xtimeout % (Q_INT64_C(1000) * 1000 * 1000);
|
||||
pts = &ts;
|
||||
}
|
||||
int r = _q_futex(&this->d._q_value, FUTEX_WAIT, quintptr(dummyFutexValue()), pts);
|
||||
if (r != 0 && errno == ETIMEDOUT)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Q_ASSERT(d->recursive);
|
||||
return static_cast<QRecursiveMutexPrivate *>(d)->lock(timeout);
|
||||
}
|
||||
Q_ASSERT(this->d);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QBasicMutex::unlockInternal()
|
||||
{
|
||||
QMutexPrivate *d = this->d;
|
||||
Q_ASSERT(d); //we must be locked
|
||||
Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
|
||||
|
||||
if (d == dummyFutexValue()) {
|
||||
this->d.fetchAndStoreRelease(0);
|
||||
_q_futex(&this->d._q_value, FUTEX_WAKE, 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
Q_ASSERT(d->recursive);
|
||||
static_cast<QRecursiveMutexPrivate *>(d)->unlock();
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_THREAD
|
96
src/corelib/thread/qmutex_mac.cpp
Normal file
96
src/corelib/thread/qmutex_mac.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include "qmutex.h"
|
||||
|
||||
#if !defined(QT_NO_THREAD)
|
||||
|
||||
#include "qmutex_p.h"
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/task.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
||||
: recursive(mode == QMutex::Recursive)
|
||||
{
|
||||
kern_return_t r = semaphore_create(mach_task_self(), &mach_semaphore, SYNC_POLICY_FIFO, 0);
|
||||
if (r != KERN_SUCCESS)
|
||||
qWarning("QMutex: failed to create semaphore, error %d", r);
|
||||
}
|
||||
|
||||
QMutexPrivate::~QMutexPrivate()
|
||||
{
|
||||
kern_return_t r = semaphore_destroy(mach_task_self(), mach_semaphore);
|
||||
if (r != KERN_SUCCESS)
|
||||
qWarning("QMutex: failed to destroy semaphore, error %d", r);
|
||||
}
|
||||
|
||||
bool QMutexPrivate::wait(int timeout)
|
||||
{
|
||||
kern_return_t r;
|
||||
if (timeout < 0) {
|
||||
do {
|
||||
r = semaphore_wait(mach_semaphore);
|
||||
} while (r == KERN_ABORTED);
|
||||
Q_ASSERT(r == KERN_SUCCESS);
|
||||
} else {
|
||||
mach_timespec_t ts;
|
||||
ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
|
||||
ts.tv_sec = (timeout / 1000);
|
||||
r = semaphore_timedwait(mach_semaphore, ts);
|
||||
}
|
||||
return (r == KERN_SUCCESS);
|
||||
}
|
||||
|
||||
void QMutexPrivate::wakeUp()
|
||||
{
|
||||
semaphore_signal(mach_semaphore);
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif //QT_NO_THREAD
|
@ -57,50 +57,80 @@
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qnamespace.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qatomic.h>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
# include <mach/semaphore.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_SYMBIAN)
|
||||
# include <e32std.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QMutexPrivate : public QMutexData {
|
||||
class QMutexPrivate {
|
||||
public:
|
||||
QMutexPrivate(QMutex::RecursionMode mode);
|
||||
~QMutexPrivate();
|
||||
QMutexPrivate(QMutex::RecursionMode mode = QMutex::NonRecursive);
|
||||
|
||||
bool wait(int timeout = -1);
|
||||
void wakeUp();
|
||||
|
||||
// 1ms = 1000000ns
|
||||
enum { MaximumSpinTimeThreshold = 1000000 };
|
||||
volatile qint64 maximumSpinTime;
|
||||
volatile qint64 averageWaitTime;
|
||||
Qt::HANDLE owner;
|
||||
uint count;
|
||||
#if !defined(Q_OS_LINUX)
|
||||
// Conrol the lifetime of the privates
|
||||
QAtomicInt refCount;
|
||||
int id;
|
||||
|
||||
bool ref() {
|
||||
Q_ASSERT(refCount >= 0);
|
||||
int c;
|
||||
do {
|
||||
c = refCount;
|
||||
if (c == 0)
|
||||
return false;
|
||||
} while (!refCount.testAndSetRelaxed(c, c + 1));
|
||||
Q_ASSERT(refCount >= 0);
|
||||
return true;
|
||||
}
|
||||
void deref() {
|
||||
Q_ASSERT(refCount >=0);
|
||||
if (!refCount.deref())
|
||||
release();
|
||||
Q_ASSERT(refCount >=0);
|
||||
}
|
||||
void release();
|
||||
static QMutexPrivate *allocate();
|
||||
|
||||
QAtomicInt waiters; //number of thread waiting
|
||||
QAtomicInt possiblyUnlocked; //bool saying that a timed wait timed out
|
||||
enum { BigNumber = 0x100000 }; //Must be bigger than the possible number of waiters (number of threads)
|
||||
void derefWaiters(int value);
|
||||
#endif
|
||||
|
||||
// handle recursive mutex
|
||||
bool recursive;
|
||||
|
||||
//platform specific stuff
|
||||
#if defined(Q_OS_MAC)
|
||||
semaphore_t mach_semaphore;
|
||||
#elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) && !defined(Q_OS_SYMBIAN)
|
||||
volatile bool wakeup;
|
||||
#elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
|
||||
bool wakeup;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
#elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
|
||||
HANDLE event;
|
||||
#elif defined(Q_OS_SYMBIAN)
|
||||
RSemaphore lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline QMutexData::QMutexData(QMutex::RecursionMode mode)
|
||||
: recursive(mode == QMutex::Recursive)
|
||||
{}
|
||||
class QRecursiveMutexPrivate : public QMutexPrivate
|
||||
{
|
||||
public:
|
||||
QRecursiveMutexPrivate()
|
||||
: QMutexPrivate(QMutex::Recursive), owner(0), count(0) {}
|
||||
Qt::HANDLE owner;
|
||||
uint count;
|
||||
QMutex mutex;
|
||||
|
||||
inline QMutexData::~QMutexData() {}
|
||||
bool lock(int timeout);
|
||||
void unlock();
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
@ -46,142 +46,35 @@
|
||||
#ifndef QT_NO_THREAD
|
||||
#include "qatomic.h"
|
||||
#include "qmutex_p.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(Q_OS_VXWORKS) && defined(wakeup)
|
||||
#undef wakeup
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
# include <mach/mach.h>
|
||||
# include <mach/task.h>
|
||||
#elif defined(Q_OS_LINUX)
|
||||
# include <linux/futex.h>
|
||||
# include <sys/syscall.h>
|
||||
# include <unistd.h>
|
||||
# include <QtCore/qelapsedtimer.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#if !defined(Q_OS_MAC) && !defined(Q_OS_LINUX)
|
||||
static void report_error(int code, const char *where, const char *what)
|
||||
{
|
||||
if (code != 0)
|
||||
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
||||
: QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
|
||||
: recursive(mode == QMutex::Recursive), wakeup(false)
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
kern_return_t r = semaphore_create(mach_task_self(), &mach_semaphore, SYNC_POLICY_FIFO, 0);
|
||||
if (r != KERN_SUCCESS)
|
||||
qWarning("QMutex: failed to create semaphore, error %d", r);
|
||||
#elif !defined(Q_OS_LINUX)
|
||||
wakeup = false;
|
||||
report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
|
||||
report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
|
||||
#endif
|
||||
}
|
||||
|
||||
QMutexPrivate::~QMutexPrivate()
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
kern_return_t r = semaphore_destroy(mach_task_self(), mach_semaphore);
|
||||
if (r != KERN_SUCCESS)
|
||||
qWarning("QMutex: failed to destroy semaphore, error %d", r);
|
||||
#elif !defined(Q_OS_LINUX)
|
||||
report_error(pthread_cond_destroy(&cond), "QMutex", "cv destroy");
|
||||
report_error(pthread_mutex_destroy(&mutex), "QMutex", "mutex destroy");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
|
||||
bool QMutexPrivate::wait(int timeout)
|
||||
{
|
||||
if (contenders.fetchAndAddAcquire(1) == 0) {
|
||||
// lock acquired without waiting
|
||||
return true;
|
||||
}
|
||||
kern_return_t r;
|
||||
if (timeout < 0) {
|
||||
do {
|
||||
r = semaphore_wait(mach_semaphore);
|
||||
} while (r == KERN_ABORTED);
|
||||
if (r != KERN_SUCCESS)
|
||||
qWarning("QMutex: infinite wait failed, error %d", r);
|
||||
} else {
|
||||
mach_timespec_t ts;
|
||||
ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
|
||||
ts.tv_sec = (timeout / 1000);
|
||||
r = semaphore_timedwait(mach_semaphore, ts);
|
||||
}
|
||||
contenders.deref();
|
||||
return r == KERN_SUCCESS;
|
||||
}
|
||||
|
||||
void QMutexPrivate::wakeUp()
|
||||
{
|
||||
semaphore_signal(mach_semaphore);
|
||||
}
|
||||
|
||||
#elif defined(Q_OS_LINUX)
|
||||
|
||||
static inline int _q_futex(volatile int *addr, int op, int val, const struct timespec *timeout, int *addr2, int val2)
|
||||
{
|
||||
return syscall(SYS_futex, addr, op, val, timeout, addr2, val2);
|
||||
}
|
||||
|
||||
bool QMutexPrivate::wait(int timeout)
|
||||
{
|
||||
struct timespec ts, *pts = 0;
|
||||
QElapsedTimer timer;
|
||||
if (timeout >= 0) {
|
||||
ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
|
||||
ts.tv_sec = (timeout / 1000);
|
||||
pts = &ts;
|
||||
timer.start();
|
||||
}
|
||||
while (contenders.fetchAndStoreAcquire(2) > 0) {
|
||||
int r = _q_futex(&contenders._q_value, FUTEX_WAIT, 2, pts, 0, 0);
|
||||
if (r != 0 && errno == ETIMEDOUT)
|
||||
return false;
|
||||
|
||||
if (pts) {
|
||||
// recalculate the timeout
|
||||
qint64 xtimeout = timeout * 1000 * 1000;
|
||||
xtimeout -= timer.nsecsElapsed();
|
||||
if (xtimeout < 0) {
|
||||
// timer expired after we returned
|
||||
return false;
|
||||
}
|
||||
|
||||
ts.tv_sec = timeout / Q_INT64_C(1000) / 1000 / 1000;
|
||||
ts.tv_nsec = timeout % (Q_INT64_C(1000) * 1000 * 1000);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void QMutexPrivate::wakeUp()
|
||||
{
|
||||
(void) contenders.fetchAndStoreRelease(0);
|
||||
(void) _q_futex(&contenders._q_value, FUTEX_WAKE, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
#else // !Q_OS_MAC && !Q_OS_LINUX
|
||||
|
||||
bool QMutexPrivate::wait(int timeout)
|
||||
{
|
||||
if (contenders.fetchAndAddAcquire(1) == 0) {
|
||||
// lock acquired without waiting
|
||||
return true;
|
||||
}
|
||||
report_error(pthread_mutex_lock(&mutex), "QMutex::lock", "mutex lock");
|
||||
int errorCode = 0;
|
||||
while (!wakeup) {
|
||||
@ -190,12 +83,10 @@ bool QMutexPrivate::wait(int timeout)
|
||||
} else {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
|
||||
timespec ti;
|
||||
ti.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000) * 1000;
|
||||
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
||||
ti.tv_nsec %= 1000000000;
|
||||
|
||||
errorCode = pthread_cond_timedwait(&cond, &mutex, &ti);
|
||||
}
|
||||
if (errorCode) {
|
||||
@ -207,10 +98,10 @@ bool QMutexPrivate::wait(int timeout)
|
||||
report_error(errorCode, "QMutex::lock()", "cv wait");
|
||||
}
|
||||
}
|
||||
bool ret = wakeup;
|
||||
wakeup = false;
|
||||
report_error(pthread_mutex_unlock(&mutex), "QMutex::lock", "mutex unlock");
|
||||
contenders.deref();
|
||||
return errorCode == 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void QMutexPrivate::wakeUp()
|
||||
@ -221,7 +112,6 @@ void QMutexPrivate::wakeUp()
|
||||
report_error(pthread_mutex_unlock(&mutex), "QMutex::unlock", "mutex unlock");
|
||||
}
|
||||
|
||||
#endif // !Q_OS_MAC && !Q_OS_LINUX
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
||||
: QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
|
||||
: recursive(mode)
|
||||
{
|
||||
event = CreateEvent(0, FALSE, FALSE, 0);
|
||||
if (!event)
|
||||
@ -60,13 +60,7 @@ QMutexPrivate::~QMutexPrivate()
|
||||
|
||||
bool QMutexPrivate::wait(int timeout)
|
||||
{
|
||||
if (contenders.fetchAndAddAcquire(1) == 0) {
|
||||
// lock acquired without waiting
|
||||
return true;
|
||||
}
|
||||
bool returnValue = (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
|
||||
contenders.deref();
|
||||
return returnValue;
|
||||
return (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
void QMutexPrivate::wakeUp()
|
||||
|
@ -79,8 +79,8 @@ public:
|
||||
void relock()
|
||||
{
|
||||
if (!locked) {
|
||||
if (mtx1) mtx1->lockInline();
|
||||
if (mtx2) mtx2->lockInline();
|
||||
if (mtx1) mtx1->lock();
|
||||
if (mtx2) mtx2->lock();
|
||||
locked = true;
|
||||
}
|
||||
}
|
||||
@ -88,8 +88,8 @@ public:
|
||||
void unlock()
|
||||
{
|
||||
if (locked) {
|
||||
if (mtx1) mtx1->unlockInline();
|
||||
if (mtx2) mtx2->unlockInline();
|
||||
if (mtx1) mtx1->unlock();
|
||||
if (mtx2) mtx2->unlock();
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
@ -100,10 +100,10 @@ public:
|
||||
if (mtx1 == mtx2)
|
||||
return false;
|
||||
if (mtx1 < mtx2) {
|
||||
mtx2->lockInline();
|
||||
mtx2->lock();
|
||||
return true;
|
||||
}
|
||||
if (!mtx2->tryLockInline()) {
|
||||
if (!mtx2->tryLock()) {
|
||||
mtx1->unlock();
|
||||
mtx2->lock();
|
||||
mtx1->lock();
|
||||
|
@ -146,7 +146,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
|
||||
{
|
||||
if (! mutex)
|
||||
return false;
|
||||
if (mutex->d->recursive) {
|
||||
if (mutex->isRecursive()) {
|
||||
qWarning("QWaitCondition: cannot wait on recursive mutexes");
|
||||
return false;
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
|
||||
{
|
||||
if (!mutex)
|
||||
return false;
|
||||
if (mutex->d->recursive) {
|
||||
if (mutex->isRecursive()) {
|
||||
qWarning("QWaitCondition::wait: Cannot wait on recursive mutexes");
|
||||
return false;
|
||||
}
|
||||
|
@ -24,8 +24,7 @@ SOURCES += thread/qatomic.cpp \
|
||||
thread/qthread.cpp \
|
||||
thread/qthreadstorage.cpp
|
||||
|
||||
unix:!symbian:SOURCES += thread/qmutex_unix.cpp \
|
||||
thread/qthread_unix.cpp \
|
||||
unix:!symbian:SOURCES += thread/qthread_unix.cpp \
|
||||
thread/qwaitcondition_unix.cpp
|
||||
|
||||
symbian:SOURCES += thread/qmutex_symbian.cpp \
|
||||
@ -39,3 +38,9 @@ win32:SOURCES += thread/qmutex_win.cpp \
|
||||
integrity:SOURCES += thread/qmutex_unix.cpp \
|
||||
thread/qthread_unix.cpp \
|
||||
thread/qwaitcondition_unix.cpp
|
||||
|
||||
unix: {
|
||||
macx-* { SOURCES += thread/qmutex_mac.cpp }
|
||||
else:linux-* { SOURCES += thread/qmutex_linux.cpp }
|
||||
else { SOURCES += thread/qmutex_unix.cpp }
|
||||
}
|
||||
|
@ -904,7 +904,7 @@ QByteArray &QByteArray::operator=(const char *str)
|
||||
x = const_cast<Data *>(&shared_empty.ba);
|
||||
} else {
|
||||
int len = qstrlen(str);
|
||||
if (d->ref != 1 || len > d->alloc || (len < d->size && len < d->alloc >> 1))
|
||||
if (d->ref != 1 || len > int(d->alloc) || (len < d->size && len < int(d->alloc) >> 1))
|
||||
realloc(len);
|
||||
x = d;
|
||||
memcpy(x->data(), str, len + 1); // include null terminator
|
||||
@ -1432,9 +1432,10 @@ void QByteArray::resize(int size)
|
||||
x->data()[size] = '\0';
|
||||
d = x;
|
||||
} else {
|
||||
if (d->ref != 1 || size > d->alloc || (!d->capacityReserved && size < d->size && size < d->alloc >> 1))
|
||||
if (d->ref != 1 || size > int(d->alloc)
|
||||
|| (!d->capacityReserved && size < d->size && size < int(d->alloc) >> 1))
|
||||
realloc(qAllocMore(size, sizeof(Data)));
|
||||
if (d->alloc >= size) {
|
||||
if (int(d->alloc) >= size) {
|
||||
d->size = size;
|
||||
d->data()[size] = '\0';
|
||||
}
|
||||
@ -1563,7 +1564,7 @@ QByteArray &QByteArray::prepend(const char *str)
|
||||
QByteArray &QByteArray::prepend(const char *str, int len)
|
||||
{
|
||||
if (str) {
|
||||
if (d->ref != 1 || d->size + len > d->alloc)
|
||||
if (d->ref != 1 || d->size + len > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + len, sizeof(Data)));
|
||||
memmove(d->data()+len, d->data(), d->size);
|
||||
memcpy(d->data(), str, len);
|
||||
@ -1581,7 +1582,7 @@ QByteArray &QByteArray::prepend(const char *str, int len)
|
||||
|
||||
QByteArray &QByteArray::prepend(char ch)
|
||||
{
|
||||
if (d->ref != 1 || d->size + 1 > d->alloc)
|
||||
if (d->ref != 1 || d->size + 1 > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + 1, sizeof(Data)));
|
||||
memmove(d->data()+1, d->data(), d->size);
|
||||
d->data()[0] = ch;
|
||||
@ -1619,7 +1620,7 @@ QByteArray &QByteArray::append(const QByteArray &ba)
|
||||
if ((d == &shared_null.ba || d == &shared_empty.ba) && !IS_RAW_DATA(ba.d)) {
|
||||
*this = ba;
|
||||
} else if (ba.d != &shared_null.ba) {
|
||||
if (d->ref != 1 || d->size + ba.d->size > d->alloc)
|
||||
if (d->ref != 1 || d->size + ba.d->size > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
|
||||
memcpy(d->data() + d->size, ba.d->data(), ba.d->size);
|
||||
d->size += ba.d->size;
|
||||
@ -1653,7 +1654,7 @@ QByteArray& QByteArray::append(const char *str)
|
||||
{
|
||||
if (str) {
|
||||
int len = qstrlen(str);
|
||||
if (d->ref != 1 || d->size + len > d->alloc)
|
||||
if (d->ref != 1 || d->size + len > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + len, sizeof(Data)));
|
||||
memcpy(d->data() + d->size, str, len + 1); // include null terminator
|
||||
d->size += len;
|
||||
@ -1678,7 +1679,7 @@ QByteArray &QByteArray::append(const char *str, int len)
|
||||
if (len < 0)
|
||||
len = qstrlen(str);
|
||||
if (str && len) {
|
||||
if (d->ref != 1 || d->size + len > d->alloc)
|
||||
if (d->ref != 1 || d->size + len > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + len, sizeof(Data)));
|
||||
memcpy(d->data() + d->size, str, len); // include null terminator
|
||||
d->size += len;
|
||||
@ -1695,7 +1696,7 @@ QByteArray &QByteArray::append(const char *str, int len)
|
||||
|
||||
QByteArray& QByteArray::append(char ch)
|
||||
{
|
||||
if (d->ref != 1 || d->size + 1 > d->alloc)
|
||||
if (d->ref != 1 || d->size + 1 > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + 1, sizeof(Data)));
|
||||
d->data()[d->size++] = ch;
|
||||
d->data()[d->size] = '\0';
|
||||
@ -2204,7 +2205,7 @@ QByteArray QByteArray::repeated(int times) const
|
||||
|
||||
QByteArray result;
|
||||
result.reserve(resultSize);
|
||||
if (result.d->alloc != resultSize)
|
||||
if (int(result.d->alloc) != resultSize)
|
||||
return QByteArray(); // not enough memory
|
||||
|
||||
memcpy(result.d->data(), d->data(), d->size);
|
||||
|
@ -133,10 +133,10 @@ struct QByteArrayData
|
||||
inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
|
||||
};
|
||||
|
||||
template<int n> struct QConstByteArrayData
|
||||
template<int N> struct QConstByteArrayData
|
||||
{
|
||||
const QByteArrayData ba;
|
||||
const char data[n];
|
||||
const char data[N + 1];
|
||||
};
|
||||
|
||||
template<int N> struct QConstByteArrayDataPtr
|
||||
@ -146,10 +146,10 @@ template<int N> struct QConstByteArrayDataPtr
|
||||
|
||||
|
||||
#if defined(Q_COMPILER_LAMBDA)
|
||||
# define QByteArrayLiteral(str) ([]() { \
|
||||
enum { Size = sizeof(str) }; \
|
||||
# define QByteArrayLiteral(str) ([]() -> QConstByteArrayDataPtr<sizeof(str) - 1> { \
|
||||
enum { Size = sizeof(str) - 1 }; \
|
||||
static const QConstByteArrayData<Size> qbytearray_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, str }; \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, str }; \
|
||||
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||
return holder; }())
|
||||
|
||||
@ -160,9 +160,9 @@ template<int N> struct QConstByteArrayDataPtr
|
||||
|
||||
# define QByteArrayLiteral(str) \
|
||||
__extension__ ({ \
|
||||
enum { Size = sizeof(str) }; \
|
||||
enum { Size = sizeof(str) - 1 }; \
|
||||
static const QConstByteArrayData<Size> qbytearray_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, str }; \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, str }; \
|
||||
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||
holder; })
|
||||
#endif
|
||||
@ -439,10 +439,10 @@ inline int QByteArray::capacity() const
|
||||
{ return d->alloc; }
|
||||
|
||||
inline void QByteArray::reserve(int asize)
|
||||
{ if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true; }
|
||||
{ if (d->ref != 1 || asize > int(d->alloc)) realloc(asize); d->capacityReserved = true; }
|
||||
|
||||
inline void QByteArray::squeeze()
|
||||
{ if (d->size < d->alloc) realloc(d->size); d->capacityReserved = false; }
|
||||
{ if (d->size < int(d->alloc)) realloc(d->size); d->capacityReserved = false; }
|
||||
|
||||
class Q_CORE_EXPORT QByteRef {
|
||||
QByteArray &a;
|
||||
|
@ -317,8 +317,6 @@ QT_BEGIN_NAMESPACE
|
||||
\value Vertical
|
||||
\value Wide
|
||||
|
||||
\omitvalue Single
|
||||
|
||||
\sa decomposition()
|
||||
*/
|
||||
|
||||
@ -382,12 +380,6 @@ QT_BEGIN_NAMESPACE
|
||||
\value ByteOrderSwapped
|
||||
\value ParagraphSeparator
|
||||
\value LineSeparator
|
||||
|
||||
\omitvalue null
|
||||
\omitvalue replacement
|
||||
\omitvalue byteOrderMark
|
||||
\omitvalue byteOrderSwapped
|
||||
\omitvalue nbsp
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -957,7 +949,7 @@ QString QChar::decomposition(uint ucs4)
|
||||
|
||||
/*!
|
||||
Returns the tag defining the composition of the character. Returns
|
||||
QChar::Single if no decomposition exists.
|
||||
QChar::NoDecomposition if no decomposition exists.
|
||||
*/
|
||||
QChar::Decomposition QChar::decompositionTag() const
|
||||
{
|
||||
@ -967,7 +959,7 @@ QChar::Decomposition QChar::decompositionTag() const
|
||||
/*!
|
||||
\overload
|
||||
Returns the tag defining the composition of the UCS-4-encoded character
|
||||
specified by \a ucs4. Returns QChar::Single if no decomposition exists.
|
||||
specified by \a ucs4. Returns QChar::NoDecomposition if no decomposition exists.
|
||||
*/
|
||||
QChar::Decomposition QChar::decompositionTag(uint ucs4)
|
||||
{
|
||||
@ -1232,7 +1224,6 @@ ushort QChar::toCaseFolded(ushort ucs2)
|
||||
return ucs2 + qGetProp(ucs2)->caseFoldDiff;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\fn char QChar::toLatin1() const
|
||||
|
||||
|
67
src/corelib/tools/qfreelist.cpp
Normal file
67
src/corelib/tools/qfreelist.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qfreelist_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// default sizes and offsets (no need to define these when customizing)
|
||||
enum {
|
||||
Offset0 = 0x00000000,
|
||||
Offset1 = 0x00008000,
|
||||
Offset2 = 0x00080000,
|
||||
Offset3 = 0x00800000,
|
||||
|
||||
Size0 = Offset1 - Offset0,
|
||||
Size1 = Offset2 - Offset1,
|
||||
Size2 = Offset3 - Offset2,
|
||||
Size3 = QFreeListDefaultConstants::MaxIndex - Offset3
|
||||
};
|
||||
|
||||
const int QFreeListDefaultConstants::Sizes[QFreeListDefaultConstants::BlockCount] = {
|
||||
Size0,
|
||||
Size1,
|
||||
Size2,
|
||||
Size3
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
294
src/corelib/tools/qfreelist_p.h
Normal file
294
src/corelib/tools/qfreelist_p.h
Normal file
@ -0,0 +1,294 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QFREELIST_P_H
|
||||
#define QFREELIST_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtCore/qatomic.h>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QT_MODULE(Core)
|
||||
|
||||
/*! \internal
|
||||
|
||||
Element in a QFreeList. ConstReferenceType and ReferenceType are used as
|
||||
the return values for QFreeList::at() and QFreeList::operator[](). Contains
|
||||
the real data storage (_t) and the id of the next free element (next).
|
||||
|
||||
Note: the t() functions should be used to access the data, not _t.
|
||||
*/
|
||||
template <typename T>
|
||||
struct QFreeListElement
|
||||
{
|
||||
typedef const T &ConstReferenceType;
|
||||
typedef T &ReferenceType;
|
||||
|
||||
T _t;
|
||||
int next;
|
||||
|
||||
inline ConstReferenceType t() const { return _t; }
|
||||
inline ReferenceType t() { return _t; }
|
||||
};
|
||||
|
||||
/*! \internal
|
||||
|
||||
Element in a QFreeList without a paylout. ConstReferenceType and
|
||||
ReferenceType are void, the t() functions return void and are empty.
|
||||
*/
|
||||
template <>
|
||||
struct QFreeListElement<void>
|
||||
{
|
||||
typedef void ConstReferenceType;
|
||||
typedef void ReferenceType;
|
||||
|
||||
int next;
|
||||
|
||||
inline void t() const { }
|
||||
inline void t() { }
|
||||
};
|
||||
|
||||
/*! \internal
|
||||
|
||||
Defines default constants used by QFreeList:
|
||||
|
||||
- The initial value returned by QFreeList::next() is zero.
|
||||
|
||||
- QFreeList allows for up to 16777216 elements in QFreeList and uses the top
|
||||
8 bits to store a serial counter for ABA protection.
|
||||
|
||||
- QFreeList will make a maximum of 4 allocations (blocks), with each
|
||||
successive block larger than the previous.
|
||||
|
||||
- Sizes static int[] array to define the size of each block.
|
||||
|
||||
It is possible to define your own constants struct/class and give this to
|
||||
QFreeList to customize/tune the behavior.
|
||||
*/
|
||||
struct Q_AUTOTEST_EXPORT QFreeListDefaultConstants
|
||||
{
|
||||
// used by QFreeList, make sure to define all of when customizing
|
||||
enum {
|
||||
InitialNextValue = 0,
|
||||
IndexMask = 0x00ffffff,
|
||||
SerialMask = ~IndexMask & ~0x80000000,
|
||||
SerialCounter = IndexMask + 1,
|
||||
MaxIndex = IndexMask,
|
||||
BlockCount = 4,
|
||||
};
|
||||
|
||||
static const int Sizes[BlockCount];
|
||||
};
|
||||
|
||||
/*! \internal
|
||||
|
||||
This is a generic implementation of a lock-free free list. Use next() to
|
||||
get the next free entry in the list, and release(id) when done with the id.
|
||||
|
||||
This version is templated and allows having a payload of type T which can
|
||||
be accessed using the id returned by next(). The payload is allocated and
|
||||
deallocated automatically by the free list, but *NOT* when calling
|
||||
next()/release(). Initialization should be done by code needing it after
|
||||
next() returns. Likewise, cleanup() should happen before calling release().
|
||||
It is possible to have use 'void' as the payload type, in which case the
|
||||
free list only contains indexes to the next free entry.
|
||||
|
||||
The ConstantsType type defaults to QFreeListDefaultConstants above. You can
|
||||
define your custom ConstantsType, see above for details on what needs to be
|
||||
available.
|
||||
*/
|
||||
template <typename T, typename ConstantsType = QFreeListDefaultConstants>
|
||||
class QFreeList
|
||||
{
|
||||
typedef T ValueType;
|
||||
typedef QFreeListElement<T> ElementType;
|
||||
typedef typename ElementType::ConstReferenceType ConstReferenceType;
|
||||
typedef typename ElementType::ReferenceType ReferenceType;
|
||||
|
||||
// return which block the index \a x falls in, and modify \a x to be the index into that block
|
||||
static inline int blockfor(int &x)
|
||||
{
|
||||
for (int i = 0; i < ConstantsType::BlockCount; ++i) {
|
||||
int size = ConstantsType::Sizes[i];
|
||||
if (x < size)
|
||||
return i;
|
||||
x -= size;
|
||||
}
|
||||
Q_ASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// allocate a block of the given \a size, initialized starting with the given \a offset
|
||||
static inline ElementType *allocate(int offset, int size)
|
||||
{
|
||||
// qDebug("QFreeList: allocating %d elements (%ld bytes) with offset %d", size, size * sizeof(ElementType), offset);
|
||||
ElementType *v = new ElementType[size];
|
||||
for (int i = 0; i < size; ++i)
|
||||
v[i].next = offset + i + 1;
|
||||
return v;
|
||||
}
|
||||
|
||||
// take the current serial number from \a o, increment it, and store it in \a n
|
||||
static inline int incrementserial(int o, int n)
|
||||
{
|
||||
return (n & ConstantsType::IndexMask) | ((o + ConstantsType::SerialCounter) & ConstantsType::SerialMask);
|
||||
}
|
||||
|
||||
// the blocks
|
||||
QAtomicPointer<ElementType> _v[ConstantsType::BlockCount];
|
||||
// the next free id
|
||||
QAtomicInt _next;
|
||||
|
||||
// QFreeList is not copyable
|
||||
Q_DISABLE_COPY(QFreeList)
|
||||
|
||||
public:
|
||||
inline QFreeList();
|
||||
inline ~QFreeList();
|
||||
|
||||
// returns the payload for the given index \a x
|
||||
inline ConstReferenceType at(int x) const;
|
||||
inline ReferenceType operator[](int x);
|
||||
|
||||
/*
|
||||
Return the next free id. Use this id to access the payload (see above).
|
||||
Call release(id) when done using the id.
|
||||
*/
|
||||
inline int next();
|
||||
inline void release(int id);
|
||||
};
|
||||
|
||||
template <typename T, typename ConstantsType>
|
||||
inline QFreeList<T, ConstantsType>::QFreeList()
|
||||
: _next(ConstantsType::InitialNextValue)
|
||||
{ }
|
||||
|
||||
template <typename T, typename ConstantsType>
|
||||
inline QFreeList<T, ConstantsType>::~QFreeList()
|
||||
{
|
||||
for (int i = 0; i < ConstantsType::BlockCount; ++i)
|
||||
delete [] static_cast<ElementType *>(_v[i]);
|
||||
}
|
||||
|
||||
template <typename T, typename ConstantsType>
|
||||
inline typename QFreeList<T, ConstantsType>::ConstReferenceType QFreeList<T, ConstantsType>::at(int x) const
|
||||
{
|
||||
const int block = blockfor(x);
|
||||
return _v[block][x].t();
|
||||
}
|
||||
|
||||
template <typename T, typename ConstantsType>
|
||||
inline typename QFreeList<T, ConstantsType>::ReferenceType QFreeList<T, ConstantsType>::operator[](int x)
|
||||
{
|
||||
const int block = blockfor(x);
|
||||
return _v[block][x].t();
|
||||
}
|
||||
|
||||
template <typename T, typename ConstantsType>
|
||||
inline int QFreeList<T, ConstantsType>::next()
|
||||
{
|
||||
int id, newid, at;
|
||||
ElementType *v;
|
||||
do {
|
||||
id = _next; // .loadAqcuire();
|
||||
|
||||
at = id & ConstantsType::IndexMask;
|
||||
const int block = blockfor(at);
|
||||
v = _v[block];
|
||||
|
||||
if (!v) {
|
||||
v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
|
||||
if (!_v[block].testAndSetRelease(0, v)) {
|
||||
// race with another thread lost
|
||||
delete [] v;
|
||||
v = _v[block];
|
||||
Q_ASSERT(v != 0);
|
||||
}
|
||||
}
|
||||
|
||||
newid = v[at].next | (id & ~ConstantsType::IndexMask);
|
||||
} while (!_next.testAndSetRelease(id, newid));
|
||||
// qDebug("QFreeList::next(): returning %d (_next now %d, serial %d)",
|
||||
// id & ConstantsType::IndexMask,
|
||||
// newid & ConstantsType::IndexMask,
|
||||
// (newid & ~ConstantsType::IndexMask) >> 24);
|
||||
return id & ConstantsType::IndexMask;
|
||||
}
|
||||
|
||||
template <typename T, typename ConstantsType>
|
||||
inline void QFreeList<T, ConstantsType>::release(int id)
|
||||
{
|
||||
int at = id & ConstantsType::IndexMask;
|
||||
const int block = blockfor(at);
|
||||
ElementType *v = _v[block];
|
||||
|
||||
int x, newid;
|
||||
do {
|
||||
x = _next; // .loadAcquire();
|
||||
v[at].next = x & ConstantsType::IndexMask;
|
||||
|
||||
newid = incrementserial(x, id);
|
||||
} while (!_next.testAndSetRelease(x, newid));
|
||||
// qDebug("QFreeList::release(%d): _next now %d (was %d), serial %d",
|
||||
// id & ConstantsType::IndexMask,
|
||||
// newid & ConstantsType::IndexMask,
|
||||
// x & ConstantsType::IndexMask,
|
||||
// (newid & ~ConstantsType::IndexMask) >> 24);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QT_END_HEADER
|
||||
|
||||
#endif // QFREELIST_P_H
|
@ -102,7 +102,7 @@ HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch)
|
||||
return QChar::mirroredChar(ch);
|
||||
}
|
||||
|
||||
void *HB_Library_Resolve(const char *library, int version, const char *symbol)
|
||||
void (*HB_Library_Resolve(const char *library, int version, const char *symbol))()
|
||||
{
|
||||
#ifdef QT_NO_LIBRARY
|
||||
return 0;
|
||||
|
@ -279,6 +279,9 @@ namespace std {
|
||||
QT_BEGIN_NAMESPACE
|
||||
#endif
|
||||
|
||||
template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE);
|
||||
template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QT_END_HEADER
|
||||
|
@ -1267,10 +1267,10 @@ void QString::resize(int size)
|
||||
QString::free(d);
|
||||
d = x;
|
||||
} else {
|
||||
if (d->ref != 1 || size > d->alloc ||
|
||||
(!d->capacityReserved && size < d->size && size < d->alloc >> 1))
|
||||
if (d->ref != 1 || size > int(d->alloc) ||
|
||||
(!d->capacityReserved && size < d->size && size < int(d->alloc) >> 1))
|
||||
realloc(grow(size));
|
||||
if (d->alloc >= size) {
|
||||
if (int(d->alloc) >= size) {
|
||||
d->size = size;
|
||||
d->data()[size] = '\0';
|
||||
}
|
||||
@ -1560,7 +1560,7 @@ QString &QString::append(const QString &str)
|
||||
if (d == &shared_null.str) {
|
||||
operator=(str);
|
||||
} else {
|
||||
if (d->ref != 1 || d->size + str.d->size > d->alloc)
|
||||
if (d->ref != 1 || d->size + str.d->size > int(d->alloc))
|
||||
realloc(grow(d->size + str.d->size));
|
||||
memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar));
|
||||
d->size += str.d->size;
|
||||
@ -1580,7 +1580,7 @@ QString &QString::append(const QLatin1String &str)
|
||||
const uchar *s = (const uchar *)str.latin1();
|
||||
if (s) {
|
||||
int len = qstrlen((char *)s);
|
||||
if (d->ref != 1 || d->size + len > d->alloc)
|
||||
if (d->ref != 1 || d->size + len > int(d->alloc))
|
||||
realloc(grow(d->size + len));
|
||||
ushort *i = d->data() + d->size;
|
||||
while ((*i++ = *s++))
|
||||
@ -1623,7 +1623,7 @@ QString &QString::append(const QLatin1String &str)
|
||||
*/
|
||||
QString &QString::append(QChar ch)
|
||||
{
|
||||
if (d->ref != 1 || d->size + 1 > d->alloc)
|
||||
if (d->ref != 1 || d->size + 1 > int(d->alloc))
|
||||
realloc(grow(d->size + 1));
|
||||
d->data()[d->size++] = ch.unicode();
|
||||
d->data()[d->size] = '\0';
|
||||
@ -3550,8 +3550,8 @@ static QByteArray toLatin1_helper(const QChar *data, int length)
|
||||
const __m128i questionMark = _mm_set1_epi16('?');
|
||||
// SSE has no compare instruction for unsigned comparison.
|
||||
// The variables must be shiffted + 0x8000 to be compared
|
||||
const __m128i signedBitOffset = _mm_set1_epi16(0x8000);
|
||||
const __m128i thresholdMask = _mm_set1_epi16(0xff + 0x8000);
|
||||
const __m128i signedBitOffset = _mm_set1_epi16(short(0x8000));
|
||||
const __m128i thresholdMask = _mm_set1_epi16(short(0xff + 0x8000));
|
||||
for (int i = 0; i < chunkCount; ++i) {
|
||||
__m128i chunk1 = _mm_loadu_si128((__m128i*)src); // load
|
||||
src += 8;
|
||||
@ -6152,7 +6152,7 @@ QString QString::repeated(int times) const
|
||||
|
||||
QString result;
|
||||
result.reserve(resultSize);
|
||||
if (result.d->alloc != resultSize)
|
||||
if (int(result.d->alloc) != resultSize)
|
||||
return QString(); // not enough memory
|
||||
|
||||
memcpy(result.d->data(), d->data(), d->size * sizeof(ushort));
|
||||
|
@ -97,36 +97,43 @@ template<int N> struct QConstStringDataPtr
|
||||
};
|
||||
|
||||
#if defined(Q_COMPILER_UNICODE_STRINGS)
|
||||
template<int n> struct QConstStringData
|
||||
template<int N> struct QConstStringData
|
||||
{
|
||||
const QStringData str;
|
||||
const char16_t data[n];
|
||||
const char16_t data[N + 1];
|
||||
};
|
||||
#define QT_QSTRING_UNICODE_MARKER u""
|
||||
|
||||
#define QT_UNICODE_LITERAL_II(str) u"" str
|
||||
|
||||
#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536)
|
||||
// wchar_t is 2 bytes
|
||||
template<int n> struct QConstStringData
|
||||
template<int N> struct QConstStringData
|
||||
{
|
||||
const QStringData str;
|
||||
const wchar_t data[n];
|
||||
const wchar_t data[N + 1];
|
||||
};
|
||||
#define QT_QSTRING_UNICODE_MARKER L""
|
||||
|
||||
#if defined(Q_CC_MSVC)
|
||||
# define QT_UNICODE_LITERAL_II(str) L##str
|
||||
#else
|
||||
# define QT_UNICODE_LITERAL_II(str) L"" str
|
||||
#endif
|
||||
|
||||
#else
|
||||
template<int n> struct QConstStringData
|
||||
template<int N> struct QConstStringData
|
||||
{
|
||||
const QStringData str;
|
||||
const ushort data[n];
|
||||
const ushort data[N + 1];
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(QT_QSTRING_UNICODE_MARKER)
|
||||
#if defined(QT_UNICODE_LITERAL_II)
|
||||
# define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str)
|
||||
# if defined(Q_COMPILER_LAMBDA)
|
||||
# define QStringLiteral(str) ([]() { \
|
||||
enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \
|
||||
# define QStringLiteral(str) ([]() -> QConstStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
|
||||
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||
static const QConstStringData<Size> qstring_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
|
||||
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||
return holder; }())
|
||||
|
||||
@ -137,9 +144,9 @@ template<int n> struct QConstStringData
|
||||
|
||||
# define QStringLiteral(str) \
|
||||
__extension__ ({ \
|
||||
enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \
|
||||
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||
static const QConstStringData<Size> qstring_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
|
||||
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||
holder; })
|
||||
# endif
|
||||
|
@ -108,13 +108,12 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
/*! \internal
|
||||
Note: The len contains the ending \0
|
||||
*/
|
||||
void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out)
|
||||
{
|
||||
#ifndef QT_NO_TEXTCODEC
|
||||
if (QString::codecForCStrings && len) {
|
||||
QString tmp = QString::fromAscii(a, len > 0 ? len - 1 : -1);
|
||||
QString tmp = QString::fromAscii(a, len > 0 ? len : -1);
|
||||
memcpy(out, reinterpret_cast<const char *>(tmp.constData()), sizeof(QChar) * tmp.size());
|
||||
out += tmp.length();
|
||||
return;
|
||||
@ -126,7 +125,7 @@ void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out
|
||||
while (*a)
|
||||
*out++ = QLatin1Char(*a++);
|
||||
} else {
|
||||
for (int i = 0; i < len - 1; ++i)
|
||||
for (int i = 0; i < len; ++i)
|
||||
*out++ = QLatin1Char(a[i]);
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
|
||||
#ifndef QT_NO_CAST_FROM_ASCII
|
||||
static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
|
||||
{
|
||||
QAbstractConcatenable::convertFromAscii(a, N, out);
|
||||
QAbstractConcatenable::convertFromAscii(a, N - 1, out);
|
||||
}
|
||||
#endif
|
||||
static inline void appendTo(const char a[N], char *&out)
|
||||
@ -313,7 +313,7 @@ template <int N> struct QConcatenable<const char[N]> : private QAbstractConcaten
|
||||
#ifndef QT_NO_CAST_FROM_ASCII
|
||||
static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
|
||||
{
|
||||
QAbstractConcatenable::convertFromAscii(a, N, out);
|
||||
QAbstractConcatenable::convertFromAscii(a, N - 1, out);
|
||||
}
|
||||
#endif
|
||||
static inline void appendTo(const char a[N], char *&out)
|
||||
@ -349,10 +349,9 @@ template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
|
||||
enum { ExactSize = false };
|
||||
static int size(const QByteArray &ba) { return ba.size(); }
|
||||
#ifndef QT_NO_CAST_FROM_ASCII
|
||||
static inline void appendTo(const QByteArray &ba, QChar *&out)
|
||||
static inline QT_ASCII_CAST_WARN void appendTo(const QByteArray &ba, QChar *&out)
|
||||
{
|
||||
// adding 1 because convertFromAscii expects the size including the null-termination
|
||||
QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size() + 1, out);
|
||||
QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size(), out);
|
||||
}
|
||||
#endif
|
||||
static inline void appendTo(const QByteArray &ba, char *&out)
|
||||
@ -364,6 +363,26 @@ template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
|
||||
}
|
||||
};
|
||||
|
||||
template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbstractConcatenable
|
||||
{
|
||||
typedef QConstByteArrayDataPtr<N> type;
|
||||
typedef QByteArray ConvertTo;
|
||||
enum { ExactSize = false };
|
||||
static int size(const type &) { return N; }
|
||||
#ifndef QT_NO_CAST_FROM_ASCII
|
||||
static inline QT_ASCII_CAST_WARN void appendTo(const type &a, QChar *&out)
|
||||
{
|
||||
QAbstractConcatenable::convertFromAscii(a.ptr->data, N, out);
|
||||
}
|
||||
#endif
|
||||
static inline void appendTo(const type &ba, char *&out)
|
||||
{
|
||||
const char *a = ba.ptr->data;
|
||||
while (*a)
|
||||
*out++ = *a++;
|
||||
}
|
||||
};
|
||||
|
||||
namespace QtStringBuilder {
|
||||
template <typename A, typename B> struct ConvertToTypeHelper
|
||||
{ typedef A ConvertTo; };
|
||||
|
@ -13,6 +13,7 @@ HEADERS += \
|
||||
tools/qdatetime.h \
|
||||
tools/qdatetime_p.h \
|
||||
tools/qeasingcurve.h \
|
||||
tools/qfreelist_p.h \
|
||||
tools/qhash.h \
|
||||
tools/qline.h \
|
||||
tools/qlinkedlist.h \
|
||||
@ -61,6 +62,7 @@ SOURCES += \
|
||||
tools/qdatetime.cpp \
|
||||
tools/qeasingcurve.cpp \
|
||||
tools/qelapsedtimer.cpp \
|
||||
tools/qfreelist.cpp \
|
||||
tools/qhash.cpp \
|
||||
tools/qline.cpp \
|
||||
tools/qlinkedlist.cpp \
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
void *qdbus_resolve_me(const char *name);
|
||||
void (*qdbus_resolve_me(const char *name))();
|
||||
|
||||
#if !defined QT_LINKED_LIBDBUS
|
||||
|
||||
@ -95,20 +95,19 @@ bool qdbus_loadLibDBus()
|
||||
return false;
|
||||
}
|
||||
|
||||
void *qdbus_resolve_conditionally(const char *name)
|
||||
void (*qdbus_resolve_conditionally(const char *name))()
|
||||
{
|
||||
if (qdbus_loadLibDBus())
|
||||
return qdbus_libdbus->resolve(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *qdbus_resolve_me(const char *name)
|
||||
void (*qdbus_resolve_me(const char *name))()
|
||||
{
|
||||
void *ptr = 0;
|
||||
if (!qdbus_loadLibDBus())
|
||||
qFatal("Cannot find libdbus-1 in your system to resolve symbol '%s'.", name);
|
||||
|
||||
ptr = qdbus_libdbus->resolve(name);
|
||||
QFunctionPointer ptr = qdbus_libdbus->resolve(name);
|
||||
if (!ptr)
|
||||
qFatal("Cannot resolve '%s' in your libdbus-1.", name);
|
||||
|
||||
|
@ -63,8 +63,8 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
#if !defined QT_LINKED_LIBDBUS
|
||||
|
||||
void *qdbus_resolve_conditionally(const char *name); // doesn't print a warning
|
||||
void *qdbus_resolve_me(const char *name); // prints a warning
|
||||
void (*qdbus_resolve_conditionally(const char *name))(); // doesn't print a warning
|
||||
void (*qdbus_resolve_me(const char *name))(); // prints a warning
|
||||
bool qdbus_loadLibDBus();
|
||||
|
||||
# define DEFINEFUNC(ret, func, args, argcall, funcret) \
|
||||
|
@ -125,6 +125,11 @@ private:
|
||||
MethodScriptable = 0x40
|
||||
};
|
||||
|
||||
enum MetaObjectFlags {
|
||||
DynamicMetaObject = 0x01,
|
||||
RequiresVariantMetaObject = 0x02
|
||||
};
|
||||
|
||||
QMap<QByteArray, Method> methods;
|
||||
QMap<QByteArray, Property> properties;
|
||||
|
||||
@ -152,6 +157,8 @@ struct QDBusMetaObjectPrivate
|
||||
int methodCount, methodData;
|
||||
int propertyCount, propertyData;
|
||||
int enumeratorCount, enumeratorData;
|
||||
int constructorCount, constructorData; // since revision 2
|
||||
int flags; // since revision 3
|
||||
|
||||
// this is specific for QDBusMetaObject:
|
||||
int propertyDBusData;
|
||||
@ -416,7 +423,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));
|
||||
|
||||
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
|
||||
header->revision = 1;
|
||||
header->revision = 3;
|
||||
header->className = 0;
|
||||
header->classInfoCount = 0;
|
||||
header->classInfoData = 0;
|
||||
@ -426,6 +433,9 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
header->propertyData = header->methodData + header->methodCount * 5;
|
||||
header->enumeratorCount = 0;
|
||||
header->enumeratorData = 0;
|
||||
header->constructorCount = 0;
|
||||
header->constructorData = 0;
|
||||
header->flags = RequiresVariantMetaObject;
|
||||
header->propertyDBusData = header->propertyData + header->propertyCount * 3;
|
||||
header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty;
|
||||
|
||||
|
@ -97,8 +97,10 @@ static QDataStream &operator<<(QDataStream &s, const BMP_FILEHDR &bf)
|
||||
|
||||
|
||||
const int BMP_OLD = 12; // old Windows/OS2 BMP size
|
||||
const int BMP_WIN = 40; // new Windows BMP size
|
||||
const int BMP_WIN = 40; // Windows BMP v3 size
|
||||
const int BMP_OS2 = 64; // new OS/2 BMP size
|
||||
const int BMP_WIN4 = 108; // Windows BMP v4 size
|
||||
const int BMP_WIN5 = 124; // Windows BMP v5 size
|
||||
|
||||
const int BMP_RGB = 0; // no compression
|
||||
const int BMP_RLE8 = 1; // run-length encoded, 8 bits
|
||||
@ -109,7 +111,7 @@ const int BMP_BITFIELDS = 3; // RGB values encoded in dat
|
||||
static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
|
||||
{
|
||||
s >> bi.biSize;
|
||||
if (bi.biSize == BMP_WIN || bi.biSize == BMP_OS2) {
|
||||
if (bi.biSize == BMP_WIN || bi.biSize == BMP_OS2 || bi.biSize == BMP_WIN4 || bi.biSize == BMP_WIN5) {
|
||||
s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount;
|
||||
s >> bi.biCompression >> bi.biSizeImage;
|
||||
s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter;
|
||||
@ -255,7 +257,57 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
|
||||
image.setDotsPerMeterY(bi.biYPelsPerMeter);
|
||||
|
||||
if (!d->isSequential())
|
||||
d->seek(startpos + BMP_FILEHDR_SIZE + bi.biSize); // goto start of colormap
|
||||
d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap
|
||||
|
||||
if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) {
|
||||
Q_ASSERT(ncols == 0);
|
||||
|
||||
if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
|
||||
return false;
|
||||
if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask))
|
||||
return false;
|
||||
if (d->read((char *)&blue_mask, sizeof(blue_mask)) != sizeof(blue_mask))
|
||||
return false;
|
||||
|
||||
// Read BMP v4+ header
|
||||
if (bi.biSize >= BMP_WIN4) {
|
||||
int alpha_mask = 0;
|
||||
int CSType = 0;
|
||||
int gamma_red = 0;
|
||||
int gamma_green = 0;
|
||||
int gamma_blue = 0;
|
||||
int endpoints[9];
|
||||
|
||||
if (d->read((char *)&alpha_mask, sizeof(alpha_mask)) != sizeof(alpha_mask))
|
||||
return false;
|
||||
if (d->read((char *)&CSType, sizeof(CSType)) != sizeof(CSType))
|
||||
return false;
|
||||
if (d->read((char *)&endpoints, sizeof(endpoints)) != sizeof(endpoints))
|
||||
return false;
|
||||
if (d->read((char *)&gamma_red, sizeof(gamma_red)) != sizeof(gamma_red))
|
||||
return false;
|
||||
if (d->read((char *)&gamma_green, sizeof(gamma_green)) != sizeof(gamma_green))
|
||||
return false;
|
||||
if (d->read((char *)&gamma_blue, sizeof(gamma_blue)) != sizeof(gamma_blue))
|
||||
return false;
|
||||
|
||||
if (bi.biSize == BMP_WIN5) {
|
||||
qint32 intent = 0;
|
||||
qint32 profileData = 0;
|
||||
qint32 profileSize = 0;
|
||||
qint32 reserved = 0;
|
||||
|
||||
if (d->read((char *)&intent, sizeof(intent)) != sizeof(intent))
|
||||
return false;
|
||||
if (d->read((char *)&profileData, sizeof(profileData)) != sizeof(profileData))
|
||||
return false;
|
||||
if (d->read((char *)&profileSize, sizeof(profileSize)) != sizeof(profileSize))
|
||||
return false;
|
||||
if (d->read((char *)&reserved, sizeof(reserved)) != sizeof(reserved) || reserved != 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ncols > 0) { // read color table
|
||||
uchar rgb[4];
|
||||
@ -268,12 +320,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
|
||||
return false;
|
||||
}
|
||||
} else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
|
||||
if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
|
||||
return false;
|
||||
if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask))
|
||||
return false;
|
||||
if (d->read((char *)&blue_mask, sizeof(blue_mask)) != sizeof(blue_mask))
|
||||
return false;
|
||||
red_shift = calc_shift(red_mask);
|
||||
red_scale = 256 / ((red_mask >> red_shift) + 1);
|
||||
green_shift = calc_shift(green_mask);
|
||||
|
@ -236,14 +236,14 @@ bool QTiffHandler::read(QImage *image)
|
||||
}
|
||||
} else {
|
||||
// create the color table
|
||||
uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
|
||||
uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
|
||||
uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
|
||||
if (!redTable || !greenTable || !blueTable) {
|
||||
uint16 *redTable = 0;
|
||||
uint16 *greenTable = 0;
|
||||
uint16 *blueTable = 0;
|
||||
if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
|
||||
TIFFClose(tiff);
|
||||
return false;
|
||||
}
|
||||
if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
|
||||
if (!redTable || !greenTable || !blueTable) {
|
||||
TIFFClose(tiff);
|
||||
return false;
|
||||
}
|
||||
@ -500,6 +500,9 @@ bool QTiffHandler::write(const QImage &image)
|
||||
uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
|
||||
uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
|
||||
if (!redTable || !greenTable || !blueTable) {
|
||||
qFree(redTable);
|
||||
qFree(greenTable);
|
||||
qFree(blueTable);
|
||||
TIFFClose(tiff);
|
||||
return false;
|
||||
}
|
||||
|
@ -55,6 +55,20 @@ QT_BEGIN_NAMESPACE
|
||||
\since 4.6
|
||||
\ingroup painting-3D
|
||||
|
||||
The QMatrix4x4 class in general is treated as a row-major matrix, in that the
|
||||
constructors and operator() functions take data in row-major format, as is
|
||||
familiar in C-style usage.
|
||||
|
||||
Internally the data is stored as column-major format, so as to be optimal for
|
||||
passing to OpenGL functions, which expect column-major data.
|
||||
|
||||
When using these functions be aware that they return data in \bold{column-major}
|
||||
format:
|
||||
\list
|
||||
\o data()
|
||||
\o constData()
|
||||
\endlist
|
||||
|
||||
\sa QVector3D, QGenericMatrix
|
||||
*/
|
||||
|
||||
@ -1725,6 +1739,7 @@ QRectF QMatrix4x4::mapRect(const QRectF& rect) const
|
||||
\fn const qreal *QMatrix4x4::data() const
|
||||
|
||||
Returns a constant pointer to the raw data of this matrix.
|
||||
This raw data is stored in column-major format.
|
||||
|
||||
\sa constData()
|
||||
*/
|
||||
@ -1733,6 +1748,7 @@ QRectF QMatrix4x4::mapRect(const QRectF& rect) const
|
||||
\fn const qreal *QMatrix4x4::constData() const
|
||||
|
||||
Returns a constant pointer to the raw data of this matrix.
|
||||
This raw data is stored in column-major format.
|
||||
|
||||
\sa data()
|
||||
*/
|
||||
|
@ -3005,7 +3005,7 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
|
||||
ensureState();
|
||||
|
||||
QFontEngine *fontEngine = textItem->fontEngine();
|
||||
if (!supportsTransformations(fontEngine)) {
|
||||
if (shouldDrawCachedGlyphs(fontEngine->fontDef.pixelSize, state()->matrix)) {
|
||||
drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
|
||||
fontEngine);
|
||||
} else {
|
||||
@ -3355,10 +3355,7 @@ bool QRasterPaintEngine::supportsTransformations(qreal pixelSize, const QTransfo
|
||||
#endif
|
||||
return true;
|
||||
|
||||
if (pixelSize * pixelSize * qAbs(m.determinant()) >= 64 * 64)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return !shouldDrawCachedGlyphs(pixelSize, m);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -53,6 +53,10 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#if !defined(QT_MAX_CACHED_GLYPH_SIZE)
|
||||
# define QT_MAX_CACHED_GLYPH_SIZE 64
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* class QVectorPath
|
||||
@ -1096,4 +1100,10 @@ bool QPaintEngineEx::supportsTransformations(qreal pixelSize, const QTransform &
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QPaintEngineEx::shouldDrawCachedGlyphs(qreal pixelSize, const QTransform &m) const
|
||||
{
|
||||
return (pixelSize * pixelSize * qAbs(m.determinant())) <
|
||||
QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -228,6 +228,7 @@ public:
|
||||
};
|
||||
virtual uint flags() const {return 0;}
|
||||
virtual bool supportsTransformations(qreal pixelSize, const QTransform &m) const;
|
||||
virtual bool shouldDrawCachedGlyphs(qreal pixelSize, const QTransform &m) const;
|
||||
|
||||
protected:
|
||||
QPaintEngineEx(QPaintEngineExPrivate &data);
|
||||
|
@ -155,6 +155,7 @@ public:
|
||||
struct FaceId {
|
||||
FaceId() : index(0), encoding(0) {}
|
||||
QByteArray filename;
|
||||
QByteArray uuid;
|
||||
int index;
|
||||
int encoding;
|
||||
};
|
||||
@ -303,7 +304,7 @@ inline bool operator ==(const QFontEngine::FaceId &f1, const QFontEngine::FaceId
|
||||
|
||||
inline uint qHash(const QFontEngine::FaceId &f)
|
||||
{
|
||||
return qHash((f.index << 16) + f.encoding) + qHash(f.filename);
|
||||
return qHash((f.index << 16) + f.encoding) + qHash(f.filename + f.uuid);
|
||||
}
|
||||
|
||||
|
||||
|
@ -139,7 +139,7 @@ QRawFont::QRawFont()
|
||||
\note The referenced file must contain a TrueType or OpenType font.
|
||||
*/
|
||||
QRawFont::QRawFont(const QString &fileName,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference)
|
||||
: d(new QRawFontPrivate)
|
||||
{
|
||||
@ -154,7 +154,7 @@ QRawFont::QRawFont(const QString &fileName,
|
||||
\note The data must contain a TrueType or OpenType font.
|
||||
*/
|
||||
QRawFont::QRawFont(const QByteArray &fontData,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference)
|
||||
: d(new QRawFontPrivate)
|
||||
{
|
||||
@ -204,7 +204,7 @@ bool QRawFont::isValid() const
|
||||
\sa loadFromData()
|
||||
*/
|
||||
void QRawFont::loadFromFile(const QString &fileName,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference)
|
||||
{
|
||||
QFile file(fileName);
|
||||
@ -222,7 +222,7 @@ void QRawFont::loadFromFile(const QString &fileName,
|
||||
\sa loadFromFile()
|
||||
*/
|
||||
void QRawFont::loadFromData(const QByteArray &fontData,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference)
|
||||
{
|
||||
detach();
|
||||
|
@ -70,10 +70,10 @@ public:
|
||||
|
||||
QRawFont();
|
||||
QRawFont(const QString &fileName,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
|
||||
QRawFont(const QByteArray &fontData,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
|
||||
QRawFont(const QRawFont &other);
|
||||
~QRawFont();
|
||||
@ -117,11 +117,11 @@ public:
|
||||
qreal unitsPerEm() const;
|
||||
|
||||
void loadFromFile(const QString &fileName,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference);
|
||||
|
||||
void loadFromData(const QByteArray &fontData,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference);
|
||||
|
||||
bool supportsCharacter(quint32 ucs4) const;
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
#include "qrawfont_p.h"
|
||||
#include "qfontengine_ft_p.h"
|
||||
#include "quuid.h"
|
||||
|
||||
#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
|
||||
# include "qfontengine_x11_p.h"
|
||||
@ -87,6 +88,7 @@ public:
|
||||
FaceId faceId;
|
||||
faceId.filename = "";
|
||||
faceId.index = 0;
|
||||
faceId.uuid = QUuid::createUuid().toByteArray();
|
||||
|
||||
return init(faceId, true, Format_None, fontData);
|
||||
}
|
||||
@ -98,7 +100,7 @@ void QRawFontPrivate::platformCleanUp()
|
||||
// Font engine handles all resources
|
||||
}
|
||||
|
||||
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, int pixelSize,
|
||||
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference)
|
||||
{
|
||||
Q_ASSERT(fontEngine == 0);
|
||||
|
@ -99,7 +99,7 @@ public:
|
||||
void cleanUp();
|
||||
void platformCleanUp();
|
||||
void platformLoadFromData(const QByteArray &fontData,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference);
|
||||
|
||||
static QRawFontPrivate *get(const QRawFont &font) { return font.d.data(); }
|
||||
|
@ -53,7 +53,7 @@ void QRawFontPrivate::platformCleanUp()
|
||||
{
|
||||
}
|
||||
|
||||
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, int pixelSize,
|
||||
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference)
|
||||
{
|
||||
Q_ASSERT(fontEngine == 0);
|
||||
|
@ -1817,6 +1817,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
|
||||
bool isGettingInput = !e->commitString().isEmpty()
|
||||
|| e->preeditString() != cursor.block().layout()->preeditAreaText()
|
||||
|| e->replacementLength() > 0;
|
||||
bool forceSelectionChanged = false;
|
||||
|
||||
cursor.beginEditBlock();
|
||||
if (isGettingInput) {
|
||||
@ -1840,6 +1841,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
|
||||
cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
|
||||
q->ensureCursorVisible();
|
||||
repaintOldAndNewSelection(oldCursor);
|
||||
forceSelectionChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1874,6 +1876,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
|
||||
cursor_d->setX();
|
||||
if (oldPreeditCursor != preeditCursor)
|
||||
emit q->microFocusChanged();
|
||||
selectionChanged(forceSelectionChanged);
|
||||
}
|
||||
|
||||
QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
|
||||
|
@ -1632,7 +1632,7 @@ bool QTextEngine::isRightToLeft() const
|
||||
int QTextEngine::findItem(int strPos) const
|
||||
{
|
||||
itemize();
|
||||
int left = 0;
|
||||
int left = 1;
|
||||
int right = layoutData->items.size()-1;
|
||||
while(left <= right) {
|
||||
int middle = ((right-left)/2)+left;
|
||||
|
@ -131,6 +131,69 @@ QT_BEGIN_NAMESPACE
|
||||
\omitvalue Valid
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn void QIntValidator::topChanged(int top)
|
||||
|
||||
This signal is emitted after the top property changed.
|
||||
|
||||
\sa QIntValidator::top(), QIntValidator::setTop(), QIntValidator::bottom(), QIntValidator::setBottom()
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QIntValidator::bottomChanged(int bottom)
|
||||
|
||||
This signal is emitted after the bottom property changed.
|
||||
|
||||
\sa QIntValidator::top(), QIntValidator::setTop(), QIntValidator::bottom(), QIntValidator::setBottom()
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QDoubleValidator::topChanged(int top)
|
||||
|
||||
This signal is emitted after the top property changed.
|
||||
|
||||
\sa QDoubleValidator::top(), QDoubleValidator::setTop(), QDoubleValidator::bottom(), QDoubleValidator::setBottom()
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QDoubleValidator::bottomChanged(int bottom)
|
||||
|
||||
This signal is emitted after the bottom property changed.
|
||||
|
||||
\sa QDoubleValidator::top(), QDoubleValidator::setTop(), QDoubleValidator::bottom(), QDoubleValidator::setBottom()
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QDoubleValidator::decimalsChanged(int decimals)
|
||||
|
||||
This signal is emitted after the decimals property changed.
|
||||
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QDoubleValidator::notationChanged(QDoubleValidator::Notation notation)
|
||||
|
||||
This signal is emitted after the notation property changed.
|
||||
|
||||
QDoubleValidator::Notation is not a registered metatype, so for queued connections,
|
||||
you will have to register it with Q_DECLARE_METATYPE() and qRegisterMetaType().
|
||||
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QRegExpValidator::regExpChanged(const QRegExp ®Exp)
|
||||
|
||||
This signal is emitted after the regExp property changed.
|
||||
\internal
|
||||
*/
|
||||
|
||||
class QValidatorPrivate : public QObjectPrivate{
|
||||
Q_DECLARE_PUBLIC(QValidator)
|
||||
public:
|
||||
@ -436,8 +499,15 @@ void QIntValidator::fixup(QString &input) const
|
||||
|
||||
void QIntValidator::setRange(int bottom, int top)
|
||||
{
|
||||
b = bottom;
|
||||
t = top;
|
||||
if (b != bottom) {
|
||||
b = bottom;
|
||||
emit bottomChanged(b);
|
||||
}
|
||||
|
||||
if (t != top) {
|
||||
t = top;
|
||||
emit topChanged(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -710,9 +780,20 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
|
||||
|
||||
void QDoubleValidator::setRange(double minimum, double maximum, int decimals)
|
||||
{
|
||||
b = minimum;
|
||||
t = maximum;
|
||||
dec = decimals;
|
||||
if (b != minimum) {
|
||||
b = minimum;
|
||||
emit bottomChanged(b);
|
||||
}
|
||||
|
||||
if (t != maximum) {
|
||||
t = maximum;
|
||||
emit topChanged(t);
|
||||
}
|
||||
|
||||
if (dec != decimals) {
|
||||
dec = decimals;
|
||||
emit decimalsChanged(dec);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -771,7 +852,10 @@ void QDoubleValidator::setDecimals(int decimals)
|
||||
void QDoubleValidator::setNotation(Notation newNotation)
|
||||
{
|
||||
Q_D(QDoubleValidator);
|
||||
d->notation = newNotation;
|
||||
if (d->notation != newNotation) {
|
||||
d->notation = newNotation;
|
||||
emit notationChanged(d->notation);
|
||||
}
|
||||
}
|
||||
|
||||
QDoubleValidator::Notation QDoubleValidator::notation() const
|
||||
@ -915,7 +999,10 @@ QValidator::State QRegExpValidator::validate(QString &input, int& pos) const
|
||||
|
||||
void QRegExpValidator::setRegExp(const QRegExp& rx)
|
||||
{
|
||||
r = rx;
|
||||
if (r != rx) {
|
||||
r = rx;
|
||||
emit regExpChanged(r);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -96,8 +96,8 @@ private:
|
||||
class Q_GUI_EXPORT QIntValidator : public QValidator
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int bottom READ bottom WRITE setBottom)
|
||||
Q_PROPERTY(int top READ top WRITE setTop)
|
||||
Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY bottomChanged)
|
||||
Q_PROPERTY(int top READ top WRITE setTop NOTIFY topChanged)
|
||||
|
||||
public:
|
||||
explicit QIntValidator(QObject * parent = 0);
|
||||
@ -113,7 +113,9 @@ public:
|
||||
|
||||
int bottom() const { return b; }
|
||||
int top() const { return t; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void bottomChanged(int bottom);
|
||||
void topChanged(int top);
|
||||
#ifdef QT3_SUPPORT
|
||||
public:
|
||||
QT3_SUPPORT_CONSTRUCTOR QIntValidator(QObject * parent, const char *name);
|
||||
@ -134,11 +136,11 @@ class QDoubleValidatorPrivate;
|
||||
class Q_GUI_EXPORT QDoubleValidator : public QValidator
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(double bottom READ bottom WRITE setBottom)
|
||||
Q_PROPERTY(double top READ top WRITE setTop)
|
||||
Q_PROPERTY(int decimals READ decimals WRITE setDecimals)
|
||||
Q_PROPERTY(double bottom READ bottom WRITE setBottom NOTIFY bottomChanged)
|
||||
Q_PROPERTY(double top READ top WRITE setTop NOTIFY topChanged)
|
||||
Q_PROPERTY(int decimals READ decimals WRITE setDecimals NOTIFY decimalsChanged)
|
||||
Q_ENUMS(Notation)
|
||||
Q_PROPERTY(Notation notation READ notation WRITE setNotation)
|
||||
Q_PROPERTY(Notation notation READ notation WRITE setNotation NOTIFY notationChanged)
|
||||
|
||||
public:
|
||||
explicit QDoubleValidator(QObject * parent = 0);
|
||||
@ -149,7 +151,6 @@ public:
|
||||
StandardNotation,
|
||||
ScientificNotation
|
||||
};
|
||||
|
||||
QValidator::State validate(QString &, int &) const;
|
||||
|
||||
virtual void setRange(double bottom, double top, int decimals = 0);
|
||||
@ -163,6 +164,12 @@ public:
|
||||
int decimals() const { return dec; }
|
||||
Notation notation() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void bottomChanged(double bottom);
|
||||
void topChanged(double top);
|
||||
void decimalsChanged(int decimals);
|
||||
void notationChanged(QDoubleValidator::Notation notation);
|
||||
|
||||
#ifdef QT3_SUPPORT
|
||||
public:
|
||||
QT3_SUPPORT_CONSTRUCTOR QDoubleValidator(QObject * parent, const char *name);
|
||||
@ -182,7 +189,7 @@ private:
|
||||
class Q_GUI_EXPORT QRegExpValidator : public QValidator
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp)
|
||||
Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp NOTIFY regExpChanged)
|
||||
|
||||
public:
|
||||
explicit QRegExpValidator(QObject *parent = 0);
|
||||
@ -194,6 +201,8 @@ public:
|
||||
void setRegExp(const QRegExp& rx);
|
||||
const QRegExp& regExp() const { return r; } // ### make inline for 5.0
|
||||
|
||||
Q_SIGNALS:
|
||||
void regExpChanged(const QRegExp& regExp);
|
||||
#ifdef QT3_SUPPORT
|
||||
public:
|
||||
QT3_SUPPORT_CONSTRUCTOR QRegExpValidator(QObject *parent, const char *name);
|
||||
|
@ -97,10 +97,6 @@ extern Q_GUI_EXPORT bool qt_cleartype_enabled;
|
||||
extern bool qt_applefontsmoothing_enabled;
|
||||
#endif
|
||||
|
||||
#if !defined(QT_MAX_CACHED_GLYPH_SIZE)
|
||||
# define QT_MAX_CACHED_GLYPH_SIZE 64
|
||||
#endif
|
||||
|
||||
Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
|
||||
|
||||
////////////////////////////////// Private Methods //////////////////////////////////////////
|
||||
@ -1441,8 +1437,7 @@ void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem)
|
||||
// don't try to cache huge fonts or vastly transformed fonts
|
||||
QFontEngine *fontEngine = textItem->fontEngine();
|
||||
const qreal pixelSize = fontEngine->fontDef.pixelSize;
|
||||
if (pixelSize * pixelSize * qAbs(det) < QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE ||
|
||||
det < 0.25f || det > 4.f) {
|
||||
if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f) {
|
||||
QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0
|
||||
? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat)
|
||||
: d->glyphCacheType;
|
||||
@ -1500,8 +1495,7 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
|
||||
|
||||
// don't try to cache huge fonts or vastly transformed fonts
|
||||
const qreal pixelSize = ti.fontEngine->fontDef.pixelSize;
|
||||
if (pixelSize * pixelSize * qAbs(det) >= QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE ||
|
||||
det < 0.25f || det > 4.f)
|
||||
if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f)
|
||||
drawCached = false;
|
||||
|
||||
QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
|
||||
|
@ -347,13 +347,13 @@ static void find_trans_colors()
|
||||
QGLFormat UNIX/GLX-specific code
|
||||
*****************************************************************************/
|
||||
|
||||
void* qglx_getProcAddress(const char* procName)
|
||||
void (*qglx_getProcAddress(const char* procName))()
|
||||
{
|
||||
// On systems where the GL driver is pluggable (like Mesa), we have to use
|
||||
// the glXGetProcAddressARB extension to resolve other function pointers as
|
||||
// the symbols wont be in the GL library, but rather in a plugin loaded by
|
||||
// the GL library.
|
||||
typedef void* (*qt_glXGetProcAddressARB)(const char *);
|
||||
typedef void (*(*qt_glXGetProcAddressARB)(const char *))();
|
||||
static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
|
||||
static bool triedResolvingGlxGetProcAddress = false;
|
||||
if (!triedResolvingGlxGetProcAddress) {
|
||||
@ -378,7 +378,7 @@ void* qglx_getProcAddress(const char* procName)
|
||||
}
|
||||
}
|
||||
|
||||
void *procAddress = 0;
|
||||
void (*procAddress)() = 0;
|
||||
if (glXGetProcAddressARB)
|
||||
procAddress = glXGetProcAddressARB(procName);
|
||||
|
||||
@ -387,7 +387,7 @@ void* qglx_getProcAddress(const char* procName)
|
||||
if (!procAddress) {
|
||||
void *handle = dlopen(NULL, RTLD_LAZY);
|
||||
if (handle) {
|
||||
procAddress = dlsym(handle, procName);
|
||||
procAddress = (void (*)())dlsym(handle, procName);
|
||||
dlclose(handle);
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ static _glXMakeContextCurrent qt_glXMakeContextCurrent = 0;
|
||||
#define glXGetFBConfigAttrib qt_glXGetFBConfigAttrib
|
||||
#define glXMakeContextCurrent qt_glXMakeContextCurrent
|
||||
|
||||
extern void* qglx_getProcAddress(const char* procName); // in qgl_x11.cpp
|
||||
extern void (*qglx_getProcAddress(const char* procName))(); // in qgl_x11.cpp
|
||||
|
||||
static bool qt_resolve_pbuffer_extensions()
|
||||
{
|
||||
|
@ -218,8 +218,8 @@ static const char * x11_atomnames = {
|
||||
\c XFIXES_MAJOR - it is a part of soname and may differ from the Xfixes
|
||||
version.
|
||||
*/
|
||||
static void* qt_load_library_runtime(const char *library, int vernum,
|
||||
int highestVernum, const char *symbol)
|
||||
static QFunctionPointer qt_load_library_runtime(const char *library, int vernum,
|
||||
int highestVernum, const char *symbol)
|
||||
{
|
||||
QList<int> versions;
|
||||
// we try to load in the following order:
|
||||
@ -234,7 +234,7 @@ static void* qt_load_library_runtime(const char *library, int vernum,
|
||||
Q_FOREACH(int version, versions) {
|
||||
QLatin1String libName(library);
|
||||
QLibrary xfixesLib(libName, version);
|
||||
void *ptr = xfixesLib.resolve(symbol);
|
||||
QFunctionPointer ptr = xfixesLib.resolve(symbol);
|
||||
if (ptr)
|
||||
return ptr;
|
||||
}
|
||||
|
@ -119,6 +119,8 @@ QT_BEGIN_NAMESPACE
|
||||
returns false.
|
||||
*/
|
||||
|
||||
class QRelatedTableModel;
|
||||
|
||||
struct QRelation
|
||||
{
|
||||
public:
|
||||
@ -135,7 +137,7 @@ struct QRelation
|
||||
bool isValid();
|
||||
|
||||
QSqlRelation rel;
|
||||
QSqlTableModel *model;
|
||||
QRelatedTableModel *model;
|
||||
QHash<QString, QVariant> dictionary;//maps keys to display values
|
||||
|
||||
private:
|
||||
@ -143,6 +145,15 @@ struct QRelation
|
||||
bool m_dictInitialized;
|
||||
};
|
||||
|
||||
class QRelatedTableModel : public QSqlTableModel
|
||||
{
|
||||
public:
|
||||
QRelatedTableModel(QRelation *rel, QObject *parent = 0, QSqlDatabase db = QSqlDatabase());
|
||||
bool select();
|
||||
private:
|
||||
bool firstSelect;
|
||||
QRelation *relation;
|
||||
};
|
||||
/*
|
||||
A QRelation must be initialized before it is considered valid.
|
||||
Note: population of the model and dictionary are kept separate
|
||||
@ -162,7 +173,7 @@ void QRelation::populateModel()
|
||||
Q_ASSERT(m_parent != NULL);
|
||||
|
||||
if (!model) {
|
||||
model = new QSqlTableModel(m_parent, m_parent->database());
|
||||
model = new QRelatedTableModel(this, m_parent, m_parent->database());
|
||||
model->setTable(rel.tableName());
|
||||
model->select();
|
||||
}
|
||||
@ -219,6 +230,27 @@ bool QRelation::isValid()
|
||||
return (rel.isValid() && m_parent != NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
QRelatedTableModel::QRelatedTableModel(QRelation *rel, QObject *parent, QSqlDatabase db) :
|
||||
QSqlTableModel(parent, db), firstSelect(true), relation(rel)
|
||||
{
|
||||
}
|
||||
|
||||
bool QRelatedTableModel::select()
|
||||
{
|
||||
if (firstSelect) {
|
||||
firstSelect = false;
|
||||
return QSqlTableModel::select();
|
||||
}
|
||||
relation->clearDictionary();
|
||||
bool res = QSqlTableModel::select();
|
||||
if (res)
|
||||
relation->populateDictionary();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
class QSqlRelationalTableModelPrivate: public QSqlTableModelPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QSqlRelationalTableModel)
|
||||
|
@ -88,7 +88,7 @@ qpa:mac: {
|
||||
|
||||
load(qt_module_config)
|
||||
|
||||
HEADERS += $$QT_SOURCE_TREE/src/testlib/qttestlibversion.h
|
||||
HEADERS += $$QT_SOURCE_TREE/src/testlib/qttestversion.h
|
||||
|
||||
QMAKE_TARGET_PRODUCT = QTestLib
|
||||
QMAKE_TARGET_DESCRIPTION = Qt \
|
||||
|
@ -55,7 +55,7 @@ void QRawFontPrivate::platformCleanUp()
|
||||
extern int qt_defaultDpi();
|
||||
|
||||
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference)
|
||||
{
|
||||
// Mac OS X ignores it
|
||||
|
@ -529,7 +529,8 @@ void QRawFontPrivate::platformCleanUp()
|
||||
{
|
||||
if (fontHandle != NULL) {
|
||||
if (ptrRemoveFontMemResourceEx == NULL) {
|
||||
void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
|
||||
QFunctionPointer func =
|
||||
QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
|
||||
ptrRemoveFontMemResourceEx =
|
||||
reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
|
||||
}
|
||||
@ -545,7 +546,7 @@ void QRawFontPrivate::platformCleanUp()
|
||||
}
|
||||
|
||||
void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
|
||||
int pixelSize,
|
||||
qreal pixelSize,
|
||||
QFont::HintingPreference hintingPreference)
|
||||
{
|
||||
QByteArray fontData(_fontData);
|
||||
@ -572,7 +573,8 @@ void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
|
||||
}
|
||||
|
||||
if (ptrAddFontMemResourceEx == NULL || ptrRemoveFontMemResourceEx == NULL) {
|
||||
void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
|
||||
QFunctionPointer func =
|
||||
QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
|
||||
ptrRemoveFontMemResourceEx =
|
||||
reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
|
||||
|
||||
|
@ -513,7 +513,7 @@ void QKeyMapperPrivate::clearMappings()
|
||||
|
||||
// ### ???
|
||||
// if (keyboardLayoutName.isEmpty())
|
||||
// qWarning("Qt: unable to determine keyboard layout, please talk to qt-bugs@trolltech.com"); ?
|
||||
// qWarning("Qt: unable to determine keyboard layout, please talk to qt-info@nokia.com"); ?
|
||||
|
||||
keyboardInputLocale = q_getKeyboardLocale(layoutName, variantName);
|
||||
keyboardInputDirection = keyboardInputLocale.textDirection();
|
||||
|
@ -148,6 +148,8 @@ public:
|
||||
|
||||
void clear();
|
||||
|
||||
QTabBar* tabBar() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setCurrentIndex(int index);
|
||||
void setCurrentWidget(QWidget *widget);
|
||||
@ -165,7 +167,6 @@ protected:
|
||||
void keyPressEvent(QKeyEvent *);
|
||||
void paintEvent(QPaintEvent *);
|
||||
void setTabBar(QTabBar *);
|
||||
QTabBar* tabBar() const;
|
||||
void changeEvent(QEvent *);
|
||||
bool event(QEvent *);
|
||||
void initStyleOption(QStyleOptionTabWidgetFrame *option) const;
|
||||
|
@ -1,7 +1,6 @@
|
||||
# Additional Qt project file for qtmain lib on Windows
|
||||
TEMPLATE = lib
|
||||
TARGET = qtmain
|
||||
DESTDIR = $$QMAKE_LIBDIR_QT
|
||||
QT =
|
||||
|
||||
CONFIG += staticlib warn_on
|
||||
@ -17,5 +16,6 @@ win32 {
|
||||
|
||||
!win32:error("$$_FILE_ is intended only for Windows!")
|
||||
load(qt_module_config)
|
||||
DESTDIR = $$QMAKE_LIBDIR_QT
|
||||
wince*:QMAKE_POST_LINK =
|
||||
|
||||
|
@ -30,6 +30,7 @@ SUBDIRS=\
|
||||
qfileinfo \
|
||||
qfilesystemwatcher \
|
||||
qflags \
|
||||
qfreelist \
|
||||
qfuture \
|
||||
qfuturewatcher \
|
||||
qgetputenv \
|
||||
|
@ -26,5 +26,3 @@ contains(QT_CONFIG, dbus){
|
||||
QT += dbus
|
||||
}
|
||||
|
||||
CONFIG+=insignificant_test
|
||||
|
||||
|
@ -10,3 +10,5 @@ wince*|symbian: {
|
||||
}
|
||||
|
||||
symbian: TARGET.CAPABILITY = NetworkServices
|
||||
|
||||
CONFIG += insignificant_test # QTBUG-20686; note, assumed unstable on all platforms
|
||||
|
@ -361,26 +361,25 @@ class DeliverInDefinedOrderObject : public QObject
|
||||
|
||||
QPointer<QThread> thread;
|
||||
int count;
|
||||
int startCount;
|
||||
int loopLevel;
|
||||
|
||||
public:
|
||||
DeliverInDefinedOrderObject(QObject *parent)
|
||||
: QObject(parent), thread(0), count(0)
|
||||
: QObject(parent), thread(0), count(0), startCount(0), loopLevel(0)
|
||||
{ }
|
||||
~DeliverInDefinedOrderObject()
|
||||
{
|
||||
if (!thread.isNull())
|
||||
thread->wait();
|
||||
}
|
||||
|
||||
signals:
|
||||
void done();
|
||||
|
||||
public slots:
|
||||
void start()
|
||||
void startThread()
|
||||
{
|
||||
QVERIFY(!thread);
|
||||
thread = new DeliverInDefinedOrderThread();
|
||||
connect(thread, SIGNAL(progress(int)), this, SLOT(threadProgress(int)));
|
||||
connect(thread, SIGNAL(finished()), this, SLOT(threadFinished()));
|
||||
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
|
||||
connect(thread, SIGNAL(destroyed()), this, SLOT(start()));
|
||||
connect(thread, SIGNAL(destroyed()), this, SLOT(threadDestroyed()));
|
||||
thread->start();
|
||||
|
||||
QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
|
||||
@ -398,21 +397,34 @@ public slots:
|
||||
{
|
||||
QVERIFY(count == 7);
|
||||
count = 0;
|
||||
thread->deleteLater();
|
||||
|
||||
QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
|
||||
}
|
||||
|
||||
void threadDestroyed()
|
||||
{
|
||||
if (++startCount < 20)
|
||||
startThread();
|
||||
else
|
||||
emit done();
|
||||
}
|
||||
|
||||
public:
|
||||
bool event(QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::User:
|
||||
{
|
||||
(void) QEventLoop().exec();
|
||||
break;
|
||||
{
|
||||
++loopLevel;
|
||||
if (loopLevel == 2) {
|
||||
// Ready. Starts a thread that emits (queued) signals, which should be handled in order
|
||||
startThread();
|
||||
}
|
||||
case QEvent::User + 1:
|
||||
QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
|
||||
(void) QEventLoop().exec();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -430,11 +442,8 @@ void tst_QCoreApplication::deliverInDefinedOrder()
|
||||
// causes sendPostedEvents() to recurse twice
|
||||
QCoreApplication::postEvent(&obj, new QEvent(QEvent::User));
|
||||
QCoreApplication::postEvent(&obj, new QEvent(QEvent::User));
|
||||
// starts a thread that emits (queued) signals, which should be handled in order
|
||||
obj.start();
|
||||
|
||||
// run for 15 seconds
|
||||
QTimer::singleShot(15000, &app, SLOT(quit()));
|
||||
QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()));
|
||||
app.exec();
|
||||
}
|
||||
#endif // QT_NO_QTHREAD
|
||||
@ -524,7 +533,7 @@ void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents()
|
||||
QCoreApplication::processEvents();
|
||||
QCOMPARE(object.counter, i);
|
||||
++i;
|
||||
} while (t.elapsed() < 3000);
|
||||
} while (t.elapsed() < 1000);
|
||||
}
|
||||
|
||||
void tst_QCoreApplication::reexec()
|
||||
|
@ -1,6 +1,3 @@
|
||||
load(qttest_p4)
|
||||
QT += widgets
|
||||
SOURCES += tst_qdialog.cpp
|
||||
|
||||
|
||||
CONFIG+=insignificant_test
|
||||
|
@ -467,6 +467,22 @@ void tst_QDialog::throwInExec()
|
||||
#if defined(Q_WS_MAC) || (defined(Q_WS_WINCE) && defined(_ARM_))
|
||||
QSKIP("Throwing exceptions in exec() is not supported on this platform.", SkipAll);
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
// C++ exceptions can't be passed through glib callbacks. Skip the test if
|
||||
// we're using the glib event loop.
|
||||
QByteArray dispatcher = QAbstractEventDispatcher::instance()->metaObject()->className();
|
||||
if (dispatcher.contains("Glib")) {
|
||||
QSKIP(
|
||||
qPrintable(QString(
|
||||
"Throwing exceptions in exec() won't work if %1 event dispatcher is used.\n"
|
||||
"Try running with QT_NO_GLIB=1 in environment."
|
||||
).arg(QString::fromLatin1(dispatcher))),
|
||||
SkipAll
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
int caughtExceptions = 0;
|
||||
try {
|
||||
ExceptionDialog dialog;
|
||||
|
@ -55,6 +55,7 @@ private slots:
|
||||
void validateThouSep();
|
||||
void validateIntEquiv_data();
|
||||
void validateIntEquiv();
|
||||
void notifySignals();
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QValidator::State);
|
||||
@ -244,6 +245,62 @@ void tst_QDoubleValidator::validate()
|
||||
dv.setNotation(QDoubleValidator::StandardNotation);
|
||||
QCOMPARE((int)dv.validate(value, dummy), (int)standard_state);
|
||||
}
|
||||
void tst_QDoubleValidator::notifySignals()
|
||||
{
|
||||
QDoubleValidator dv(0.1, 0.9, 10, 0);
|
||||
QSignalSpy topSpy(&dv, SIGNAL(topChanged(double)));
|
||||
QSignalSpy bottomSpy(&dv, SIGNAL(bottomChanged(double)));
|
||||
QSignalSpy decSpy(&dv, SIGNAL(decimalsChanged(int)));
|
||||
|
||||
qRegisterMetaType<QDoubleValidator::Notation>("QDoubleValidator::Notation");
|
||||
QSignalSpy notSpy(&dv, SIGNAL(notationChanged(QDoubleValidator::Notation)));
|
||||
|
||||
dv.setTop(0.8);
|
||||
QCOMPARE(topSpy.count(), 1);
|
||||
QVERIFY(dv.top() == 0.8);
|
||||
dv.setBottom(0.2);
|
||||
QCOMPARE(bottomSpy.count(), 1);
|
||||
QVERIFY(dv.bottom() == 0.2);
|
||||
|
||||
dv.setRange(0.2, 0.7);
|
||||
QCOMPARE(topSpy.count(), 2);
|
||||
QCOMPARE(bottomSpy.count(), 1);
|
||||
QCOMPARE(decSpy.count(), 1);
|
||||
QVERIFY(dv.bottom() == 0.2);
|
||||
QVERIFY(dv.top() == 0.7);
|
||||
QVERIFY(dv.decimals() == 0.);
|
||||
|
||||
dv.setRange(0.3, 0.7);
|
||||
QCOMPARE(topSpy.count(), 2);
|
||||
QCOMPARE(bottomSpy.count(), 2);
|
||||
QVERIFY(dv.bottom() == 0.3);
|
||||
QVERIFY(dv.top() == 0.7);
|
||||
QVERIFY(dv.decimals() == 0.);
|
||||
|
||||
dv.setRange(0.4, 0.6);
|
||||
QCOMPARE(topSpy.count(), 3);
|
||||
QCOMPARE(bottomSpy.count(), 3);
|
||||
QVERIFY(dv.bottom() == 0.4);
|
||||
QVERIFY(dv.top() == 0.6);
|
||||
QVERIFY(dv.decimals() == 0.);
|
||||
|
||||
dv.setDecimals(10);
|
||||
QCOMPARE(decSpy.count(), 2);
|
||||
QVERIFY(dv.decimals() == 10.);
|
||||
|
||||
|
||||
dv.setRange(0.4, 0.6, 100);
|
||||
QCOMPARE(topSpy.count(), 3);
|
||||
QCOMPARE(bottomSpy.count(), 3);
|
||||
QCOMPARE(decSpy.count(), 3);
|
||||
QVERIFY(dv.bottom() == 0.4);
|
||||
QVERIFY(dv.top() == 0.6);
|
||||
QVERIFY(dv.decimals() == 100.);
|
||||
|
||||
dv.setNotation(QDoubleValidator::StandardNotation);
|
||||
QCOMPARE(notSpy.count(), 1);
|
||||
QVERIFY(dv.notation() == QDoubleValidator::StandardNotation);
|
||||
}
|
||||
|
||||
void tst_QDoubleValidator::validateIntEquiv_data()
|
||||
{
|
||||
|
@ -41,4 +41,4 @@ symbian {
|
||||
LIBS+=-lefsrv
|
||||
}
|
||||
|
||||
CONFIG+=insignificant_test
|
||||
mac*:CONFIG+=insignificant_test
|
||||
|
@ -2438,7 +2438,7 @@ void tst_QFile::rename_data()
|
||||
QTest::newRow("a -> b") << QString("a") << QString("b") << false;
|
||||
QTest::newRow("a -> .") << QString("a") << QString(".") << false;
|
||||
QTest::newRow("renamefile -> renamefile") << QString("renamefile") << QString("renamefile") << false;
|
||||
QTest::newRow("renamefile -> Makefile") << QString("renamefile") << QString("Makefile") << false;
|
||||
QTest::newRow("renamefile -> noreadfile") << QString("renamefile") << QString("noreadfile") << false;
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
|
||||
QTest::newRow("renamefile -> /etc/renamefile") << QString("renamefile") << QString("/etc/renamefile") << false;
|
||||
#endif
|
||||
|
@ -15,5 +15,3 @@ symbian: {
|
||||
DEPLOYMENT += dummyDeploy
|
||||
LIBS += -lefsrv
|
||||
}
|
||||
|
||||
CONFIG+=insignificant_test
|
||||
|
@ -909,12 +909,16 @@ void tst_QFileSystemModel::sort()
|
||||
expectedOrder << tempFile2.fileName() << tempFile.fileName() << dirPath + QChar('/') + "." << dirPath + QChar('/') + "..";
|
||||
//File dialog Mode means sub trees are not sorted, only the current root
|
||||
if (fileDialogMode) {
|
||||
// FIXME: we were only able to disableRecursiveSort in developer builds, so we can only
|
||||
// stably perform this test for developer builds
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
QList<QString> actualRows;
|
||||
for(int i = 0; i < myModel->rowCount(parent); ++i)
|
||||
{
|
||||
actualRows << dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString();
|
||||
}
|
||||
QVERIFY(actualRows != expectedOrder);
|
||||
#endif
|
||||
} else {
|
||||
for(int i = 0; i < myModel->rowCount(parent); ++i)
|
||||
{
|
||||
|
6
tests/auto/qfreelist/qfreelist.pro
Normal file
6
tests/auto/qfreelist/qfreelist.pro
Normal file
@ -0,0 +1,6 @@
|
||||
load(qttest_p4)
|
||||
SOURCES += tst_qfreelist.cpp
|
||||
QT += core-private
|
||||
QT -= gui
|
||||
|
||||
!private_tests:SOURCES += $$QT_SOURCE_TREE/src/corelib/tools/qfreelist.cpp
|
179
tests/auto/qfreelist/tst_qfreelist.cpp
Normal file
179
tests/auto/qfreelist/tst_qfreelist.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QThread>
|
||||
#include <private/qfreelist_p.h>
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
//TESTED_CLASS=QFreeList
|
||||
//TESTED_FILES=corelib/tools/qfreelist_p.h
|
||||
|
||||
class tst_QFreeList : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void basicTest();
|
||||
void customized();
|
||||
void threadedTest();
|
||||
};
|
||||
|
||||
void tst_QFreeList::basicTest()
|
||||
{
|
||||
{
|
||||
QFreeList<void> voidFreeList;
|
||||
int zero = voidFreeList.next();
|
||||
int one = voidFreeList.next();
|
||||
int two = voidFreeList.next();
|
||||
QCOMPARE(zero, 0);
|
||||
QCOMPARE(one, 1);
|
||||
QCOMPARE(two, 2);
|
||||
voidFreeList[zero];
|
||||
voidFreeList[one];
|
||||
voidFreeList[two];
|
||||
voidFreeList.at(zero);
|
||||
voidFreeList.at(one);
|
||||
voidFreeList.at(two);
|
||||
voidFreeList.release(one);
|
||||
int next = voidFreeList.next();
|
||||
QCOMPARE(next, 1);
|
||||
voidFreeList[next];
|
||||
voidFreeList.at(next);
|
||||
}
|
||||
|
||||
{
|
||||
QFreeList<int> intFreeList;
|
||||
int zero = intFreeList.next();
|
||||
int one = intFreeList.next();
|
||||
int two = intFreeList.next();
|
||||
QCOMPARE(zero, 0);
|
||||
QCOMPARE(one, 1);
|
||||
QCOMPARE(two, 2);
|
||||
intFreeList[zero] = zero;
|
||||
intFreeList[one] = one;
|
||||
intFreeList[two] = two;
|
||||
QCOMPARE(intFreeList.at(zero), zero);
|
||||
QCOMPARE(intFreeList.at(one), one);
|
||||
QCOMPARE(intFreeList.at(two), two);
|
||||
intFreeList.release(one);
|
||||
int next = intFreeList.next();
|
||||
QCOMPARE(next, 1);
|
||||
QCOMPARE(intFreeList.at(next), one);
|
||||
intFreeList[next] = -one;
|
||||
QCOMPARE(intFreeList.at(next), -one);
|
||||
}
|
||||
}
|
||||
|
||||
struct CustomFreeListConstants : public QFreeListDefaultConstants
|
||||
{
|
||||
enum {
|
||||
InitialNextValue = 50,
|
||||
BlockCount = 10
|
||||
};
|
||||
|
||||
static const int Sizes[10];
|
||||
};
|
||||
|
||||
const int CustomFreeListConstants::Sizes[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 16777216 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 };
|
||||
|
||||
void tst_QFreeList::customized()
|
||||
{
|
||||
QFreeList<void, CustomFreeListConstants> customFreeList;
|
||||
int next = customFreeList.next();
|
||||
QCOMPARE(next, int(CustomFreeListConstants::InitialNextValue));
|
||||
customFreeList[next];
|
||||
customFreeList.at(next);
|
||||
customFreeList.release(next);
|
||||
}
|
||||
|
||||
enum { TimeLimit = 3000 };
|
||||
|
||||
class FreeListThread : public QThread
|
||||
{
|
||||
static QFreeList<void> freelist;
|
||||
|
||||
public:
|
||||
inline FreeListThread() : QThread() { }
|
||||
inline void run()
|
||||
{
|
||||
QElapsedTimer t;
|
||||
t.start();
|
||||
QList<int> needToRelease;
|
||||
do {
|
||||
int i = freelist.next();
|
||||
int j = freelist.next();
|
||||
int k = freelist.next();
|
||||
int l = freelist.next();
|
||||
freelist.release(k);
|
||||
int n = freelist.next();
|
||||
int m = freelist.next();
|
||||
freelist.release(l);
|
||||
freelist.release(m);
|
||||
freelist.release(n);
|
||||
freelist.release(j);
|
||||
// freelist.release(i);
|
||||
needToRelease << i;
|
||||
} while (t.elapsed() < TimeLimit);
|
||||
|
||||
foreach (int x, needToRelease)
|
||||
freelist.release(x);
|
||||
}
|
||||
};
|
||||
|
||||
QFreeList<void> FreeListThread::freelist;
|
||||
|
||||
void tst_QFreeList::threadedTest()
|
||||
{
|
||||
const int ThreadCount = QThread::idealThreadCount();
|
||||
FreeListThread *threads = new FreeListThread[ThreadCount];
|
||||
for (int i = 0; i < ThreadCount; ++i)
|
||||
threads[i].start();
|
||||
for (int i = 0; i < ThreadCount; ++i)
|
||||
threads[i].wait();
|
||||
delete [] threads;
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QFreeList)
|
||||
#include "tst_qfreelist.moc"
|
@ -18,5 +18,3 @@ wince*: {
|
||||
} else {
|
||||
DEFINES += SRCDIR=\\\"$$PWD/\\\"
|
||||
}
|
||||
|
||||
CONFIG+=insignificant_test
|
||||
|
@ -378,6 +378,8 @@ void tst_QFtp::connectToUnresponsiveHost()
|
||||
a lot of other stuff in QFtp, so we just expect this test to fail on Windows.
|
||||
*/
|
||||
QEXPECT_FAIL("", "timeout not working due to strange Windows socket behaviour (see source file of this test for explanation)", Abort);
|
||||
#else
|
||||
QEXPECT_FAIL("", "QTBUG-20687", Abort);
|
||||
#endif
|
||||
QVERIFY2(! QTestEventLoop::instance().timeout(), "Network timeout longer than expected (should have been 60 seconds)");
|
||||
|
||||
|
@ -130,10 +130,12 @@ void tst_QGlobal::qInternalCallbacks()
|
||||
QInternal::unregisterCallback(QInternal::DisconnectCallback, disconnect_callback);
|
||||
|
||||
connect_info.reset();
|
||||
QTest::ignoreMessage(QtWarningMsg, "Object::connect: No such signal QObject::mysignal(x)");
|
||||
ok = QObject::connect(&a, signal.toLatin1(), &b, slot.toLatin1(), Qt::AutoConnection);
|
||||
QVERIFY(!ok);
|
||||
QCOMPARE(connect_info.sender, (QObject *) 0);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "Object::disconnect: No such signal QObject::mysignal(x)");
|
||||
ok = QObject::disconnect(&a, signal.toLatin1(), &b, slot.toLatin1());
|
||||
QVERIFY(!ok);
|
||||
QCOMPARE(connect_info.sender, (QObject *) 0);
|
||||
|
@ -2,5 +2,3 @@ load(qttest_p4)
|
||||
QT += widgets
|
||||
SOURCES += tst_qgraphicstransform.cpp
|
||||
CONFIG += parallel_test
|
||||
|
||||
CONFIG+=insignificant_test
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user