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 Cwd 'abs_path';
|
||||||
use Config;
|
use Config;
|
||||||
use strict;
|
use strict;
|
||||||
|
use English qw(-no_match_vars );
|
||||||
|
|
||||||
# set output basedir to be where ever syncqt is run from
|
# set output basedir to be where ever syncqt is run from
|
||||||
our $out_basedir = getcwd();
|
our $out_basedir = getcwd();
|
||||||
@ -38,7 +39,7 @@ our (%modules, %moduleheaders, %classnames, %mastercontent, %modulepris);
|
|||||||
my $isunix = 0;
|
my $isunix = 0;
|
||||||
my $module = 0;
|
my $module = 0;
|
||||||
my $showonly = 0;
|
my $showonly = 0;
|
||||||
my $quiet = 0;
|
my $verbose_level = 1;
|
||||||
my $remove_stale = 1;
|
my $remove_stale = 1;
|
||||||
my $force_win = 0;
|
my $force_win = 0;
|
||||||
my $force_relative = 0;
|
my $force_relative = 0;
|
||||||
@ -50,6 +51,7 @@ my $module_fwd = "";
|
|||||||
my $cache_module_fwd = 0;
|
my $cache_module_fwd = 0;
|
||||||
my $developer_build = 0;
|
my $developer_build = 0;
|
||||||
my $no_module_version_header = 0;
|
my $no_module_version_header = 0;
|
||||||
|
my $makefile_generator = "";
|
||||||
my @modules_to_sync ;
|
my @modules_to_sync ;
|
||||||
$force_relative = 1 if ( -d "/System/Library/Frameworks" );
|
$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 " -showonly Show action but not perform (default: " . ($showonly ? "yes" : "no") . ")\n";
|
||||||
print " -outdir <PATH> Specify output directory for sync (default: $out_basedir)\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 " -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 " -separate-module <NAME>:<PROFILEDIR>:<HEADERDIR>\n";
|
||||||
print " Create headers for <NAME> with original headers in\n";
|
print " Create headers for <NAME> with original headers in\n";
|
||||||
print " <HEADERDIR> relative to <PROFILEDIR> \n";
|
print " <HEADERDIR> relative to <PROFILEDIR> \n";
|
||||||
@ -88,6 +92,7 @@ sub showUsage
|
|||||||
print " easy development\n";
|
print " easy development\n";
|
||||||
print " -no-module-version-header\n";
|
print " -no-module-version-header\n";
|
||||||
print " Don't create module version header file\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";
|
print " -help This help\n";
|
||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
@ -273,6 +278,15 @@ sub classNames {
|
|||||||
return @ret;
|
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)
|
# Syntax: syncHeader(header, iheader, copy, timestamp)
|
||||||
# Params: header, string, filename to create "symlink" for
|
# Params: header, string, filename to create "symlink" for
|
||||||
@ -284,14 +298,14 @@ sub classNames {
|
|||||||
# Returns: 1 if successful, else 0.
|
# Returns: 1 if successful, else 0.
|
||||||
######################################################################
|
######################################################################
|
||||||
sub syncHeader {
|
sub syncHeader {
|
||||||
my ($header, $iheader, $copy, $ts) = @_;
|
my ($lib, $header, $iheader, $copy, $ts) = @_;
|
||||||
$iheader =~ s=\\=/=g;
|
$iheader =~ s=\\=/=g;
|
||||||
$header =~ s=\\=/=g;
|
$header =~ s=\\=/=g;
|
||||||
return copyFile($iheader, $header) if($copy);
|
return copyFile($lib, $iheader, $header) if($copy);
|
||||||
|
|
||||||
unless(-e $header) {
|
unless(-e $header) {
|
||||||
my $header_dir = dirname($header);
|
my $header_dir = dirname($header);
|
||||||
mkpath $header_dir, !$quiet;
|
make_path($header_dir, $lib, $verbose_level);
|
||||||
|
|
||||||
#write it
|
#write it
|
||||||
my $iheader_out = fixPaths($iheader, $header_dir);
|
my $iheader_out = fixPaths($iheader, $header_dir);
|
||||||
@ -412,7 +426,7 @@ sub fileCompare {
|
|||||||
######################################################################
|
######################################################################
|
||||||
sub copyFile
|
sub copyFile
|
||||||
{
|
{
|
||||||
my ($file,$ifile, $copy,$knowdiff,$filecontents,$ifilecontents) = @_;
|
my ($lib, $file,$ifile, $copy,$knowdiff,$filecontents,$ifilecontents) = @_;
|
||||||
# Bi-directional synchronization
|
# Bi-directional synchronization
|
||||||
open( I, "< " . $file ) || die "Could not open $file for reading";
|
open( I, "< " . $file ) || die "Could not open $file for reading";
|
||||||
local $/;
|
local $/;
|
||||||
@ -434,7 +448,7 @@ sub copyFile
|
|||||||
if ( $knowdiff || ($filecontents ne $ifilecontents) ) {
|
if ( $knowdiff || ($filecontents ne $ifilecontents) ) {
|
||||||
if ( $copy > 0 ) {
|
if ( $copy > 0 ) {
|
||||||
my $file_dir = dirname($file);
|
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?)";
|
open(O, "> " . $file) || die "Could not open $file for writing (no write permission?)";
|
||||||
local $/;
|
local $/;
|
||||||
binmode O;
|
binmode O;
|
||||||
@ -444,7 +458,7 @@ sub copyFile
|
|||||||
return 1;
|
return 1;
|
||||||
} elsif ( $copy < 0 ) {
|
} elsif ( $copy < 0 ) {
|
||||||
my $ifile_dir = dirname($ifile);
|
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?)";
|
open(O, "> " . $ifile) || die "Could not open $ifile for writing (no write permission?)";
|
||||||
local $/;
|
local $/;
|
||||||
binmode O;
|
binmode O;
|
||||||
@ -468,10 +482,10 @@ sub copyFile
|
|||||||
######################################################################
|
######################################################################
|
||||||
sub symlinkFile
|
sub symlinkFile
|
||||||
{
|
{
|
||||||
my ($file,$ifile) = @_;
|
my ($lib, $file, $ifile) = @_;
|
||||||
|
|
||||||
if ($isunix) {
|
if ($isunix) {
|
||||||
print "symlink created for $file " unless $quiet;
|
print "$lib: symlink created for $file " if ($verbose_level);
|
||||||
if ( $force_relative && ($ifile =~ /^$quoted_basedir/)) {
|
if ( $force_relative && ($ifile =~ /^$quoted_basedir/)) {
|
||||||
my $t = getcwd();
|
my $t = getcwd();
|
||||||
my $c = -1;
|
my $c = -1;
|
||||||
@ -479,12 +493,12 @@ sub symlinkFile
|
|||||||
$t =~ s-^$quoted_basedir/--;
|
$t =~ s-^$quoted_basedir/--;
|
||||||
$p .= "../" while( ($c = index( $t, "/", $c + 1)) != -1 );
|
$p .= "../" while( ($c = index( $t, "/", $c + 1)) != -1 );
|
||||||
$file =~ s-^$quoted_basedir/-$p-;
|
$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 symlink($file, $ifile);
|
||||||
}
|
}
|
||||||
return copyFile($file, $ifile);
|
return copyFile($lib, $file, $ifile);
|
||||||
}
|
}
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
@ -534,8 +548,10 @@ sub findFiles {
|
|||||||
######################################################################
|
######################################################################
|
||||||
sub loadSyncProfile {
|
sub loadSyncProfile {
|
||||||
my ($srcbase, $outbase) = @_;
|
my ($srcbase, $outbase) = @_;
|
||||||
print("srcbase = $$srcbase \n");
|
if ($verbose_level) {
|
||||||
print("outbase = $$outbase \n");
|
print("<srcbase> = $$srcbase \n");
|
||||||
|
print("<outbase> = $$outbase \n");
|
||||||
|
}
|
||||||
|
|
||||||
my $syncprofile = "$$srcbase/sync.profile";
|
my $syncprofile = "$$srcbase/sync.profile";
|
||||||
my $result;
|
my $result;
|
||||||
@ -627,8 +643,14 @@ while ( @ARGV ) {
|
|||||||
$var = "showonly";
|
$var = "showonly";
|
||||||
$val = "yes";
|
$val = "yes";
|
||||||
} elsif($arg eq "-quiet") {
|
} elsif($arg eq "-quiet") {
|
||||||
$var = "quiet";
|
$var = "verbose";
|
||||||
|
$val = "0";
|
||||||
|
} elsif($arg eq "-v") {
|
||||||
|
$var = "verbose";
|
||||||
$val = "yes";
|
$val = "yes";
|
||||||
|
} elsif($arg eq "-verbose") {
|
||||||
|
$var = "verbose";
|
||||||
|
$val = shift @ARGV;
|
||||||
} elsif($arg eq "-private") {
|
} elsif($arg eq "-private") {
|
||||||
$var = "create_private_headers";
|
$var = "create_private_headers";
|
||||||
$val = "yes";
|
$val = "yes";
|
||||||
@ -639,6 +661,9 @@ while ( @ARGV ) {
|
|||||||
# skip, it's been dealt with at the top of the file
|
# skip, it's been dealt with at the top of the file
|
||||||
shift @ARGV;
|
shift @ARGV;
|
||||||
next;
|
next;
|
||||||
|
} elsif($arg eq "-generator") {
|
||||||
|
$var = "makefile_generator";
|
||||||
|
$val = shift @ARGV;
|
||||||
} elsif($arg =~/^-/) {
|
} elsif($arg =~/^-/) {
|
||||||
print "Unknown option: $arg\n\n" if(!$var);
|
print "Unknown option: $arg\n\n" if(!$var);
|
||||||
showUsage();
|
showUsage();
|
||||||
@ -667,11 +692,13 @@ while ( @ARGV ) {
|
|||||||
} elsif($showonly) {
|
} elsif($showonly) {
|
||||||
$showonly--;
|
$showonly--;
|
||||||
}
|
}
|
||||||
} elsif ($var eq "quiet") {
|
} elsif ($var eq "verbose") {
|
||||||
if($val eq "yes") {
|
if($val eq "yes") {
|
||||||
$quiet++;
|
$verbose_level++;
|
||||||
} elsif($quiet) {
|
} elsif($val eq "no" && $verbose_level) {
|
||||||
$quiet--;
|
$verbose_level--;
|
||||||
|
} else {
|
||||||
|
$verbose_level = int($val);
|
||||||
}
|
}
|
||||||
} elsif ($var eq "check-includes") {
|
} elsif ($var eq "check-includes") {
|
||||||
if($val eq "yes") {
|
if($val eq "yes") {
|
||||||
@ -698,7 +725,7 @@ while ( @ARGV ) {
|
|||||||
$force_relative--;
|
$force_relative--;
|
||||||
}
|
}
|
||||||
} elsif ($var eq "module") {
|
} 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});
|
die "No such module: $val" unless(defined $modules{$val});
|
||||||
push @modules_to_sync, $val;
|
push @modules_to_sync, $val;
|
||||||
} elsif ($var eq "separate-module") {
|
} elsif ($var eq "separate-module") {
|
||||||
@ -720,6 +747,8 @@ while ( @ARGV ) {
|
|||||||
$cache_module_fwd = 1;
|
$cache_module_fwd = 1;
|
||||||
} elsif ($var eq "developer_build") {
|
} elsif ($var eq "developer_build") {
|
||||||
$developer_build = 1;
|
$developer_build = 1;
|
||||||
|
} elsif ($var eq "makefile_generator") {
|
||||||
|
$makefile_generator = $val;
|
||||||
} elsif ($var eq "no_module_version_header") {
|
} elsif ($var eq "no_module_version_header") {
|
||||||
$no_module_version_header = 1;
|
$no_module_version_header = 1;
|
||||||
} elsif ($var eq "output") {
|
} elsif ($var eq "output") {
|
||||||
@ -766,9 +795,7 @@ loadSyncProfile(\$basedir, \$out_basedir);
|
|||||||
$isunix = checkUnix; #cache checkUnix
|
$isunix = checkUnix; #cache checkUnix
|
||||||
|
|
||||||
# create path
|
# create path
|
||||||
mkpath "$out_basedir/include", !$quiet;
|
make_path("$out_basedir/include/Qt", "<outdir>", $verbose_level);
|
||||||
mkpath "$out_basedir/include/Qt", !$quiet;
|
|
||||||
|
|
||||||
|
|
||||||
foreach my $lib (@modules_to_sync) {
|
foreach my $lib (@modules_to_sync) {
|
||||||
#iteration info
|
#iteration info
|
||||||
@ -796,7 +823,7 @@ foreach my $lib (@modules_to_sync) {
|
|||||||
chomp $module_patch_version;
|
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 = "";
|
my $pathtoheaders = "";
|
||||||
$pathtoheaders = $moduleheaders{$lib} if ($moduleheaders{$lib});
|
$pathtoheaders = $moduleheaders{$lib} if ($moduleheaders{$lib});
|
||||||
@ -870,6 +897,7 @@ foreach my $lib (@modules_to_sync) {
|
|||||||
my $modulepri = $modulepris{$lib};
|
my $modulepri = $modulepris{$lib};
|
||||||
if (-e $modulepri) {
|
if (-e $modulepri) {
|
||||||
my $modulepriname = basename($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 $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));
|
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";
|
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 "#define " .uc($lib) . "_VERSION $modulehexstring\n", ;
|
||||||
print MODULE_VERSION_HEADER_FILE "\n";
|
print MODULE_VERSION_HEADER_FILE "\n";
|
||||||
print MODULE_VERSION_HEADER_FILE "#endif // QT_". uc($lib) . "_VERSION_H\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) {
|
} 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;
|
push @headers, "*".$if;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
my $header_dirname = "";
|
||||||
foreach my $header (@headers) {
|
foreach my $header (@headers) {
|
||||||
my $shadow = ($header =~ s/^\*//);
|
my $shadow = ($header =~ s/^\*//);
|
||||||
$header = 0 if($header =~ /^ui_.*.h/);
|
$header = 0 if($header =~ /^ui_.*.h/);
|
||||||
@ -979,11 +1011,11 @@ foreach my $lib (@modules_to_sync) {
|
|||||||
# class =~ s,::,/,g;
|
# class =~ s,::,/,g;
|
||||||
# }
|
# }
|
||||||
$class_lib_map_contents .= "QT_CLASS_LIB($full_class, $lib, $header_base)\n";
|
$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
|
# KDE-Compat headers for Phonon
|
||||||
if ($lib eq "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) {
|
} elsif ($create_private_headers) {
|
||||||
@ -994,7 +1026,7 @@ foreach my $lib (@modules_to_sync) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach(@headers) { #sync them
|
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) {
|
if($public_header) {
|
||||||
@ -1023,9 +1055,29 @@ foreach my $lib (@modules_to_sync) {
|
|||||||
$pri_install_pfiles.= "$pri_install_iheader ";;
|
$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) {
|
if($master_include && $master_contents) {
|
||||||
my $master_dir = dirname($master_include);
|
my $master_dir = dirname($master_include);
|
||||||
mkpath $master_dir, !$quiet;
|
make_path($master_dir, $lib, $verbose_level);
|
||||||
print "header (master) created for $lib\n" unless $quiet;
|
|
||||||
open MASTERINCLUDE, ">$master_include";
|
open MASTERINCLUDE, ">$master_include";
|
||||||
print MASTERINCLUDE $master_contents;
|
print MASTERINCLUDE $master_contents;
|
||||||
close MASTERINCLUDE;
|
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) {
|
if($headers_pri_file && $master_contents) {
|
||||||
my $headers_pri_dir = dirname($headers_pri_file);
|
my $headers_pri_dir = dirname($headers_pri_file);
|
||||||
mkpath $headers_pri_dir, !$quiet;
|
make_path($headers_pri_dir, $lib, $verbose_level);
|
||||||
print "headers.pri file created for $lib\n" unless $quiet;
|
|
||||||
open HEADERS_PRI_FILE, ">$headers_pri_file";
|
open HEADERS_PRI_FILE, ">$headers_pri_file";
|
||||||
print HEADERS_PRI_FILE $headers_pri_contents;
|
print HEADERS_PRI_FILE $headers_pri_contents;
|
||||||
close HEADERS_PRI_FILE;
|
close HEADERS_PRI_FILE;
|
||||||
|
print "$lib: created headers.pri file\n" if($verbose_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
# create forwarding module pri in qtbase/mkspecs/modules
|
# create forwarding module pri in qtbase/mkspecs/modules
|
||||||
@ -1088,7 +1140,7 @@ foreach my $lib (@modules_to_sync) {
|
|||||||
my $modulepri = $modulepris{$lib};
|
my $modulepri = $modulepris{$lib};
|
||||||
if (-e $modulepri) {
|
if (-e $modulepri) {
|
||||||
my $modulepriname = basename($modulepri);
|
my $modulepriname = basename($modulepri);
|
||||||
mkpath($module_fwd);
|
make_path($module_fwd, $lib, $verbose_level);
|
||||||
my $moduleprifwd = "$module_fwd/$modulepriname";
|
my $moduleprifwd = "$module_fwd/$modulepriname";
|
||||||
my $mod_base = $developer_build ? $basedir : $out_basedir;
|
my $mod_base = $developer_build ? $basedir : $out_basedir;
|
||||||
my $mod_component_base = $developer_build ? $qtbasedir : $out_basedir;
|
my $mod_component_base = $developer_build ? $qtbasedir : $out_basedir;
|
||||||
@ -1114,7 +1166,7 @@ foreach my $lib (@modules_to_sync) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elsif ($modulepri) {
|
} 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) {
|
if($class_lib_map) {
|
||||||
my $class_lib_map_dir = dirname($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";
|
open CLASS_LIB_MAP, ">$class_lib_map";
|
||||||
print CLASS_LIB_MAP $class_lib_map_contents;
|
print CLASS_LIB_MAP $class_lib_map_contents;
|
||||||
close CLASS_LIB_MAP;
|
close CLASS_LIB_MAP;
|
||||||
@ -1216,7 +1268,7 @@ if($check_includes) {
|
|||||||
if($include) {
|
if($include) {
|
||||||
for my $trylib (keys(%modules)) {
|
for my $trylib (keys(%modules)) {
|
||||||
if(-e "$out_basedir/include/$trylib/$include") {
|
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 ($header_skip_qt_begin_header_test == 0) {
|
||||||
if ($qt_begin_header_found == 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) {
|
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 ($header_skip_qt_begin_namespace_test == 0) {
|
||||||
if ($qt_begin_namespace_found == 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) {
|
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 ($header_skip_qt_module_test == 0) {
|
||||||
if ($qt_module_found == 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);
|
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;
|
exit 0;
|
||||||
|
10
configure
vendored
10
configure
vendored
@ -2577,7 +2577,7 @@ if [ "$OPT_SHADOW" = "yes" ]; then
|
|||||||
chmod 755 "$outpath/bin/syncqt"
|
chmod 755 "$outpath/bin/syncqt"
|
||||||
fi
|
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"
|
rm -f "$outpath/bin/$i"
|
||||||
if [ -x "$relpath/bin/$i" ]; then
|
if [ -x "$relpath/bin/$i" ]; then
|
||||||
mkdir -p "$outpath/bin"
|
mkdir -p "$outpath/bin"
|
||||||
@ -2970,7 +2970,7 @@ if [ '!' -f "${XQMAKESPEC}/qplatformdefs.h" ]; then
|
|||||||
echo
|
echo
|
||||||
echo " $XQMAKESPEC/qplatformdefs.h"
|
echo " $XQMAKESPEC/qplatformdefs.h"
|
||||||
echo
|
echo
|
||||||
echo " Please contact qt-bugs@trolltech.com."
|
echo " Please contact qt-info@nokia.com."
|
||||||
echo
|
echo
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
@ -6911,7 +6911,7 @@ fi
|
|||||||
# For "-carbon" builds: 32 bit x86/ppc.
|
# For "-carbon" builds: 32 bit x86/ppc.
|
||||||
# For builds on snow leopard : compiler default (64-bit).
|
# For builds on snow leopard : compiler default (64-bit).
|
||||||
# For builds on leopard : compiler default (32-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"
|
source "$mactests/defaultarch.test" "$TEST_COMPILER" "$OPT_VERBOSE" "$mactests"
|
||||||
|
|
||||||
if [ "$CFG_MAC_CARBON" = "yes" ]; then
|
if [ "$CFG_MAC_CARBON" = "yes" ]; then
|
||||||
@ -7150,7 +7150,7 @@ fi
|
|||||||
[ "$CFG_AVX" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG avx"
|
[ "$CFG_AVX" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG avx"
|
||||||
[ "$CFG_IWMMXT" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG iwmmxt"
|
[ "$CFG_IWMMXT" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG iwmmxt"
|
||||||
[ "$CFG_NEON" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG neon"
|
[ "$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
|
if [ "$CFG_CLOCK_GETTIME" = "yes" ]; then
|
||||||
QT_CONFIG="$QT_CONFIG clock-gettime"
|
QT_CONFIG="$QT_CONFIG clock-gettime"
|
||||||
fi
|
fi
|
||||||
@ -8617,7 +8617,7 @@ else
|
|||||||
echo "Building for: $XPLATFORM"
|
echo "Building for: $XPLATFORM"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$PLATFORM_MAC" = "yes" ]; then
|
if [ ! -z "$CFG_MAC_ARCHS" ]; then
|
||||||
echo "Architecture: $CFG_ARCH ($CFG_MAC_ARCHS )"
|
echo "Architecture: $CFG_ARCH ($CFG_MAC_ARCHS )"
|
||||||
else
|
else
|
||||||
echo "Architecture: $CFG_ARCH"
|
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
|
- Unite clipping support has been removed from QPainter. The alternative is
|
||||||
to unite QRegion's and using the result on QPainter.
|
to unite QRegion's and using the result on QPainter.
|
||||||
|
|
||||||
|
- QLibrary::resolve() now returns a function pointer instead of a void
|
||||||
|
pointer.
|
||||||
|
|
||||||
****************************************************************************
|
****************************************************************************
|
||||||
* General *
|
* General *
|
||||||
****************************************************************************
|
****************************************************************************
|
||||||
|
@ -316,7 +316,7 @@
|
|||||||
Now we construct the \c FlippablePad item, passing its column-row count to
|
Now we construct the \c FlippablePad item, passing its column-row count to
|
||||||
its constructor.
|
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.
|
QGraphicsRotation object for each of these.
|
||||||
|
|
||||||
\list
|
\list
|
||||||
|
@ -54,7 +54,7 @@ LocationDialog::LocationDialog(QWidget *parent)
|
|||||||
scopeComboBox->addItem(tr("System"));
|
scopeComboBox->addItem(tr("System"));
|
||||||
|
|
||||||
organizationComboBox = new QComboBox;
|
organizationComboBox = new QComboBox;
|
||||||
organizationComboBox->addItem(tr("Trolltech"));
|
organizationComboBox->addItem(tr("Qt"));
|
||||||
organizationComboBox->setEditable(true);
|
organizationComboBox->setEditable(true);
|
||||||
|
|
||||||
applicationComboBox = new QComboBox;
|
applicationComboBox = new QComboBox;
|
||||||
|
@ -39,4 +39,4 @@ qmake -spec macx-xcode
|
|||||||
|
|
||||||
Then open the generated Xcode project in Xcode and build it.
|
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.
|
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"
|
### Qt 5: remove "uic" and "resources" - or add "qt"
|
||||||
CONFIG = lex yacc warn_on debug uic resources $$CONFIG
|
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_)
|
PRO_BASENAME = $$basename(_PRO_FILE_)
|
||||||
|
|
||||||
# Try to detect proper QTDIR path. We require QTDIR, as syncqt uses that to create qt_module.pri
|
# 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)
|
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)
|
!silent:message($$MSG)
|
||||||
system($$MSG) {
|
system($$MSG) {
|
||||||
# success! Nothing to do
|
# success! Nothing to do
|
||||||
|
@ -140,7 +140,7 @@ defineTest(qtAddModule) {
|
|||||||
}
|
}
|
||||||
isEmpty(LINKAGE) {
|
isEmpty(LINKAGE) {
|
||||||
# Make sure we can link to uninstalled libraries
|
# Make sure we can link to uninstalled libraries
|
||||||
!isEqual(MODULE_LIBS, $[QT_INSTALL_LIBS]) {
|
!isEqual(MODULE_LIBS, $$[QT_INSTALL_LIBS]) {
|
||||||
QMAKE_LIBDIR *= $$MODULE_LIBS
|
QMAKE_LIBDIR *= $$MODULE_LIBS
|
||||||
unix:!mac:QMAKE_LFLAGS *= "-Wl,-rpath-link,$$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
|
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_LUPDATE, lupdate)
|
||||||
qtPrepareTool(QMAKE_LRELEASE, lrelease)
|
qtPrepareTool(QMAKE_LRELEASE, lrelease)
|
||||||
|
|
||||||
|
@ -1382,16 +1382,15 @@ QMakeProject::read(uchar cmd)
|
|||||||
read(Option::mkfile::cachefile, base_vars);
|
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
|
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
|
//get a default
|
||||||
if(pfile != "-" && vars["TARGET"].isEmpty())
|
if(pfile != "-" && vars["TARGET"].isEmpty())
|
||||||
vars["TARGET"].append(QFileInfo(pfile).baseName());
|
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
|
win32:syncqt.files=$$QT_BUILD_TREE/bin/syncqt.bat
|
||||||
INSTALLS += syncqt
|
INSTALLS += syncqt
|
||||||
|
|
||||||
|
#qtmodule-configtests
|
||||||
|
configtests.path=$$[QT_INSTALL_BINS]
|
||||||
|
configtests.files=$$QT_BUILD_TREE/bin/qtmodule-configtests
|
||||||
|
INSTALLS += configtests
|
||||||
|
|
||||||
#mkspecs
|
#mkspecs
|
||||||
mkspecs.path=$$[QT_INSTALL_DATA]/mkspecs
|
mkspecs.path=$$[QT_INSTALL_DATA]/mkspecs
|
||||||
mkspecs.files=$$QT_BUILD_TREE/mkspecs/qconfig.pri $$files($$QT_SOURCE_TREE/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);
|
int HB_GetUnicodeCharCombiningClass(HB_UChar32 ch);
|
||||||
HB_UChar16 HB_GetMirroredChar(HB_UChar16 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
|
HB_END_HEADER
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ void HB_GetGraphemeAndLineBreakClass(HB_UChar32 ch, HB_GraphemeClass *grapheme,
|
|||||||
*lineBreak = (HB_LineBreakClass) prop->line_break_class;
|
*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);
|
return QLibrary::resolve(library, version, symbol);
|
||||||
}
|
}
|
||||||
|
@ -75,13 +75,34 @@ inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
|
|||||||
return testAndSetOrdered(expectedValue, 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;
|
int returnValue = _q_value;
|
||||||
_q_value += valueToAdd;
|
_q_value += valueToAdd;
|
||||||
return returnValue;
|
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>
|
template <typename T>
|
||||||
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
|
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
|
||||||
{
|
{
|
||||||
|
@ -718,6 +718,13 @@ QT_BEGIN_NAMESPACE
|
|||||||
\sa QtMsgHandler, qInstallMsgHandler()
|
\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)
|
/*! \macro qint64 Q_INT64_C(literal)
|
||||||
\relates <QtGlobal>
|
\relates <QtGlobal>
|
||||||
|
|
||||||
|
@ -281,7 +281,7 @@ namespace QT_NAMESPACE {}
|
|||||||
# define Q_OS_VXWORKS
|
# define Q_OS_VXWORKS
|
||||||
#elif defined(__MAKEDEPEND__)
|
#elif defined(__MAKEDEPEND__)
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINCE)
|
#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINCE)
|
||||||
@ -794,7 +794,7 @@ namespace QT_NAMESPACE {}
|
|||||||
# define Q_CC_NOKIAX86
|
# define Q_CC_NOKIAX86
|
||||||
|
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -1807,6 +1807,8 @@ Q_CORE_EXPORT void qt_message_output(QtMsgType, const char *buf);
|
|||||||
typedef void (*QtMsgHandler)(QtMsgType, const char *);
|
typedef void (*QtMsgHandler)(QtMsgType, const char *);
|
||||||
Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
|
Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
|
||||||
|
|
||||||
|
typedef void (*QFunctionPointer)();
|
||||||
|
|
||||||
#if !defined(Q_UNIMPLEMENTED)
|
#if !defined(Q_UNIMPLEMENTED)
|
||||||
# define Q_UNIMPLEMENTED() qWarning("%s:%d: %s: Unimplemented code.", __FILE__, __LINE__, Q_FUNC_INFO)
|
# define Q_UNIMPLEMENTED() qWarning("%s:%d: %s: Unimplemented code.", __FILE__, __LINE__, Q_FUNC_INFO)
|
||||||
#endif
|
#endif
|
||||||
|
@ -131,7 +131,7 @@
|
|||||||
# define __NR_inotify_rm_watch 286
|
# define __NR_inotify_rm_watch 286
|
||||||
# define __NR_inotify_init1 328
|
# define __NR_inotify_init1 328
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
#if !defined(IN_CLOEXEC) && defined(O_CLOEXEC) && defined(__NR_inotify_init1)
|
#if !defined(IN_CLOEXEC) && defined(O_CLOEXEC) && defined(__NR_inotify_init1)
|
||||||
|
@ -45,109 +45,10 @@
|
|||||||
#include "qthread.h"
|
#include "qthread.h"
|
||||||
#include <private/qthread_p.h>
|
#include <private/qthread_p.h>
|
||||||
#include <private/qcoreapplication_p.h>
|
#include <private/qcoreapplication_p.h>
|
||||||
|
#include <private/qfreelist_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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()
|
void QAbstractEventDispatcherPrivate::init()
|
||||||
{
|
{
|
||||||
Q_Q(QAbstractEventDispatcher);
|
Q_Q(QAbstractEventDispatcher);
|
||||||
@ -158,79 +59,54 @@ void QAbstractEventDispatcherPrivate::init()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer IDs are implemented using a free-list;
|
// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
|
||||||
// there's a vector initialized with:
|
struct QtTimerIdFreeListConstants : public QFreeListDefaultConstants
|
||||||
// X[i] = i + 1
|
{
|
||||||
// and nextFreeTimerId starts with 1.
|
enum
|
||||||
//
|
{
|
||||||
// Allocating a timer ID involves taking the ID from
|
InitialNextValue = 1,
|
||||||
// X[nextFreeTimerId]
|
BlockCount = 6,
|
||||||
// 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
|
static const int Sizes[BlockCount];
|
||||||
// free list). As an added protection, we use the cell to store an invalid
|
};
|
||||||
// (negative) value that we can later check for integrity.
|
|
||||||
//
|
enum {
|
||||||
// (continues below).
|
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 QAbstractEventDispatcherPrivate::allocateTimerId()
|
||||||
{
|
{
|
||||||
int timerId, newTimerId;
|
return timerIdFreeList()->next();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
|
||||||
{
|
{
|
||||||
int which = timerId & TimerIdMask;
|
timerIdFreeList()->release(timerId);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -859,20 +859,31 @@ QMetaProperty QMetaObject::property(int index) const
|
|||||||
if (flags & EnumOrFlag) {
|
if (flags & EnumOrFlag) {
|
||||||
result.menum = enumerator(indexOfEnumerator(type));
|
result.menum = enumerator(indexOfEnumerator(type));
|
||||||
if (!result.menum.isValid()) {
|
if (!result.menum.isValid()) {
|
||||||
QByteArray enum_name = type;
|
const char *enum_name = type;
|
||||||
QByteArray scope_name = d.stringdata;
|
const char *scope_name = d.stringdata;
|
||||||
int s = enum_name.lastIndexOf("::");
|
char *scope_buffer = 0;
|
||||||
if (s > 0) {
|
|
||||||
scope_name = enum_name.left(s);
|
const char *colon = strrchr(enum_name, ':');
|
||||||
enum_name = enum_name.mid(s + 2);
|
// ':' 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;
|
const QMetaObject *scope = 0;
|
||||||
if (scope_name == "Qt")
|
if (qstrcmp(scope_name, "Qt") == 0)
|
||||||
scope = &QObject::staticQtMetaObject;
|
scope = &QObject::staticQtMetaObject;
|
||||||
else
|
else
|
||||||
scope = QMetaObject_findMetaObject(this, scope_name);
|
scope = QMetaObject_findMetaObject(this, scope_name);
|
||||||
if (scope)
|
if (scope)
|
||||||
result.menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
|
result.menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
|
||||||
|
if (scope_buffer)
|
||||||
|
qFree(scope_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,8 @@ enum MethodFlags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum MetaObjectFlags {
|
enum MetaObjectFlags {
|
||||||
DynamicMetaObject = 0x01
|
DynamicMetaObject = 0x01,
|
||||||
|
RequiresVariantMetaObject = 0x02
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMutex;
|
class QMutex;
|
||||||
|
@ -60,7 +60,6 @@
|
|||||||
#include <qsharedpointer.h>
|
#include <qsharedpointer.h>
|
||||||
|
|
||||||
#include <private/qorderedmutexlocker_p.h>
|
#include <private/qorderedmutexlocker_p.h>
|
||||||
#include <private/qmutexpool_p.h>
|
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
@ -95,35 +94,22 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
|
|||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0);
|
static QBasicMutex _q_ObjectMutexPool[131];
|
||||||
static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
|
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* mutex to be locked when accessing the connectionlists or the senders list
|
* mutex to be locked when accessing the connectionlists or the senders list
|
||||||
*/
|
*/
|
||||||
static inline QMutex *signalSlotLock(const QObject *o)
|
static inline QMutex *signalSlotLock(const QObject *o)
|
||||||
{
|
{
|
||||||
if (!signalSlotMutexes) {
|
return static_cast<QMutex *>(&_q_ObjectMutexPool[
|
||||||
QMutexPool *mp = new QMutexPool;
|
uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]);
|
||||||
if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
|
|
||||||
delete mp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return signalSlotMutexes->get(o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
|
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
|
||||||
{
|
{}
|
||||||
objectCount.ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
|
extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
|
||||||
{
|
{}
|
||||||
if(!objectCount.deref()) {
|
|
||||||
QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0);
|
|
||||||
delete old;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct QConnectionSenderSwitcher {
|
struct QConnectionSenderSwitcher {
|
||||||
QObject *receiver;
|
QObject *receiver;
|
||||||
@ -879,7 +865,7 @@ QObject::~QObject()
|
|||||||
if (c->next) c->next->prev = c->prev;
|
if (c->next) c->next->prev = c->prev;
|
||||||
}
|
}
|
||||||
if (needToUnlock)
|
if (needToUnlock)
|
||||||
m->unlockInline();
|
m->unlock();
|
||||||
|
|
||||||
connectionList.first = c->nextConnectionList;
|
connectionList.first = c->nextConnectionList;
|
||||||
delete c;
|
delete c;
|
||||||
@ -903,7 +889,7 @@ QObject::~QObject()
|
|||||||
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
|
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
|
||||||
//the node has maybe been removed while the mutex was unlocked in relock?
|
//the node has maybe been removed while the mutex was unlocked in relock?
|
||||||
if (!node || node->sender != sender) {
|
if (!node || node->sender != sender) {
|
||||||
m->unlockInline();
|
m->unlock();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
node->receiver = 0;
|
node->receiver = 0;
|
||||||
@ -913,7 +899,7 @@ QObject::~QObject()
|
|||||||
|
|
||||||
node = node->next;
|
node = node->next;
|
||||||
if (needToUnlock)
|
if (needToUnlock)
|
||||||
m->unlockInline();
|
m->unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3077,7 +3063,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (needToUnlock)
|
if (needToUnlock)
|
||||||
receiverMutex->unlockInline();
|
receiverMutex->unlock();
|
||||||
|
|
||||||
c->receiver = 0;
|
c->receiver = 0;
|
||||||
|
|
||||||
|
@ -447,7 +447,7 @@ QLibraryPrivate::~QLibraryPrivate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *QLibraryPrivate::resolve(const char *symbol)
|
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
|
||||||
{
|
{
|
||||||
if (!pHnd)
|
if (!pHnd)
|
||||||
return 0;
|
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
|
Note: In Symbian resolving with symbol names works only if the loaded
|
||||||
library was built as STDDLL. Otherwise, the ordinals must be used.
|
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())
|
if (!isLoaded() && !load())
|
||||||
return 0;
|
return 0;
|
||||||
@ -1152,7 +1152,7 @@ void *QLibrary::resolve(const char *symbol)
|
|||||||
|
|
||||||
\sa resolve()
|
\sa resolve()
|
||||||
*/
|
*/
|
||||||
void *QLibrary::resolve(const QString &fileName, const char *symbol)
|
QFunctionPointer QLibrary::resolve(const QString &fileName, const char *symbol)
|
||||||
{
|
{
|
||||||
QLibrary library(fileName);
|
QLibrary library(fileName);
|
||||||
return library.resolve(symbol);
|
return library.resolve(symbol);
|
||||||
@ -1175,7 +1175,7 @@ void *QLibrary::resolve(const QString &fileName, const char *symbol)
|
|||||||
|
|
||||||
\sa resolve()
|
\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);
|
QLibrary library(fileName, verNum);
|
||||||
return library.resolve(symbol);
|
return library.resolve(symbol);
|
||||||
@ -1199,7 +1199,7 @@ void *QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
|
|||||||
|
|
||||||
\sa resolve()
|
\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);
|
QLibrary library(fileName, version);
|
||||||
return library.resolve(symbol);
|
return library.resolve(symbol);
|
||||||
|
@ -79,10 +79,10 @@ public:
|
|||||||
explicit QLibrary(const QString& fileName, const QString &version, QObject *parent = 0);
|
explicit QLibrary(const QString& fileName, const QString &version, QObject *parent = 0);
|
||||||
~QLibrary();
|
~QLibrary();
|
||||||
|
|
||||||
void *resolve(const char *symbol);
|
QFunctionPointer resolve(const char *symbol);
|
||||||
static void *resolve(const QString &fileName, const char *symbol);
|
static QFunctionPointer resolve(const QString &fileName, const char *symbol);
|
||||||
static void *resolve(const QString &fileName, int verNum, const char *symbol);
|
static QFunctionPointer resolve(const QString &fileName, int verNum, const char *symbol);
|
||||||
static void *resolve(const QString &fileName, const QString &version, const char *symbol);
|
static QFunctionPointer resolve(const QString &fileName, const QString &version, const char *symbol);
|
||||||
|
|
||||||
bool load();
|
bool load();
|
||||||
bool unload();
|
bool unload();
|
||||||
|
@ -87,7 +87,7 @@ public:
|
|||||||
bool loadPlugin(); // loads and resolves instance
|
bool loadPlugin(); // loads and resolves instance
|
||||||
bool unload();
|
bool unload();
|
||||||
void release();
|
void release();
|
||||||
void *resolve(const char *);
|
QFunctionPointer resolve(const char *);
|
||||||
|
|
||||||
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
|
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ private:
|
|||||||
|
|
||||||
bool load_sys();
|
bool load_sys();
|
||||||
bool unload_sys();
|
bool unload_sys();
|
||||||
void *resolve_sys(const char *);
|
QFunctionPointer resolve_sys(const char *);
|
||||||
|
|
||||||
QAtomicInt libraryRefCount;
|
QAtomicInt libraryRefCount;
|
||||||
QAtomicInt libraryUnloadCount;
|
QAtomicInt libraryUnloadCount;
|
||||||
|
@ -267,29 +267,29 @@ bool QLibraryPrivate::unload_sys()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#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
|
#endif
|
||||||
|
|
||||||
void* QLibraryPrivate::resolve_sys(const char* symbol)
|
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
|
||||||
{
|
{
|
||||||
#if defined(QT_AOUT_UNDERSCORE)
|
#if defined(QT_AOUT_UNDERSCORE)
|
||||||
// older a.out systems add an underscore in front of symbols
|
// older a.out systems add an underscore in front of symbols
|
||||||
char* undrscr_symbol = new char[strlen(symbol)+2];
|
char* undrscr_symbol = new char[strlen(symbol)+2];
|
||||||
undrscr_symbol[0] = '_';
|
undrscr_symbol[0] = '_';
|
||||||
strcpy(undrscr_symbol+1, symbol);
|
strcpy(undrscr_symbol+1, symbol);
|
||||||
void* address = dlsym(pHnd, undrscr_symbol);
|
QFunctionPointer address = QFunctionPointer(dlsym(pHnd, undrscr_symbol));
|
||||||
delete [] undrscr_symbol;
|
delete [] undrscr_symbol;
|
||||||
#elif defined(QT_HPUX_LD)
|
#elif defined(QT_HPUX_LD)
|
||||||
void* address = 0;
|
QFunctionPointer address = 0;
|
||||||
if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0)
|
if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0)
|
||||||
address = 0;
|
address = 0;
|
||||||
#elif defined (QT_NO_DYNAMIC_LIBRARY)
|
#elif defined (QT_NO_DYNAMIC_LIBRARY)
|
||||||
void *address = 0;
|
QFunctionPointer address = 0;
|
||||||
#else
|
#else
|
||||||
void* address = dlsym(pHnd, symbol);
|
QFunctionPointer address = QFunctionPointer(dlsym(pHnd, symbol));
|
||||||
#endif
|
#endif
|
||||||
if (!address) {
|
if (!address) {
|
||||||
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
|
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
|
||||||
|
@ -113,12 +113,12 @@ bool QLibraryPrivate::unload_sys()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* QLibraryPrivate::resolve_sys(const char* symbol)
|
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINCE
|
#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
|
#else
|
||||||
void* address = (void*)GetProcAddress(pHnd, symbol);
|
FARPROC address = GetProcAddress(pHnd, symbol);
|
||||||
#endif
|
#endif
|
||||||
if (!address) {
|
if (!address) {
|
||||||
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
|
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
|
||||||
@ -126,6 +126,6 @@ void* QLibraryPrivate::resolve_sys(const char* symbol)
|
|||||||
} else {
|
} else {
|
||||||
errorString.clear();
|
errorString.clear();
|
||||||
}
|
}
|
||||||
return address;
|
return QFunctionPointer(address);
|
||||||
}
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -78,20 +78,20 @@ public:
|
|||||||
return (m_handle != 0);
|
return (m_handle != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *resolve(const char *symbol)
|
QFunctionPointer resolve(const char *symbol)
|
||||||
{
|
{
|
||||||
if (!m_didLoad)
|
if (!m_didLoad)
|
||||||
load();
|
load();
|
||||||
if (!m_handle)
|
if (!m_handle)
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef Q_OS_WINCE
|
#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
|
#else
|
||||||
return (void*)GetProcAddress(m_handle, symbol);
|
return QFunctionPointer(GetProcAddress(m_handle, symbol));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *resolve(const QString &libraryName, const char *symbol)
|
static QFunctionPointer resolve(const QString &libraryName, const char *symbol)
|
||||||
{
|
{
|
||||||
return QSystemLibrary(libraryName).resolve(symbol);
|
return QSystemLibrary(libraryName).resolve(symbol);
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,25 @@
|
|||||||
#include "qthread.h"
|
#include "qthread.h"
|
||||||
#include "qmutex_p.h"
|
#include "qmutex_p.h"
|
||||||
|
|
||||||
|
#ifndef Q_OS_LINUX
|
||||||
|
#include "private/qfreelist_p.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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
|
\class QMutex
|
||||||
\brief The QMutex class provides access serialization between threads.
|
\brief The QMutex class provides access serialization between threads.
|
||||||
@ -122,8 +139,12 @@ QT_BEGIN_NAMESPACE
|
|||||||
\sa lock(), unlock()
|
\sa lock(), unlock()
|
||||||
*/
|
*/
|
||||||
QMutex::QMutex(RecursionMode mode)
|
QMutex::QMutex(RecursionMode mode)
|
||||||
: d(new QMutexPrivate(mode))
|
{
|
||||||
{ }
|
if (mode == Recursive)
|
||||||
|
d = new QRecursiveMutexPrivate;
|
||||||
|
else
|
||||||
|
d = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Destroys the mutex.
|
Destroys the mutex.
|
||||||
@ -131,9 +152,18 @@ QMutex::QMutex(RecursionMode mode)
|
|||||||
\warning Destroying a locked mutex may result in undefined behavior.
|
\warning Destroying a locked mutex may result in undefined behavior.
|
||||||
*/
|
*/
|
||||||
QMutex::~QMutex()
|
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
|
Locks the mutex. If another thread has locked the mutex then this
|
||||||
call will block until that thread has unlocked it.
|
call will block until that thread has unlocked it.
|
||||||
|
|
||||||
@ -145,40 +175,8 @@ QMutex::~QMutex()
|
|||||||
|
|
||||||
\sa unlock()
|
\sa unlock()
|
||||||
*/
|
*/
|
||||||
void QMutex::lock()
|
|
||||||
{
|
|
||||||
QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
|
|
||||||
Qt::HANDLE self;
|
|
||||||
|
|
||||||
if (d->recursive) {
|
/*!\fn bool QMutex::trylock()
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Attempts to lock the mutex. If the lock was obtained, this function
|
Attempts to lock the mutex. If the lock was obtained, this function
|
||||||
returns true. If another thread has locked the mutex, this
|
returns true. If another thread has locked the mutex, this
|
||||||
function returns false immediately.
|
function returns false immediately.
|
||||||
@ -195,36 +193,9 @@ void QMutex::lock()
|
|||||||
|
|
||||||
\sa lock(), unlock()
|
\sa lock(), unlock()
|
||||||
*/
|
*/
|
||||||
bool QMutex::tryLock()
|
|
||||||
{
|
|
||||||
QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
|
|
||||||
Qt::HANDLE self;
|
|
||||||
|
|
||||||
if (d->recursive) {
|
/*! \fn bool QMutex::tryLock(int timeout)
|
||||||
self = QThread::currentThreadId();
|
\overload
|
||||||
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
|
|
||||||
|
|
||||||
Attempts to lock the mutex. This function returns true if the lock
|
Attempts to lock the mutex. This function returns true if the lock
|
||||||
was obtained; otherwise it returns false. If another thread has
|
was obtained; otherwise it returns false. If another thread has
|
||||||
@ -247,81 +218,30 @@ bool QMutex::tryLock()
|
|||||||
|
|
||||||
\sa lock(), unlock()
|
\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
|
Unlocks the mutex. Attempting to unlock a mutex in a different
|
||||||
thread to the one that locked it results in an error. Unlocking a
|
thread to the one that locked it results in an error. Unlocking a
|
||||||
mutex that is not locked results in undefined behavior.
|
mutex that is not locked results in undefined behavior.
|
||||||
|
|
||||||
\sa lock()
|
\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 true if the mutex is recursive
|
||||||
returns false.
|
|
||||||
|
|
||||||
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
|
\class QMutexLocker
|
||||||
@ -418,96 +338,217 @@ void QMutex::unlock()
|
|||||||
\sa unlock()
|
\sa unlock()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef Q_OS_LINUX //linux implementation is in qmutex_linux.cpp
|
||||||
/*!
|
/*!
|
||||||
\fn QMutex::QMutex(bool recursive)
|
\internal helper for lock()
|
||||||
|
|
||||||
Use the constructor that takes a RecursionMode parameter instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\internal helper for lockInline()
|
|
||||||
*/
|
*/
|
||||||
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) {
|
if (d == dummyLocked()) {
|
||||||
// don't spin on single cpu machines
|
if (timeout == 0)
|
||||||
bool isLocked = d->wait();
|
return false;
|
||||||
Q_ASSERT_X(isLocked, "QMutex::lock",
|
QMutexPrivate *newD = QMutexPrivate::allocate();
|
||||||
"Internal error, infinite wait has timed out.");
|
if (!this->d.testAndSetOrdered(d, newD)) {
|
||||||
Q_UNUSED(isLocked);
|
//Either the mutex is already unlocked, or another thread already set it.
|
||||||
return;
|
newD->deref();
|
||||||
}
|
continue;
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
d = newD;
|
||||||
// adjust the spin count when spinning does not benefit contention performance
|
//the d->refCount is already 1 the deref will occurs when we unlock
|
||||||
if ((spinTime + actualWaitTime) - qint64(QMutexPrivate::MaximumSpinTimeThreshold) >= qint64(QMutexPrivate::MaximumSpinTimeThreshold)) {
|
} else if (d->recursive) {
|
||||||
// long waits, stop spinning
|
return static_cast<QRecursiveMutexPrivate *>(d)->lock(timeout);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
// 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)
|
if (timeout == 0 && !d->possiblyUnlocked)
|
||||||
qint64 maximumSpinTime = d->maximumSpinTime;
|
return false;
|
||||||
qint64 spinTime = elapsedTimer.nsecsElapsed();
|
|
||||||
if (spinTime < maximumSpinTime / 2) {
|
if (!d->ref())
|
||||||
// we are using much less time than we need, adjust the limit
|
continue; //that QMutexPrivate was already released
|
||||||
d->maximumSpinTime = qBound(qint64(d->averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
|
|
||||||
|
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
|
\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
|
\internal
|
||||||
inline version of QMutex::lock()
|
*/
|
||||||
*/
|
void QRecursiveMutexPrivate::unlock()
|
||||||
|
{
|
||||||
/*!
|
if (count > 0) {
|
||||||
\fn QMutex::unlockInline()
|
count--;
|
||||||
\internal
|
} else {
|
||||||
inline version of QMutex::unlock()
|
owner = 0;
|
||||||
*/
|
mutex.unlock();
|
||||||
|
}
|
||||||
/*!
|
}
|
||||||
\fn QMutex::tryLockInline()
|
|
||||||
\internal
|
|
||||||
inline version of QMutex::tryLock()
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -52,47 +52,64 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
QT_MODULE(Core)
|
QT_MODULE(Core)
|
||||||
|
|
||||||
#ifndef QT_NO_THREAD
|
#if !defined(QT_NO_THREAD) && !defined(qdoc)
|
||||||
|
|
||||||
class QAtomicInt;
|
class QMutexPrivate;
|
||||||
class QMutexData;
|
|
||||||
|
|
||||||
class Q_CORE_EXPORT QMutex
|
class Q_CORE_EXPORT QBasicMutex
|
||||||
{
|
{
|
||||||
friend class QWaitCondition;
|
|
||||||
friend class QWaitConditionPrivate;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum RecursionMode { NonRecursive, Recursive };
|
inline void lock() {
|
||||||
|
if (!fastTryLock())
|
||||||
|
lockInternal();
|
||||||
|
}
|
||||||
|
|
||||||
explicit QMutex(RecursionMode mode = NonRecursive);
|
inline void unlock() {
|
||||||
~QMutex();
|
Q_ASSERT(d); //mutex must be locked
|
||||||
|
if (!d.testAndSetRelease(dummyLocked(), 0))
|
||||||
|
unlockInternal();
|
||||||
|
}
|
||||||
|
|
||||||
void lock(); //### Qt5: make inline;
|
bool tryLock(int timeout = 0) {
|
||||||
inline void lockInline();
|
return fastTryLock() || lockInternal(timeout);
|
||||||
bool tryLock(); //### Qt5: make inline;
|
}
|
||||||
bool tryLock(int timeout);
|
|
||||||
inline bool tryLockInline();
|
bool isRecursive();
|
||||||
void unlock(); //### Qt5: make inline;
|
|
||||||
inline void unlockInline();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void lockInternal();
|
inline bool fastTryLock() {
|
||||||
|
return d.testAndSetAcquire(0, dummyLocked());
|
||||||
|
}
|
||||||
|
bool lockInternal(int timeout = -1);
|
||||||
void unlockInternal();
|
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
|
class Q_CORE_EXPORT QMutexLocker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline explicit QMutexLocker(QMutex *m)
|
inline explicit QMutexLocker(QBasicMutex *m)
|
||||||
{
|
{
|
||||||
Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0),
|
Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0),
|
||||||
"QMutexLocker", "QMutex pointer is misaligned");
|
"QMutexLocker", "QMutex pointer is misaligned");
|
||||||
if (m) {
|
if (m) {
|
||||||
m->lockInline();
|
m->lock();
|
||||||
val = reinterpret_cast<quintptr>(m) | quintptr(1u);
|
val = reinterpret_cast<quintptr>(m) | quintptr(1u);
|
||||||
} else {
|
} else {
|
||||||
val = 0;
|
val = 0;
|
||||||
@ -104,7 +121,7 @@ public:
|
|||||||
{
|
{
|
||||||
if ((val & quintptr(1u)) == quintptr(1u)) {
|
if ((val & quintptr(1u)) == quintptr(1u)) {
|
||||||
val &= ~quintptr(1u);
|
val &= ~quintptr(1u);
|
||||||
mutex()->unlockInline();
|
mutex()->unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +129,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (val) {
|
if (val) {
|
||||||
if ((val & quintptr(1u)) == quintptr(0u)) {
|
if ((val & quintptr(1u)) == quintptr(0u)) {
|
||||||
mutex()->lockInline();
|
mutex()->lock();
|
||||||
val |= quintptr(1u);
|
val |= quintptr(1u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,54 +155,9 @@ private:
|
|||||||
quintptr val;
|
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
|
class Q_CORE_EXPORT QMutex
|
||||||
@ -194,14 +166,11 @@ public:
|
|||||||
enum RecursionMode { NonRecursive, Recursive };
|
enum RecursionMode { NonRecursive, Recursive };
|
||||||
|
|
||||||
inline explicit QMutex(RecursionMode mode = NonRecursive) { Q_UNUSED(mode); }
|
inline explicit QMutex(RecursionMode mode = NonRecursive) { Q_UNUSED(mode); }
|
||||||
inline ~QMutex() {}
|
|
||||||
|
|
||||||
static inline void lock() {}
|
static inline void lock() {}
|
||||||
static inline void lockInline() {}
|
|
||||||
static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; }
|
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 unlock() {}
|
||||||
static inline void unlockInline() {}
|
static inline bool isRecursive() { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QMutex)
|
Q_DISABLE_COPY(QMutex)
|
||||||
@ -221,7 +190,9 @@ private:
|
|||||||
Q_DISABLE_COPY(QMutexLocker)
|
Q_DISABLE_COPY(QMutexLocker)
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QT_NO_THREAD
|
typedef QMutex QBasicMutex;
|
||||||
|
|
||||||
|
#endif // QT_NO_THREAD or qdoc
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
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/qglobal.h>
|
||||||
#include <QtCore/qnamespace.h>
|
#include <QtCore/qnamespace.h>
|
||||||
#include <QtCore/qmutex.h>
|
#include <QtCore/qmutex.h>
|
||||||
|
#include <QtCore/qatomic.h>
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
# include <mach/semaphore.h>
|
# include <mach/semaphore.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_SYMBIAN)
|
|
||||||
# include <e32std.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QMutexPrivate : public QMutexData {
|
class QMutexPrivate {
|
||||||
public:
|
public:
|
||||||
QMutexPrivate(QMutex::RecursionMode mode);
|
|
||||||
~QMutexPrivate();
|
~QMutexPrivate();
|
||||||
|
QMutexPrivate(QMutex::RecursionMode mode = QMutex::NonRecursive);
|
||||||
|
|
||||||
bool wait(int timeout = -1);
|
bool wait(int timeout = -1);
|
||||||
void wakeUp();
|
void wakeUp();
|
||||||
|
|
||||||
// 1ms = 1000000ns
|
#if !defined(Q_OS_LINUX)
|
||||||
enum { MaximumSpinTimeThreshold = 1000000 };
|
// Conrol the lifetime of the privates
|
||||||
volatile qint64 maximumSpinTime;
|
QAtomicInt refCount;
|
||||||
volatile qint64 averageWaitTime;
|
int id;
|
||||||
Qt::HANDLE owner;
|
|
||||||
uint count;
|
|
||||||
|
|
||||||
|
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)
|
#if defined(Q_OS_MAC)
|
||||||
semaphore_t mach_semaphore;
|
semaphore_t mach_semaphore;
|
||||||
#elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) && !defined(Q_OS_SYMBIAN)
|
#elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
|
||||||
volatile bool wakeup;
|
bool wakeup;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
#elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
|
#elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
#elif defined(Q_OS_SYMBIAN)
|
|
||||||
RSemaphore lock;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QMutexData::QMutexData(QMutex::RecursionMode mode)
|
class QRecursiveMutexPrivate : public QMutexPrivate
|
||||||
: recursive(mode == QMutex::Recursive)
|
{
|
||||||
{}
|
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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -46,142 +46,35 @@
|
|||||||
#ifndef QT_NO_THREAD
|
#ifndef QT_NO_THREAD
|
||||||
#include "qatomic.h"
|
#include "qatomic.h"
|
||||||
#include "qmutex_p.h"
|
#include "qmutex_p.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#if defined(Q_OS_VXWORKS) && defined(wakeup)
|
#if defined(Q_OS_VXWORKS) && defined(wakeup)
|
||||||
#undef wakeup
|
#undef wakeup
|
||||||
#endif
|
#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
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
#if !defined(Q_OS_MAC) && !defined(Q_OS_LINUX)
|
|
||||||
static void report_error(int code, const char *where, const char *what)
|
static void report_error(int code, const char *where, const char *what)
|
||||||
{
|
{
|
||||||
if (code != 0)
|
if (code != 0)
|
||||||
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
|
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
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_mutex_init(&mutex, NULL), "QMutex", "mutex init");
|
||||||
report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
|
report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QMutexPrivate::~QMutexPrivate()
|
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_cond_destroy(&cond), "QMutex", "cv destroy");
|
||||||
report_error(pthread_mutex_destroy(&mutex), "QMutex", "mutex 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)
|
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");
|
report_error(pthread_mutex_lock(&mutex), "QMutex::lock", "mutex lock");
|
||||||
int errorCode = 0;
|
int errorCode = 0;
|
||||||
while (!wakeup) {
|
while (!wakeup) {
|
||||||
@ -190,12 +83,10 @@ bool QMutexPrivate::wait(int timeout)
|
|||||||
} else {
|
} else {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
|
|
||||||
timespec ti;
|
timespec ti;
|
||||||
ti.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000) * 1000;
|
ti.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000) * 1000;
|
||||||
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
||||||
ti.tv_nsec %= 1000000000;
|
ti.tv_nsec %= 1000000000;
|
||||||
|
|
||||||
errorCode = pthread_cond_timedwait(&cond, &mutex, &ti);
|
errorCode = pthread_cond_timedwait(&cond, &mutex, &ti);
|
||||||
}
|
}
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
@ -207,10 +98,10 @@ bool QMutexPrivate::wait(int timeout)
|
|||||||
report_error(errorCode, "QMutex::lock()", "cv wait");
|
report_error(errorCode, "QMutex::lock()", "cv wait");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool ret = wakeup;
|
||||||
wakeup = false;
|
wakeup = false;
|
||||||
report_error(pthread_mutex_unlock(&mutex), "QMutex::lock", "mutex unlock");
|
report_error(pthread_mutex_unlock(&mutex), "QMutex::lock", "mutex unlock");
|
||||||
contenders.deref();
|
return ret;
|
||||||
return errorCode == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMutexPrivate::wakeUp()
|
void QMutexPrivate::wakeUp()
|
||||||
@ -221,7 +112,6 @@ void QMutexPrivate::wakeUp()
|
|||||||
report_error(pthread_mutex_unlock(&mutex), "QMutex::unlock", "mutex unlock");
|
report_error(pthread_mutex_unlock(&mutex), "QMutex::unlock", "mutex unlock");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !Q_OS_MAC && !Q_OS_LINUX
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
||||||
: QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
|
: recursive(mode)
|
||||||
{
|
{
|
||||||
event = CreateEvent(0, FALSE, FALSE, 0);
|
event = CreateEvent(0, FALSE, FALSE, 0);
|
||||||
if (!event)
|
if (!event)
|
||||||
@ -60,13 +60,7 @@ QMutexPrivate::~QMutexPrivate()
|
|||||||
|
|
||||||
bool QMutexPrivate::wait(int timeout)
|
bool QMutexPrivate::wait(int timeout)
|
||||||
{
|
{
|
||||||
if (contenders.fetchAndAddAcquire(1) == 0) {
|
return (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
|
||||||
// lock acquired without waiting
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool returnValue = (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
|
|
||||||
contenders.deref();
|
|
||||||
return returnValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMutexPrivate::wakeUp()
|
void QMutexPrivate::wakeUp()
|
||||||
|
@ -79,8 +79,8 @@ public:
|
|||||||
void relock()
|
void relock()
|
||||||
{
|
{
|
||||||
if (!locked) {
|
if (!locked) {
|
||||||
if (mtx1) mtx1->lockInline();
|
if (mtx1) mtx1->lock();
|
||||||
if (mtx2) mtx2->lockInline();
|
if (mtx2) mtx2->lock();
|
||||||
locked = true;
|
locked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,8 +88,8 @@ public:
|
|||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
if (locked) {
|
if (locked) {
|
||||||
if (mtx1) mtx1->unlockInline();
|
if (mtx1) mtx1->unlock();
|
||||||
if (mtx2) mtx2->unlockInline();
|
if (mtx2) mtx2->unlock();
|
||||||
locked = false;
|
locked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,10 +100,10 @@ public:
|
|||||||
if (mtx1 == mtx2)
|
if (mtx1 == mtx2)
|
||||||
return false;
|
return false;
|
||||||
if (mtx1 < mtx2) {
|
if (mtx1 < mtx2) {
|
||||||
mtx2->lockInline();
|
mtx2->lock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!mtx2->tryLockInline()) {
|
if (!mtx2->tryLock()) {
|
||||||
mtx1->unlock();
|
mtx1->unlock();
|
||||||
mtx2->lock();
|
mtx2->lock();
|
||||||
mtx1->lock();
|
mtx1->lock();
|
||||||
|
@ -146,7 +146,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
|
|||||||
{
|
{
|
||||||
if (! mutex)
|
if (! mutex)
|
||||||
return false;
|
return false;
|
||||||
if (mutex->d->recursive) {
|
if (mutex->isRecursive()) {
|
||||||
qWarning("QWaitCondition: cannot wait on recursive mutexes");
|
qWarning("QWaitCondition: cannot wait on recursive mutexes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
|
|||||||
{
|
{
|
||||||
if (!mutex)
|
if (!mutex)
|
||||||
return false;
|
return false;
|
||||||
if (mutex->d->recursive) {
|
if (mutex->isRecursive()) {
|
||||||
qWarning("QWaitCondition::wait: Cannot wait on recursive mutexes");
|
qWarning("QWaitCondition::wait: Cannot wait on recursive mutexes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,7 @@ SOURCES += thread/qatomic.cpp \
|
|||||||
thread/qthread.cpp \
|
thread/qthread.cpp \
|
||||||
thread/qthreadstorage.cpp
|
thread/qthreadstorage.cpp
|
||||||
|
|
||||||
unix:!symbian:SOURCES += thread/qmutex_unix.cpp \
|
unix:!symbian:SOURCES += thread/qthread_unix.cpp \
|
||||||
thread/qthread_unix.cpp \
|
|
||||||
thread/qwaitcondition_unix.cpp
|
thread/qwaitcondition_unix.cpp
|
||||||
|
|
||||||
symbian:SOURCES += thread/qmutex_symbian.cpp \
|
symbian:SOURCES += thread/qmutex_symbian.cpp \
|
||||||
@ -39,3 +38,9 @@ win32:SOURCES += thread/qmutex_win.cpp \
|
|||||||
integrity:SOURCES += thread/qmutex_unix.cpp \
|
integrity:SOURCES += thread/qmutex_unix.cpp \
|
||||||
thread/qthread_unix.cpp \
|
thread/qthread_unix.cpp \
|
||||||
thread/qwaitcondition_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);
|
x = const_cast<Data *>(&shared_empty.ba);
|
||||||
} else {
|
} else {
|
||||||
int len = qstrlen(str);
|
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);
|
realloc(len);
|
||||||
x = d;
|
x = d;
|
||||||
memcpy(x->data(), str, len + 1); // include null terminator
|
memcpy(x->data(), str, len + 1); // include null terminator
|
||||||
@ -1432,9 +1432,10 @@ void QByteArray::resize(int size)
|
|||||||
x->data()[size] = '\0';
|
x->data()[size] = '\0';
|
||||||
d = x;
|
d = x;
|
||||||
} else {
|
} 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)));
|
realloc(qAllocMore(size, sizeof(Data)));
|
||||||
if (d->alloc >= size) {
|
if (int(d->alloc) >= size) {
|
||||||
d->size = size;
|
d->size = size;
|
||||||
d->data()[size] = '\0';
|
d->data()[size] = '\0';
|
||||||
}
|
}
|
||||||
@ -1563,7 +1564,7 @@ QByteArray &QByteArray::prepend(const char *str)
|
|||||||
QByteArray &QByteArray::prepend(const char *str, int len)
|
QByteArray &QByteArray::prepend(const char *str, int len)
|
||||||
{
|
{
|
||||||
if (str) {
|
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)));
|
realloc(qAllocMore(d->size + len, sizeof(Data)));
|
||||||
memmove(d->data()+len, d->data(), d->size);
|
memmove(d->data()+len, d->data(), d->size);
|
||||||
memcpy(d->data(), str, len);
|
memcpy(d->data(), str, len);
|
||||||
@ -1581,7 +1582,7 @@ QByteArray &QByteArray::prepend(const char *str, int len)
|
|||||||
|
|
||||||
QByteArray &QByteArray::prepend(char ch)
|
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)));
|
realloc(qAllocMore(d->size + 1, sizeof(Data)));
|
||||||
memmove(d->data()+1, d->data(), d->size);
|
memmove(d->data()+1, d->data(), d->size);
|
||||||
d->data()[0] = ch;
|
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)) {
|
if ((d == &shared_null.ba || d == &shared_empty.ba) && !IS_RAW_DATA(ba.d)) {
|
||||||
*this = ba;
|
*this = ba;
|
||||||
} else if (ba.d != &shared_null.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)));
|
realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
|
||||||
memcpy(d->data() + d->size, ba.d->data(), ba.d->size);
|
memcpy(d->data() + d->size, ba.d->data(), ba.d->size);
|
||||||
d->size += ba.d->size;
|
d->size += ba.d->size;
|
||||||
@ -1653,7 +1654,7 @@ QByteArray& QByteArray::append(const char *str)
|
|||||||
{
|
{
|
||||||
if (str) {
|
if (str) {
|
||||||
int len = qstrlen(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)));
|
realloc(qAllocMore(d->size + len, sizeof(Data)));
|
||||||
memcpy(d->data() + d->size, str, len + 1); // include null terminator
|
memcpy(d->data() + d->size, str, len + 1); // include null terminator
|
||||||
d->size += len;
|
d->size += len;
|
||||||
@ -1678,7 +1679,7 @@ QByteArray &QByteArray::append(const char *str, int len)
|
|||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = qstrlen(str);
|
len = qstrlen(str);
|
||||||
if (str && len) {
|
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)));
|
realloc(qAllocMore(d->size + len, sizeof(Data)));
|
||||||
memcpy(d->data() + d->size, str, len); // include null terminator
|
memcpy(d->data() + d->size, str, len); // include null terminator
|
||||||
d->size += len;
|
d->size += len;
|
||||||
@ -1695,7 +1696,7 @@ QByteArray &QByteArray::append(const char *str, int len)
|
|||||||
|
|
||||||
QByteArray& QByteArray::append(char ch)
|
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)));
|
realloc(qAllocMore(d->size + 1, sizeof(Data)));
|
||||||
d->data()[d->size++] = ch;
|
d->data()[d->size++] = ch;
|
||||||
d->data()[d->size] = '\0';
|
d->data()[d->size] = '\0';
|
||||||
@ -2204,7 +2205,7 @@ QByteArray QByteArray::repeated(int times) const
|
|||||||
|
|
||||||
QByteArray result;
|
QByteArray result;
|
||||||
result.reserve(resultSize);
|
result.reserve(resultSize);
|
||||||
if (result.d->alloc != resultSize)
|
if (int(result.d->alloc) != resultSize)
|
||||||
return QByteArray(); // not enough memory
|
return QByteArray(); // not enough memory
|
||||||
|
|
||||||
memcpy(result.d->data(), d->data(), d->size);
|
memcpy(result.d->data(), d->data(), d->size);
|
||||||
|
@ -133,10 +133,10 @@ struct QByteArrayData
|
|||||||
inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
|
inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int n> struct QConstByteArrayData
|
template<int N> struct QConstByteArrayData
|
||||||
{
|
{
|
||||||
const QByteArrayData ba;
|
const QByteArrayData ba;
|
||||||
const char data[n];
|
const char data[N + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int N> struct QConstByteArrayDataPtr
|
template<int N> struct QConstByteArrayDataPtr
|
||||||
@ -146,10 +146,10 @@ template<int N> struct QConstByteArrayDataPtr
|
|||||||
|
|
||||||
|
|
||||||
#if defined(Q_COMPILER_LAMBDA)
|
#if defined(Q_COMPILER_LAMBDA)
|
||||||
# define QByteArrayLiteral(str) ([]() { \
|
# define QByteArrayLiteral(str) ([]() -> QConstByteArrayDataPtr<sizeof(str) - 1> { \
|
||||||
enum { Size = sizeof(str) }; \
|
enum { Size = sizeof(str) - 1 }; \
|
||||||
static const QConstByteArrayData<Size> qbytearray_literal = \
|
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 }; \
|
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||||
return holder; }())
|
return holder; }())
|
||||||
|
|
||||||
@ -160,9 +160,9 @@ template<int N> struct QConstByteArrayDataPtr
|
|||||||
|
|
||||||
# define QByteArrayLiteral(str) \
|
# define QByteArrayLiteral(str) \
|
||||||
__extension__ ({ \
|
__extension__ ({ \
|
||||||
enum { Size = sizeof(str) }; \
|
enum { Size = sizeof(str) - 1 }; \
|
||||||
static const QConstByteArrayData<Size> qbytearray_literal = \
|
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 }; \
|
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||||
holder; })
|
holder; })
|
||||||
#endif
|
#endif
|
||||||
@ -439,10 +439,10 @@ inline int QByteArray::capacity() const
|
|||||||
{ return d->alloc; }
|
{ return d->alloc; }
|
||||||
|
|
||||||
inline void QByteArray::reserve(int asize)
|
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()
|
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 {
|
class Q_CORE_EXPORT QByteRef {
|
||||||
QByteArray &a;
|
QByteArray &a;
|
||||||
|
@ -317,8 +317,6 @@ QT_BEGIN_NAMESPACE
|
|||||||
\value Vertical
|
\value Vertical
|
||||||
\value Wide
|
\value Wide
|
||||||
|
|
||||||
\omitvalue Single
|
|
||||||
|
|
||||||
\sa decomposition()
|
\sa decomposition()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -382,12 +380,6 @@ QT_BEGIN_NAMESPACE
|
|||||||
\value ByteOrderSwapped
|
\value ByteOrderSwapped
|
||||||
\value ParagraphSeparator
|
\value ParagraphSeparator
|
||||||
\value LineSeparator
|
\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
|
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
|
QChar::Decomposition QChar::decompositionTag() const
|
||||||
{
|
{
|
||||||
@ -967,7 +959,7 @@ QChar::Decomposition QChar::decompositionTag() const
|
|||||||
/*!
|
/*!
|
||||||
\overload
|
\overload
|
||||||
Returns the tag defining the composition of the UCS-4-encoded character
|
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)
|
QChar::Decomposition QChar::decompositionTag(uint ucs4)
|
||||||
{
|
{
|
||||||
@ -1232,7 +1224,6 @@ ushort QChar::toCaseFolded(ushort ucs2)
|
|||||||
return ucs2 + qGetProp(ucs2)->caseFoldDiff;
|
return ucs2 + qGetProp(ucs2)->caseFoldDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn char QChar::toLatin1() const
|
\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);
|
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
|
#ifdef QT_NO_LIBRARY
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -279,6 +279,9 @@ namespace std {
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
#endif
|
#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_NAMESPACE
|
||||||
|
|
||||||
QT_END_HEADER
|
QT_END_HEADER
|
||||||
|
@ -1267,10 +1267,10 @@ void QString::resize(int size)
|
|||||||
QString::free(d);
|
QString::free(d);
|
||||||
d = x;
|
d = x;
|
||||||
} else {
|
} else {
|
||||||
if (d->ref != 1 || size > d->alloc ||
|
if (d->ref != 1 || size > int(d->alloc) ||
|
||||||
(!d->capacityReserved && size < d->size && size < d->alloc >> 1))
|
(!d->capacityReserved && size < d->size && size < int(d->alloc) >> 1))
|
||||||
realloc(grow(size));
|
realloc(grow(size));
|
||||||
if (d->alloc >= size) {
|
if (int(d->alloc) >= size) {
|
||||||
d->size = size;
|
d->size = size;
|
||||||
d->data()[size] = '\0';
|
d->data()[size] = '\0';
|
||||||
}
|
}
|
||||||
@ -1560,7 +1560,7 @@ QString &QString::append(const QString &str)
|
|||||||
if (d == &shared_null.str) {
|
if (d == &shared_null.str) {
|
||||||
operator=(str);
|
operator=(str);
|
||||||
} else {
|
} 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));
|
realloc(grow(d->size + str.d->size));
|
||||||
memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar));
|
memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar));
|
||||||
d->size += str.d->size;
|
d->size += str.d->size;
|
||||||
@ -1580,7 +1580,7 @@ QString &QString::append(const QLatin1String &str)
|
|||||||
const uchar *s = (const uchar *)str.latin1();
|
const uchar *s = (const uchar *)str.latin1();
|
||||||
if (s) {
|
if (s) {
|
||||||
int len = qstrlen((char *)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));
|
realloc(grow(d->size + len));
|
||||||
ushort *i = d->data() + d->size;
|
ushort *i = d->data() + d->size;
|
||||||
while ((*i++ = *s++))
|
while ((*i++ = *s++))
|
||||||
@ -1623,7 +1623,7 @@ QString &QString::append(const QLatin1String &str)
|
|||||||
*/
|
*/
|
||||||
QString &QString::append(QChar ch)
|
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));
|
realloc(grow(d->size + 1));
|
||||||
d->data()[d->size++] = ch.unicode();
|
d->data()[d->size++] = ch.unicode();
|
||||||
d->data()[d->size] = '\0';
|
d->data()[d->size] = '\0';
|
||||||
@ -3550,8 +3550,8 @@ static QByteArray toLatin1_helper(const QChar *data, int length)
|
|||||||
const __m128i questionMark = _mm_set1_epi16('?');
|
const __m128i questionMark = _mm_set1_epi16('?');
|
||||||
// SSE has no compare instruction for unsigned comparison.
|
// SSE has no compare instruction for unsigned comparison.
|
||||||
// The variables must be shiffted + 0x8000 to be compared
|
// The variables must be shiffted + 0x8000 to be compared
|
||||||
const __m128i signedBitOffset = _mm_set1_epi16(0x8000);
|
const __m128i signedBitOffset = _mm_set1_epi16(short(0x8000));
|
||||||
const __m128i thresholdMask = _mm_set1_epi16(0xff + 0x8000);
|
const __m128i thresholdMask = _mm_set1_epi16(short(0xff + 0x8000));
|
||||||
for (int i = 0; i < chunkCount; ++i) {
|
for (int i = 0; i < chunkCount; ++i) {
|
||||||
__m128i chunk1 = _mm_loadu_si128((__m128i*)src); // load
|
__m128i chunk1 = _mm_loadu_si128((__m128i*)src); // load
|
||||||
src += 8;
|
src += 8;
|
||||||
@ -6152,7 +6152,7 @@ QString QString::repeated(int times) const
|
|||||||
|
|
||||||
QString result;
|
QString result;
|
||||||
result.reserve(resultSize);
|
result.reserve(resultSize);
|
||||||
if (result.d->alloc != resultSize)
|
if (int(result.d->alloc) != resultSize)
|
||||||
return QString(); // not enough memory
|
return QString(); // not enough memory
|
||||||
|
|
||||||
memcpy(result.d->data(), d->data(), d->size * sizeof(ushort));
|
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)
|
#if defined(Q_COMPILER_UNICODE_STRINGS)
|
||||||
template<int n> struct QConstStringData
|
template<int N> struct QConstStringData
|
||||||
{
|
{
|
||||||
const QStringData str;
|
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)
|
#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
|
// wchar_t is 2 bytes
|
||||||
template<int n> struct QConstStringData
|
template<int N> struct QConstStringData
|
||||||
{
|
{
|
||||||
const QStringData str;
|
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
|
#else
|
||||||
template<int n> struct QConstStringData
|
template<int N> struct QConstStringData
|
||||||
{
|
{
|
||||||
const QStringData str;
|
const QStringData str;
|
||||||
const ushort data[n];
|
const ushort data[N + 1];
|
||||||
};
|
};
|
||||||
#endif
|
#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)
|
# if defined(Q_COMPILER_LAMBDA)
|
||||||
# define QStringLiteral(str) ([]() { \
|
# define QStringLiteral(str) ([]() -> QConstStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
|
||||||
enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \
|
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||||
static const QConstStringData<Size> qstring_literal = \
|
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 }; \
|
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||||
return holder; }())
|
return holder; }())
|
||||||
|
|
||||||
@ -137,9 +144,9 @@ template<int n> struct QConstStringData
|
|||||||
|
|
||||||
# define QStringLiteral(str) \
|
# define QStringLiteral(str) \
|
||||||
__extension__ ({ \
|
__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 = \
|
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 }; \
|
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||||
holder; })
|
holder; })
|
||||||
# endif
|
# endif
|
||||||
|
@ -108,13 +108,12 @@ QT_BEGIN_NAMESPACE
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*! \internal
|
/*! \internal
|
||||||
Note: The len contains the ending \0
|
|
||||||
*/
|
*/
|
||||||
void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out)
|
void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out)
|
||||||
{
|
{
|
||||||
#ifndef QT_NO_TEXTCODEC
|
#ifndef QT_NO_TEXTCODEC
|
||||||
if (QString::codecForCStrings && len) {
|
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());
|
memcpy(out, reinterpret_cast<const char *>(tmp.constData()), sizeof(QChar) * tmp.size());
|
||||||
out += tmp.length();
|
out += tmp.length();
|
||||||
return;
|
return;
|
||||||
@ -126,7 +125,7 @@ void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out
|
|||||||
while (*a)
|
while (*a)
|
||||||
*out++ = QLatin1Char(*a++);
|
*out++ = QLatin1Char(*a++);
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < len - 1; ++i)
|
for (int i = 0; i < len; ++i)
|
||||||
*out++ = QLatin1Char(a[i]);
|
*out++ = QLatin1Char(a[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ template <int N> struct QConcatenable<char[N]> : private QAbstractConcatenable
|
|||||||
#ifndef QT_NO_CAST_FROM_ASCII
|
#ifndef QT_NO_CAST_FROM_ASCII
|
||||||
static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
|
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
|
#endif
|
||||||
static inline void appendTo(const char a[N], char *&out)
|
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
|
#ifndef QT_NO_CAST_FROM_ASCII
|
||||||
static inline void QT_ASCII_CAST_WARN appendTo(const char a[N], QChar *&out)
|
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
|
#endif
|
||||||
static inline void appendTo(const char a[N], char *&out)
|
static inline void appendTo(const char a[N], char *&out)
|
||||||
@ -349,10 +349,9 @@ template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
|
|||||||
enum { ExactSize = false };
|
enum { ExactSize = false };
|
||||||
static int size(const QByteArray &ba) { return ba.size(); }
|
static int size(const QByteArray &ba) { return ba.size(); }
|
||||||
#ifndef QT_NO_CAST_FROM_ASCII
|
#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(), out);
|
||||||
QAbstractConcatenable::convertFromAscii(ba.constData(), ba.size() + 1, out);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
static inline void appendTo(const QByteArray &ba, char *&out)
|
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 {
|
namespace QtStringBuilder {
|
||||||
template <typename A, typename B> struct ConvertToTypeHelper
|
template <typename A, typename B> struct ConvertToTypeHelper
|
||||||
{ typedef A ConvertTo; };
|
{ typedef A ConvertTo; };
|
||||||
|
@ -13,6 +13,7 @@ HEADERS += \
|
|||||||
tools/qdatetime.h \
|
tools/qdatetime.h \
|
||||||
tools/qdatetime_p.h \
|
tools/qdatetime_p.h \
|
||||||
tools/qeasingcurve.h \
|
tools/qeasingcurve.h \
|
||||||
|
tools/qfreelist_p.h \
|
||||||
tools/qhash.h \
|
tools/qhash.h \
|
||||||
tools/qline.h \
|
tools/qline.h \
|
||||||
tools/qlinkedlist.h \
|
tools/qlinkedlist.h \
|
||||||
@ -61,6 +62,7 @@ SOURCES += \
|
|||||||
tools/qdatetime.cpp \
|
tools/qdatetime.cpp \
|
||||||
tools/qeasingcurve.cpp \
|
tools/qeasingcurve.cpp \
|
||||||
tools/qelapsedtimer.cpp \
|
tools/qelapsedtimer.cpp \
|
||||||
|
tools/qfreelist.cpp \
|
||||||
tools/qhash.cpp \
|
tools/qhash.cpp \
|
||||||
tools/qline.cpp \
|
tools/qline.cpp \
|
||||||
tools/qlinkedlist.cpp \
|
tools/qlinkedlist.cpp \
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
void *qdbus_resolve_me(const char *name);
|
void (*qdbus_resolve_me(const char *name))();
|
||||||
|
|
||||||
#if !defined QT_LINKED_LIBDBUS
|
#if !defined QT_LINKED_LIBDBUS
|
||||||
|
|
||||||
@ -95,20 +95,19 @@ bool qdbus_loadLibDBus()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *qdbus_resolve_conditionally(const char *name)
|
void (*qdbus_resolve_conditionally(const char *name))()
|
||||||
{
|
{
|
||||||
if (qdbus_loadLibDBus())
|
if (qdbus_loadLibDBus())
|
||||||
return qdbus_libdbus->resolve(name);
|
return qdbus_libdbus->resolve(name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *qdbus_resolve_me(const char *name)
|
void (*qdbus_resolve_me(const char *name))()
|
||||||
{
|
{
|
||||||
void *ptr = 0;
|
|
||||||
if (!qdbus_loadLibDBus())
|
if (!qdbus_loadLibDBus())
|
||||||
qFatal("Cannot find libdbus-1 in your system to resolve symbol '%s'.", name);
|
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)
|
if (!ptr)
|
||||||
qFatal("Cannot resolve '%s' in your libdbus-1.", name);
|
qFatal("Cannot resolve '%s' in your libdbus-1.", name);
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
#if !defined QT_LINKED_LIBDBUS
|
#if !defined QT_LINKED_LIBDBUS
|
||||||
|
|
||||||
void *qdbus_resolve_conditionally(const char *name); // doesn't print a warning
|
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_me(const char *name))(); // prints a warning
|
||||||
bool qdbus_loadLibDBus();
|
bool qdbus_loadLibDBus();
|
||||||
|
|
||||||
# define DEFINEFUNC(ret, func, args, argcall, funcret) \
|
# define DEFINEFUNC(ret, func, args, argcall, funcret) \
|
||||||
|
@ -125,6 +125,11 @@ private:
|
|||||||
MethodScriptable = 0x40
|
MethodScriptable = 0x40
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MetaObjectFlags {
|
||||||
|
DynamicMetaObject = 0x01,
|
||||||
|
RequiresVariantMetaObject = 0x02
|
||||||
|
};
|
||||||
|
|
||||||
QMap<QByteArray, Method> methods;
|
QMap<QByteArray, Method> methods;
|
||||||
QMap<QByteArray, Property> properties;
|
QMap<QByteArray, Property> properties;
|
||||||
|
|
||||||
@ -152,6 +157,8 @@ struct QDBusMetaObjectPrivate
|
|||||||
int methodCount, methodData;
|
int methodCount, methodData;
|
||||||
int propertyCount, propertyData;
|
int propertyCount, propertyData;
|
||||||
int enumeratorCount, enumeratorData;
|
int enumeratorCount, enumeratorData;
|
||||||
|
int constructorCount, constructorData; // since revision 2
|
||||||
|
int flags; // since revision 3
|
||||||
|
|
||||||
// this is specific for QDBusMetaObject:
|
// this is specific for QDBusMetaObject:
|
||||||
int propertyDBusData;
|
int propertyDBusData;
|
||||||
@ -416,7 +423,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
|||||||
idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));
|
idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));
|
||||||
|
|
||||||
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
|
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
|
||||||
header->revision = 1;
|
header->revision = 3;
|
||||||
header->className = 0;
|
header->className = 0;
|
||||||
header->classInfoCount = 0;
|
header->classInfoCount = 0;
|
||||||
header->classInfoData = 0;
|
header->classInfoData = 0;
|
||||||
@ -426,6 +433,9 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
|||||||
header->propertyData = header->methodData + header->methodCount * 5;
|
header->propertyData = header->methodData + header->methodCount * 5;
|
||||||
header->enumeratorCount = 0;
|
header->enumeratorCount = 0;
|
||||||
header->enumeratorData = 0;
|
header->enumeratorData = 0;
|
||||||
|
header->constructorCount = 0;
|
||||||
|
header->constructorData = 0;
|
||||||
|
header->flags = RequiresVariantMetaObject;
|
||||||
header->propertyDBusData = header->propertyData + header->propertyCount * 3;
|
header->propertyDBusData = header->propertyData + header->propertyCount * 3;
|
||||||
header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty;
|
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_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_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_RGB = 0; // no compression
|
||||||
const int BMP_RLE8 = 1; // run-length encoded, 8 bits
|
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)
|
static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
|
||||||
{
|
{
|
||||||
s >> bi.biSize;
|
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.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount;
|
||||||
s >> bi.biCompression >> bi.biSizeImage;
|
s >> bi.biCompression >> bi.biSizeImage;
|
||||||
s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter;
|
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);
|
image.setDotsPerMeterY(bi.biYPelsPerMeter);
|
||||||
|
|
||||||
if (!d->isSequential())
|
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
|
if (ncols > 0) { // read color table
|
||||||
uchar rgb[4];
|
uchar rgb[4];
|
||||||
@ -268,12 +320,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
|
} 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_shift = calc_shift(red_mask);
|
||||||
red_scale = 256 / ((red_mask >> red_shift) + 1);
|
red_scale = 256 / ((red_mask >> red_shift) + 1);
|
||||||
green_shift = calc_shift(green_mask);
|
green_shift = calc_shift(green_mask);
|
||||||
|
@ -236,14 +236,14 @@ bool QTiffHandler::read(QImage *image)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// create the color table
|
// create the color table
|
||||||
uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
|
uint16 *redTable = 0;
|
||||||
uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
|
uint16 *greenTable = 0;
|
||||||
uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
|
uint16 *blueTable = 0;
|
||||||
if (!redTable || !greenTable || !blueTable) {
|
if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
|
||||||
TIFFClose(tiff);
|
TIFFClose(tiff);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
|
if (!redTable || !greenTable || !blueTable) {
|
||||||
TIFFClose(tiff);
|
TIFFClose(tiff);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -500,6 +500,9 @@ bool QTiffHandler::write(const QImage &image)
|
|||||||
uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
|
uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
|
||||||
uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
|
uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
|
||||||
if (!redTable || !greenTable || !blueTable) {
|
if (!redTable || !greenTable || !blueTable) {
|
||||||
|
qFree(redTable);
|
||||||
|
qFree(greenTable);
|
||||||
|
qFree(blueTable);
|
||||||
TIFFClose(tiff);
|
TIFFClose(tiff);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,20 @@ QT_BEGIN_NAMESPACE
|
|||||||
\since 4.6
|
\since 4.6
|
||||||
\ingroup painting-3D
|
\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
|
\sa QVector3D, QGenericMatrix
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -1725,6 +1739,7 @@ QRectF QMatrix4x4::mapRect(const QRectF& rect) const
|
|||||||
\fn const qreal *QMatrix4x4::data() const
|
\fn const qreal *QMatrix4x4::data() const
|
||||||
|
|
||||||
Returns a constant pointer to the raw data of this matrix.
|
Returns a constant pointer to the raw data of this matrix.
|
||||||
|
This raw data is stored in column-major format.
|
||||||
|
|
||||||
\sa constData()
|
\sa constData()
|
||||||
*/
|
*/
|
||||||
@ -1733,6 +1748,7 @@ QRectF QMatrix4x4::mapRect(const QRectF& rect) const
|
|||||||
\fn const qreal *QMatrix4x4::constData() const
|
\fn const qreal *QMatrix4x4::constData() const
|
||||||
|
|
||||||
Returns a constant pointer to the raw data of this matrix.
|
Returns a constant pointer to the raw data of this matrix.
|
||||||
|
This raw data is stored in column-major format.
|
||||||
|
|
||||||
\sa data()
|
\sa data()
|
||||||
*/
|
*/
|
||||||
|
@ -3005,7 +3005,7 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
|
|||||||
ensureState();
|
ensureState();
|
||||||
|
|
||||||
QFontEngine *fontEngine = textItem->fontEngine();
|
QFontEngine *fontEngine = textItem->fontEngine();
|
||||||
if (!supportsTransformations(fontEngine)) {
|
if (shouldDrawCachedGlyphs(fontEngine->fontDef.pixelSize, state()->matrix)) {
|
||||||
drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
|
drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
|
||||||
fontEngine);
|
fontEngine);
|
||||||
} else {
|
} else {
|
||||||
@ -3355,10 +3355,7 @@ bool QRasterPaintEngine::supportsTransformations(qreal pixelSize, const QTransfo
|
|||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (pixelSize * pixelSize * qAbs(m.determinant()) >= 64 * 64)
|
return !shouldDrawCachedGlyphs(pixelSize, m);
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -53,6 +53,10 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#if !defined(QT_MAX_CACHED_GLYPH_SIZE)
|
||||||
|
# define QT_MAX_CACHED_GLYPH_SIZE 64
|
||||||
|
#endif
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* class QVectorPath
|
* class QVectorPath
|
||||||
@ -1096,4 +1100,10 @@ bool QPaintEngineEx::supportsTransformations(qreal pixelSize, const QTransform &
|
|||||||
return false;
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -228,6 +228,7 @@ public:
|
|||||||
};
|
};
|
||||||
virtual uint flags() const {return 0;}
|
virtual uint flags() const {return 0;}
|
||||||
virtual bool supportsTransformations(qreal pixelSize, const QTransform &m) const;
|
virtual bool supportsTransformations(qreal pixelSize, const QTransform &m) const;
|
||||||
|
virtual bool shouldDrawCachedGlyphs(qreal pixelSize, const QTransform &m) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QPaintEngineEx(QPaintEngineExPrivate &data);
|
QPaintEngineEx(QPaintEngineExPrivate &data);
|
||||||
|
@ -155,6 +155,7 @@ public:
|
|||||||
struct FaceId {
|
struct FaceId {
|
||||||
FaceId() : index(0), encoding(0) {}
|
FaceId() : index(0), encoding(0) {}
|
||||||
QByteArray filename;
|
QByteArray filename;
|
||||||
|
QByteArray uuid;
|
||||||
int index;
|
int index;
|
||||||
int encoding;
|
int encoding;
|
||||||
};
|
};
|
||||||
@ -303,7 +304,7 @@ inline bool operator ==(const QFontEngine::FaceId &f1, const QFontEngine::FaceId
|
|||||||
|
|
||||||
inline uint qHash(const QFontEngine::FaceId &f)
|
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.
|
\note The referenced file must contain a TrueType or OpenType font.
|
||||||
*/
|
*/
|
||||||
QRawFont::QRawFont(const QString &fileName,
|
QRawFont::QRawFont(const QString &fileName,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference)
|
QFont::HintingPreference hintingPreference)
|
||||||
: d(new QRawFontPrivate)
|
: d(new QRawFontPrivate)
|
||||||
{
|
{
|
||||||
@ -154,7 +154,7 @@ QRawFont::QRawFont(const QString &fileName,
|
|||||||
\note The data must contain a TrueType or OpenType font.
|
\note The data must contain a TrueType or OpenType font.
|
||||||
*/
|
*/
|
||||||
QRawFont::QRawFont(const QByteArray &fontData,
|
QRawFont::QRawFont(const QByteArray &fontData,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference)
|
QFont::HintingPreference hintingPreference)
|
||||||
: d(new QRawFontPrivate)
|
: d(new QRawFontPrivate)
|
||||||
{
|
{
|
||||||
@ -204,7 +204,7 @@ bool QRawFont::isValid() const
|
|||||||
\sa loadFromData()
|
\sa loadFromData()
|
||||||
*/
|
*/
|
||||||
void QRawFont::loadFromFile(const QString &fileName,
|
void QRawFont::loadFromFile(const QString &fileName,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference)
|
QFont::HintingPreference hintingPreference)
|
||||||
{
|
{
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
@ -222,7 +222,7 @@ void QRawFont::loadFromFile(const QString &fileName,
|
|||||||
\sa loadFromFile()
|
\sa loadFromFile()
|
||||||
*/
|
*/
|
||||||
void QRawFont::loadFromData(const QByteArray &fontData,
|
void QRawFont::loadFromData(const QByteArray &fontData,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference)
|
QFont::HintingPreference hintingPreference)
|
||||||
{
|
{
|
||||||
detach();
|
detach();
|
||||||
|
@ -70,10 +70,10 @@ public:
|
|||||||
|
|
||||||
QRawFont();
|
QRawFont();
|
||||||
QRawFont(const QString &fileName,
|
QRawFont(const QString &fileName,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
|
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
|
||||||
QRawFont(const QByteArray &fontData,
|
QRawFont(const QByteArray &fontData,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
|
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
|
||||||
QRawFont(const QRawFont &other);
|
QRawFont(const QRawFont &other);
|
||||||
~QRawFont();
|
~QRawFont();
|
||||||
@ -117,11 +117,11 @@ public:
|
|||||||
qreal unitsPerEm() const;
|
qreal unitsPerEm() const;
|
||||||
|
|
||||||
void loadFromFile(const QString &fileName,
|
void loadFromFile(const QString &fileName,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference);
|
QFont::HintingPreference hintingPreference);
|
||||||
|
|
||||||
void loadFromData(const QByteArray &fontData,
|
void loadFromData(const QByteArray &fontData,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference);
|
QFont::HintingPreference hintingPreference);
|
||||||
|
|
||||||
bool supportsCharacter(quint32 ucs4) const;
|
bool supportsCharacter(quint32 ucs4) const;
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
#include "qrawfont_p.h"
|
#include "qrawfont_p.h"
|
||||||
#include "qfontengine_ft_p.h"
|
#include "qfontengine_ft_p.h"
|
||||||
|
#include "quuid.h"
|
||||||
|
|
||||||
#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
|
#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
|
||||||
# include "qfontengine_x11_p.h"
|
# include "qfontengine_x11_p.h"
|
||||||
@ -87,6 +88,7 @@ public:
|
|||||||
FaceId faceId;
|
FaceId faceId;
|
||||||
faceId.filename = "";
|
faceId.filename = "";
|
||||||
faceId.index = 0;
|
faceId.index = 0;
|
||||||
|
faceId.uuid = QUuid::createUuid().toByteArray();
|
||||||
|
|
||||||
return init(faceId, true, Format_None, fontData);
|
return init(faceId, true, Format_None, fontData);
|
||||||
}
|
}
|
||||||
@ -98,7 +100,7 @@ void QRawFontPrivate::platformCleanUp()
|
|||||||
// Font engine handles all resources
|
// Font engine handles all resources
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, int pixelSize,
|
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference)
|
QFont::HintingPreference hintingPreference)
|
||||||
{
|
{
|
||||||
Q_ASSERT(fontEngine == 0);
|
Q_ASSERT(fontEngine == 0);
|
||||||
|
@ -99,7 +99,7 @@ public:
|
|||||||
void cleanUp();
|
void cleanUp();
|
||||||
void platformCleanUp();
|
void platformCleanUp();
|
||||||
void platformLoadFromData(const QByteArray &fontData,
|
void platformLoadFromData(const QByteArray &fontData,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference);
|
QFont::HintingPreference hintingPreference);
|
||||||
|
|
||||||
static QRawFontPrivate *get(const QRawFont &font) { return font.d.data(); }
|
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)
|
QFont::HintingPreference hintingPreference)
|
||||||
{
|
{
|
||||||
Q_ASSERT(fontEngine == 0);
|
Q_ASSERT(fontEngine == 0);
|
||||||
|
@ -1817,6 +1817,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
|
|||||||
bool isGettingInput = !e->commitString().isEmpty()
|
bool isGettingInput = !e->commitString().isEmpty()
|
||||||
|| e->preeditString() != cursor.block().layout()->preeditAreaText()
|
|| e->preeditString() != cursor.block().layout()->preeditAreaText()
|
||||||
|| e->replacementLength() > 0;
|
|| e->replacementLength() > 0;
|
||||||
|
bool forceSelectionChanged = false;
|
||||||
|
|
||||||
cursor.beginEditBlock();
|
cursor.beginEditBlock();
|
||||||
if (isGettingInput) {
|
if (isGettingInput) {
|
||||||
@ -1840,6 +1841,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
|
|||||||
cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
|
cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
|
||||||
q->ensureCursorVisible();
|
q->ensureCursorVisible();
|
||||||
repaintOldAndNewSelection(oldCursor);
|
repaintOldAndNewSelection(oldCursor);
|
||||||
|
forceSelectionChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1874,6 +1876,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
|
|||||||
cursor_d->setX();
|
cursor_d->setX();
|
||||||
if (oldPreeditCursor != preeditCursor)
|
if (oldPreeditCursor != preeditCursor)
|
||||||
emit q->microFocusChanged();
|
emit q->microFocusChanged();
|
||||||
|
selectionChanged(forceSelectionChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
|
QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
|
||||||
|
@ -1632,7 +1632,7 @@ bool QTextEngine::isRightToLeft() const
|
|||||||
int QTextEngine::findItem(int strPos) const
|
int QTextEngine::findItem(int strPos) const
|
||||||
{
|
{
|
||||||
itemize();
|
itemize();
|
||||||
int left = 0;
|
int left = 1;
|
||||||
int right = layoutData->items.size()-1;
|
int right = layoutData->items.size()-1;
|
||||||
while(left <= right) {
|
while(left <= right) {
|
||||||
int middle = ((right-left)/2)+left;
|
int middle = ((right-left)/2)+left;
|
||||||
|
@ -131,6 +131,69 @@ QT_BEGIN_NAMESPACE
|
|||||||
\omitvalue Valid
|
\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{
|
class QValidatorPrivate : public QObjectPrivate{
|
||||||
Q_DECLARE_PUBLIC(QValidator)
|
Q_DECLARE_PUBLIC(QValidator)
|
||||||
public:
|
public:
|
||||||
@ -436,8 +499,15 @@ void QIntValidator::fixup(QString &input) const
|
|||||||
|
|
||||||
void QIntValidator::setRange(int bottom, int top)
|
void QIntValidator::setRange(int bottom, int top)
|
||||||
{
|
{
|
||||||
b = bottom;
|
if (b != bottom) {
|
||||||
t = top;
|
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)
|
void QDoubleValidator::setRange(double minimum, double maximum, int decimals)
|
||||||
{
|
{
|
||||||
b = minimum;
|
if (b != minimum) {
|
||||||
t = maximum;
|
b = minimum;
|
||||||
dec = decimals;
|
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)
|
void QDoubleValidator::setNotation(Notation newNotation)
|
||||||
{
|
{
|
||||||
Q_D(QDoubleValidator);
|
Q_D(QDoubleValidator);
|
||||||
d->notation = newNotation;
|
if (d->notation != newNotation) {
|
||||||
|
d->notation = newNotation;
|
||||||
|
emit notationChanged(d->notation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QDoubleValidator::Notation QDoubleValidator::notation() const
|
QDoubleValidator::Notation QDoubleValidator::notation() const
|
||||||
@ -915,7 +999,10 @@ QValidator::State QRegExpValidator::validate(QString &input, int& pos) const
|
|||||||
|
|
||||||
void QRegExpValidator::setRegExp(const QRegExp& rx)
|
void QRegExpValidator::setRegExp(const QRegExp& rx)
|
||||||
{
|
{
|
||||||
r = rx;
|
if (r != rx) {
|
||||||
|
r = rx;
|
||||||
|
emit regExpChanged(r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -96,8 +96,8 @@ private:
|
|||||||
class Q_GUI_EXPORT QIntValidator : public QValidator
|
class Q_GUI_EXPORT QIntValidator : public QValidator
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(int bottom READ bottom WRITE setBottom)
|
Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY bottomChanged)
|
||||||
Q_PROPERTY(int top READ top WRITE setTop)
|
Q_PROPERTY(int top READ top WRITE setTop NOTIFY topChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QIntValidator(QObject * parent = 0);
|
explicit QIntValidator(QObject * parent = 0);
|
||||||
@ -113,7 +113,9 @@ public:
|
|||||||
|
|
||||||
int bottom() const { return b; }
|
int bottom() const { return b; }
|
||||||
int top() const { return t; }
|
int top() const { return t; }
|
||||||
|
Q_SIGNALS:
|
||||||
|
void bottomChanged(int bottom);
|
||||||
|
void topChanged(int top);
|
||||||
#ifdef QT3_SUPPORT
|
#ifdef QT3_SUPPORT
|
||||||
public:
|
public:
|
||||||
QT3_SUPPORT_CONSTRUCTOR QIntValidator(QObject * parent, const char *name);
|
QT3_SUPPORT_CONSTRUCTOR QIntValidator(QObject * parent, const char *name);
|
||||||
@ -134,11 +136,11 @@ class QDoubleValidatorPrivate;
|
|||||||
class Q_GUI_EXPORT QDoubleValidator : public QValidator
|
class Q_GUI_EXPORT QDoubleValidator : public QValidator
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(double bottom READ bottom WRITE setBottom)
|
Q_PROPERTY(double bottom READ bottom WRITE setBottom NOTIFY bottomChanged)
|
||||||
Q_PROPERTY(double top READ top WRITE setTop)
|
Q_PROPERTY(double top READ top WRITE setTop NOTIFY topChanged)
|
||||||
Q_PROPERTY(int decimals READ decimals WRITE setDecimals)
|
Q_PROPERTY(int decimals READ decimals WRITE setDecimals NOTIFY decimalsChanged)
|
||||||
Q_ENUMS(Notation)
|
Q_ENUMS(Notation)
|
||||||
Q_PROPERTY(Notation notation READ notation WRITE setNotation)
|
Q_PROPERTY(Notation notation READ notation WRITE setNotation NOTIFY notationChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QDoubleValidator(QObject * parent = 0);
|
explicit QDoubleValidator(QObject * parent = 0);
|
||||||
@ -149,7 +151,6 @@ public:
|
|||||||
StandardNotation,
|
StandardNotation,
|
||||||
ScientificNotation
|
ScientificNotation
|
||||||
};
|
};
|
||||||
|
|
||||||
QValidator::State validate(QString &, int &) const;
|
QValidator::State validate(QString &, int &) const;
|
||||||
|
|
||||||
virtual void setRange(double bottom, double top, int decimals = 0);
|
virtual void setRange(double bottom, double top, int decimals = 0);
|
||||||
@ -163,6 +164,12 @@ public:
|
|||||||
int decimals() const { return dec; }
|
int decimals() const { return dec; }
|
||||||
Notation notation() const;
|
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
|
#ifdef QT3_SUPPORT
|
||||||
public:
|
public:
|
||||||
QT3_SUPPORT_CONSTRUCTOR QDoubleValidator(QObject * parent, const char *name);
|
QT3_SUPPORT_CONSTRUCTOR QDoubleValidator(QObject * parent, const char *name);
|
||||||
@ -182,7 +189,7 @@ private:
|
|||||||
class Q_GUI_EXPORT QRegExpValidator : public QValidator
|
class Q_GUI_EXPORT QRegExpValidator : public QValidator
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp)
|
Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp NOTIFY regExpChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QRegExpValidator(QObject *parent = 0);
|
explicit QRegExpValidator(QObject *parent = 0);
|
||||||
@ -194,6 +201,8 @@ public:
|
|||||||
void setRegExp(const QRegExp& rx);
|
void setRegExp(const QRegExp& rx);
|
||||||
const QRegExp& regExp() const { return r; } // ### make inline for 5.0
|
const QRegExp& regExp() const { return r; } // ### make inline for 5.0
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void regExpChanged(const QRegExp& regExp);
|
||||||
#ifdef QT3_SUPPORT
|
#ifdef QT3_SUPPORT
|
||||||
public:
|
public:
|
||||||
QT3_SUPPORT_CONSTRUCTOR QRegExpValidator(QObject *parent, const char *name);
|
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;
|
extern bool qt_applefontsmoothing_enabled;
|
||||||
#endif
|
#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);
|
Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
|
||||||
|
|
||||||
////////////////////////////////// Private Methods //////////////////////////////////////////
|
////////////////////////////////// Private Methods //////////////////////////////////////////
|
||||||
@ -1441,8 +1437,7 @@ void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem)
|
|||||||
// don't try to cache huge fonts or vastly transformed fonts
|
// don't try to cache huge fonts or vastly transformed fonts
|
||||||
QFontEngine *fontEngine = textItem->fontEngine();
|
QFontEngine *fontEngine = textItem->fontEngine();
|
||||||
const qreal pixelSize = fontEngine->fontDef.pixelSize;
|
const qreal pixelSize = fontEngine->fontDef.pixelSize;
|
||||||
if (pixelSize * pixelSize * qAbs(det) < QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE ||
|
if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f) {
|
||||||
det < 0.25f || det > 4.f) {
|
|
||||||
QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0
|
QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0
|
||||||
? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat)
|
? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat)
|
||||||
: d->glyphCacheType;
|
: 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
|
// don't try to cache huge fonts or vastly transformed fonts
|
||||||
const qreal pixelSize = ti.fontEngine->fontDef.pixelSize;
|
const qreal pixelSize = ti.fontEngine->fontDef.pixelSize;
|
||||||
if (pixelSize * pixelSize * qAbs(det) >= QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE ||
|
if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f)
|
||||||
det < 0.25f || det > 4.f)
|
|
||||||
drawCached = false;
|
drawCached = false;
|
||||||
|
|
||||||
QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
|
QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
|
||||||
|
@ -347,13 +347,13 @@ static void find_trans_colors()
|
|||||||
QGLFormat UNIX/GLX-specific code
|
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
|
// On systems where the GL driver is pluggable (like Mesa), we have to use
|
||||||
// the glXGetProcAddressARB extension to resolve other function pointers as
|
// 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 symbols wont be in the GL library, but rather in a plugin loaded by
|
||||||
// the GL library.
|
// the GL library.
|
||||||
typedef void* (*qt_glXGetProcAddressARB)(const char *);
|
typedef void (*(*qt_glXGetProcAddressARB)(const char *))();
|
||||||
static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
|
static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
|
||||||
static bool triedResolvingGlxGetProcAddress = false;
|
static bool triedResolvingGlxGetProcAddress = false;
|
||||||
if (!triedResolvingGlxGetProcAddress) {
|
if (!triedResolvingGlxGetProcAddress) {
|
||||||
@ -378,7 +378,7 @@ void* qglx_getProcAddress(const char* procName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *procAddress = 0;
|
void (*procAddress)() = 0;
|
||||||
if (glXGetProcAddressARB)
|
if (glXGetProcAddressARB)
|
||||||
procAddress = glXGetProcAddressARB(procName);
|
procAddress = glXGetProcAddressARB(procName);
|
||||||
|
|
||||||
@ -387,7 +387,7 @@ void* qglx_getProcAddress(const char* procName)
|
|||||||
if (!procAddress) {
|
if (!procAddress) {
|
||||||
void *handle = dlopen(NULL, RTLD_LAZY);
|
void *handle = dlopen(NULL, RTLD_LAZY);
|
||||||
if (handle) {
|
if (handle) {
|
||||||
procAddress = dlsym(handle, procName);
|
procAddress = (void (*)())dlsym(handle, procName);
|
||||||
dlclose(handle);
|
dlclose(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ static _glXMakeContextCurrent qt_glXMakeContextCurrent = 0;
|
|||||||
#define glXGetFBConfigAttrib qt_glXGetFBConfigAttrib
|
#define glXGetFBConfigAttrib qt_glXGetFBConfigAttrib
|
||||||
#define glXMakeContextCurrent qt_glXMakeContextCurrent
|
#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()
|
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
|
\c XFIXES_MAJOR - it is a part of soname and may differ from the Xfixes
|
||||||
version.
|
version.
|
||||||
*/
|
*/
|
||||||
static void* qt_load_library_runtime(const char *library, int vernum,
|
static QFunctionPointer qt_load_library_runtime(const char *library, int vernum,
|
||||||
int highestVernum, const char *symbol)
|
int highestVernum, const char *symbol)
|
||||||
{
|
{
|
||||||
QList<int> versions;
|
QList<int> versions;
|
||||||
// we try to load in the following order:
|
// 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) {
|
Q_FOREACH(int version, versions) {
|
||||||
QLatin1String libName(library);
|
QLatin1String libName(library);
|
||||||
QLibrary xfixesLib(libName, version);
|
QLibrary xfixesLib(libName, version);
|
||||||
void *ptr = xfixesLib.resolve(symbol);
|
QFunctionPointer ptr = xfixesLib.resolve(symbol);
|
||||||
if (ptr)
|
if (ptr)
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,8 @@ QT_BEGIN_NAMESPACE
|
|||||||
returns false.
|
returns false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class QRelatedTableModel;
|
||||||
|
|
||||||
struct QRelation
|
struct QRelation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -135,7 +137,7 @@ struct QRelation
|
|||||||
bool isValid();
|
bool isValid();
|
||||||
|
|
||||||
QSqlRelation rel;
|
QSqlRelation rel;
|
||||||
QSqlTableModel *model;
|
QRelatedTableModel *model;
|
||||||
QHash<QString, QVariant> dictionary;//maps keys to display values
|
QHash<QString, QVariant> dictionary;//maps keys to display values
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -143,6 +145,15 @@ struct QRelation
|
|||||||
bool m_dictInitialized;
|
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.
|
A QRelation must be initialized before it is considered valid.
|
||||||
Note: population of the model and dictionary are kept separate
|
Note: population of the model and dictionary are kept separate
|
||||||
@ -162,7 +173,7 @@ void QRelation::populateModel()
|
|||||||
Q_ASSERT(m_parent != NULL);
|
Q_ASSERT(m_parent != NULL);
|
||||||
|
|
||||||
if (!model) {
|
if (!model) {
|
||||||
model = new QSqlTableModel(m_parent, m_parent->database());
|
model = new QRelatedTableModel(this, m_parent, m_parent->database());
|
||||||
model->setTable(rel.tableName());
|
model->setTable(rel.tableName());
|
||||||
model->select();
|
model->select();
|
||||||
}
|
}
|
||||||
@ -219,6 +230,27 @@ bool QRelation::isValid()
|
|||||||
return (rel.isValid() && m_parent != NULL);
|
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
|
class QSqlRelationalTableModelPrivate: public QSqlTableModelPrivate
|
||||||
{
|
{
|
||||||
Q_DECLARE_PUBLIC(QSqlRelationalTableModel)
|
Q_DECLARE_PUBLIC(QSqlRelationalTableModel)
|
||||||
|
@ -88,7 +88,7 @@ qpa:mac: {
|
|||||||
|
|
||||||
load(qt_module_config)
|
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_PRODUCT = QTestLib
|
||||||
QMAKE_TARGET_DESCRIPTION = Qt \
|
QMAKE_TARGET_DESCRIPTION = Qt \
|
||||||
|
@ -55,7 +55,7 @@ void QRawFontPrivate::platformCleanUp()
|
|||||||
extern int qt_defaultDpi();
|
extern int qt_defaultDpi();
|
||||||
|
|
||||||
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData,
|
void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference)
|
QFont::HintingPreference hintingPreference)
|
||||||
{
|
{
|
||||||
// Mac OS X ignores it
|
// Mac OS X ignores it
|
||||||
|
@ -529,7 +529,8 @@ void QRawFontPrivate::platformCleanUp()
|
|||||||
{
|
{
|
||||||
if (fontHandle != NULL) {
|
if (fontHandle != NULL) {
|
||||||
if (ptrRemoveFontMemResourceEx == NULL) {
|
if (ptrRemoveFontMemResourceEx == NULL) {
|
||||||
void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
|
QFunctionPointer func =
|
||||||
|
QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
|
||||||
ptrRemoveFontMemResourceEx =
|
ptrRemoveFontMemResourceEx =
|
||||||
reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
|
reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
|
||||||
}
|
}
|
||||||
@ -545,7 +546,7 @@ void QRawFontPrivate::platformCleanUp()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
|
void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
|
||||||
int pixelSize,
|
qreal pixelSize,
|
||||||
QFont::HintingPreference hintingPreference)
|
QFont::HintingPreference hintingPreference)
|
||||||
{
|
{
|
||||||
QByteArray fontData(_fontData);
|
QByteArray fontData(_fontData);
|
||||||
@ -572,7 +573,8 @@ void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ptrAddFontMemResourceEx == NULL || ptrRemoveFontMemResourceEx == NULL) {
|
if (ptrAddFontMemResourceEx == NULL || ptrRemoveFontMemResourceEx == NULL) {
|
||||||
void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
|
QFunctionPointer func =
|
||||||
|
QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
|
||||||
ptrRemoveFontMemResourceEx =
|
ptrRemoveFontMemResourceEx =
|
||||||
reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
|
reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
|
||||||
|
|
||||||
|
@ -513,7 +513,7 @@ void QKeyMapperPrivate::clearMappings()
|
|||||||
|
|
||||||
// ### ???
|
// ### ???
|
||||||
// if (keyboardLayoutName.isEmpty())
|
// 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);
|
keyboardInputLocale = q_getKeyboardLocale(layoutName, variantName);
|
||||||
keyboardInputDirection = keyboardInputLocale.textDirection();
|
keyboardInputDirection = keyboardInputLocale.textDirection();
|
||||||
|
@ -148,6 +148,8 @@ public:
|
|||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
QTabBar* tabBar() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void setCurrentIndex(int index);
|
void setCurrentIndex(int index);
|
||||||
void setCurrentWidget(QWidget *widget);
|
void setCurrentWidget(QWidget *widget);
|
||||||
@ -165,7 +167,6 @@ protected:
|
|||||||
void keyPressEvent(QKeyEvent *);
|
void keyPressEvent(QKeyEvent *);
|
||||||
void paintEvent(QPaintEvent *);
|
void paintEvent(QPaintEvent *);
|
||||||
void setTabBar(QTabBar *);
|
void setTabBar(QTabBar *);
|
||||||
QTabBar* tabBar() const;
|
|
||||||
void changeEvent(QEvent *);
|
void changeEvent(QEvent *);
|
||||||
bool event(QEvent *);
|
bool event(QEvent *);
|
||||||
void initStyleOption(QStyleOptionTabWidgetFrame *option) const;
|
void initStyleOption(QStyleOptionTabWidgetFrame *option) const;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
# Additional Qt project file for qtmain lib on Windows
|
# Additional Qt project file for qtmain lib on Windows
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
TARGET = qtmain
|
TARGET = qtmain
|
||||||
DESTDIR = $$QMAKE_LIBDIR_QT
|
|
||||||
QT =
|
QT =
|
||||||
|
|
||||||
CONFIG += staticlib warn_on
|
CONFIG += staticlib warn_on
|
||||||
@ -17,5 +16,6 @@ win32 {
|
|||||||
|
|
||||||
!win32:error("$$_FILE_ is intended only for Windows!")
|
!win32:error("$$_FILE_ is intended only for Windows!")
|
||||||
load(qt_module_config)
|
load(qt_module_config)
|
||||||
|
DESTDIR = $$QMAKE_LIBDIR_QT
|
||||||
wince*:QMAKE_POST_LINK =
|
wince*:QMAKE_POST_LINK =
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ SUBDIRS=\
|
|||||||
qfileinfo \
|
qfileinfo \
|
||||||
qfilesystemwatcher \
|
qfilesystemwatcher \
|
||||||
qflags \
|
qflags \
|
||||||
|
qfreelist \
|
||||||
qfuture \
|
qfuture \
|
||||||
qfuturewatcher \
|
qfuturewatcher \
|
||||||
qgetputenv \
|
qgetputenv \
|
||||||
|
@ -26,5 +26,3 @@ contains(QT_CONFIG, dbus){
|
|||||||
QT += dbus
|
QT += dbus
|
||||||
}
|
}
|
||||||
|
|
||||||
CONFIG+=insignificant_test
|
|
||||||
|
|
||||||
|
@ -10,3 +10,5 @@ wince*|symbian: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
symbian: TARGET.CAPABILITY = NetworkServices
|
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;
|
QPointer<QThread> thread;
|
||||||
int count;
|
int count;
|
||||||
|
int startCount;
|
||||||
|
int loopLevel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DeliverInDefinedOrderObject(QObject *parent)
|
DeliverInDefinedOrderObject(QObject *parent)
|
||||||
: QObject(parent), thread(0), count(0)
|
: QObject(parent), thread(0), count(0), startCount(0), loopLevel(0)
|
||||||
{ }
|
{ }
|
||||||
~DeliverInDefinedOrderObject()
|
|
||||||
{
|
signals:
|
||||||
if (!thread.isNull())
|
void done();
|
||||||
thread->wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void start()
|
void startThread()
|
||||||
{
|
{
|
||||||
QVERIFY(!thread);
|
QVERIFY(!thread);
|
||||||
thread = new DeliverInDefinedOrderThread();
|
thread = new DeliverInDefinedOrderThread();
|
||||||
connect(thread, SIGNAL(progress(int)), this, SLOT(threadProgress(int)));
|
connect(thread, SIGNAL(progress(int)), this, SLOT(threadProgress(int)));
|
||||||
connect(thread, SIGNAL(finished()), this, SLOT(threadFinished()));
|
connect(thread, SIGNAL(finished()), this, SLOT(threadFinished()));
|
||||||
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
|
connect(thread, SIGNAL(destroyed()), this, SLOT(threadDestroyed()));
|
||||||
connect(thread, SIGNAL(destroyed()), this, SLOT(start()));
|
|
||||||
thread->start();
|
thread->start();
|
||||||
|
|
||||||
QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
|
QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
|
||||||
@ -398,21 +397,34 @@ public slots:
|
|||||||
{
|
{
|
||||||
QVERIFY(count == 7);
|
QVERIFY(count == 7);
|
||||||
count = 0;
|
count = 0;
|
||||||
|
thread->deleteLater();
|
||||||
|
|
||||||
QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
|
QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void threadDestroyed()
|
||||||
|
{
|
||||||
|
if (++startCount < 20)
|
||||||
|
startThread();
|
||||||
|
else
|
||||||
|
emit done();
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool event(QEvent *event)
|
bool event(QEvent *event)
|
||||||
{
|
{
|
||||||
switch (event->type()) {
|
switch (event->type()) {
|
||||||
case QEvent::User:
|
case QEvent::User:
|
||||||
{
|
{
|
||||||
(void) QEventLoop().exec();
|
++loopLevel;
|
||||||
break;
|
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;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -430,11 +442,8 @@ void tst_QCoreApplication::deliverInDefinedOrder()
|
|||||||
// causes sendPostedEvents() to recurse twice
|
// causes sendPostedEvents() to recurse twice
|
||||||
QCoreApplication::postEvent(&obj, new QEvent(QEvent::User));
|
QCoreApplication::postEvent(&obj, new QEvent(QEvent::User));
|
||||||
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
|
QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()));
|
||||||
QTimer::singleShot(15000, &app, SLOT(quit()));
|
|
||||||
app.exec();
|
app.exec();
|
||||||
}
|
}
|
||||||
#endif // QT_NO_QTHREAD
|
#endif // QT_NO_QTHREAD
|
||||||
@ -524,7 +533,7 @@ void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents()
|
|||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
QCOMPARE(object.counter, i);
|
QCOMPARE(object.counter, i);
|
||||||
++i;
|
++i;
|
||||||
} while (t.elapsed() < 3000);
|
} while (t.elapsed() < 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QCoreApplication::reexec()
|
void tst_QCoreApplication::reexec()
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
load(qttest_p4)
|
load(qttest_p4)
|
||||||
QT += widgets
|
QT += widgets
|
||||||
SOURCES += tst_qdialog.cpp
|
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_))
|
#if defined(Q_WS_MAC) || (defined(Q_WS_WINCE) && defined(_ARM_))
|
||||||
QSKIP("Throwing exceptions in exec() is not supported on this platform.", SkipAll);
|
QSKIP("Throwing exceptions in exec() is not supported on this platform.", SkipAll);
|
||||||
#endif
|
#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;
|
int caughtExceptions = 0;
|
||||||
try {
|
try {
|
||||||
ExceptionDialog dialog;
|
ExceptionDialog dialog;
|
||||||
|
@ -55,6 +55,7 @@ private slots:
|
|||||||
void validateThouSep();
|
void validateThouSep();
|
||||||
void validateIntEquiv_data();
|
void validateIntEquiv_data();
|
||||||
void validateIntEquiv();
|
void validateIntEquiv();
|
||||||
|
void notifySignals();
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QValidator::State);
|
Q_DECLARE_METATYPE(QValidator::State);
|
||||||
@ -244,6 +245,62 @@ void tst_QDoubleValidator::validate()
|
|||||||
dv.setNotation(QDoubleValidator::StandardNotation);
|
dv.setNotation(QDoubleValidator::StandardNotation);
|
||||||
QCOMPARE((int)dv.validate(value, dummy), (int)standard_state);
|
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()
|
void tst_QDoubleValidator::validateIntEquiv_data()
|
||||||
{
|
{
|
||||||
|
@ -41,4 +41,4 @@ symbian {
|
|||||||
LIBS+=-lefsrv
|
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 -> b") << QString("a") << QString("b") << false;
|
||||||
QTest::newRow("a -> .") << QString("a") << QString(".") << false;
|
QTest::newRow("a -> .") << QString("a") << QString(".") << false;
|
||||||
QTest::newRow("renamefile -> renamefile") << QString("renamefile") << QString("renamefile") << 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)
|
#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
|
||||||
QTest::newRow("renamefile -> /etc/renamefile") << QString("renamefile") << QString("/etc/renamefile") << false;
|
QTest::newRow("renamefile -> /etc/renamefile") << QString("renamefile") << QString("/etc/renamefile") << false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,5 +15,3 @@ symbian: {
|
|||||||
DEPLOYMENT += dummyDeploy
|
DEPLOYMENT += dummyDeploy
|
||||||
LIBS += -lefsrv
|
LIBS += -lefsrv
|
||||||
}
|
}
|
||||||
|
|
||||||
CONFIG+=insignificant_test
|
|
||||||
|
@ -909,12 +909,16 @@ void tst_QFileSystemModel::sort()
|
|||||||
expectedOrder << tempFile2.fileName() << tempFile.fileName() << dirPath + QChar('/') + "." << dirPath + QChar('/') + "..";
|
expectedOrder << tempFile2.fileName() << tempFile.fileName() << dirPath + QChar('/') + "." << dirPath + QChar('/') + "..";
|
||||||
//File dialog Mode means sub trees are not sorted, only the current root
|
//File dialog Mode means sub trees are not sorted, only the current root
|
||||||
if (fileDialogMode) {
|
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;
|
QList<QString> actualRows;
|
||||||
for(int i = 0; i < myModel->rowCount(parent); ++i)
|
for(int i = 0; i < myModel->rowCount(parent); ++i)
|
||||||
{
|
{
|
||||||
actualRows << dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString();
|
actualRows << dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString();
|
||||||
}
|
}
|
||||||
QVERIFY(actualRows != expectedOrder);
|
QVERIFY(actualRows != expectedOrder);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < myModel->rowCount(parent); ++i)
|
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 {
|
} else {
|
||||||
DEFINES += SRCDIR=\\\"$$PWD/\\\"
|
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.
|
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);
|
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
|
#endif
|
||||||
QVERIFY2(! QTestEventLoop::instance().timeout(), "Network timeout longer than expected (should have been 60 seconds)");
|
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);
|
QInternal::unregisterCallback(QInternal::DisconnectCallback, disconnect_callback);
|
||||||
|
|
||||||
connect_info.reset();
|
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);
|
ok = QObject::connect(&a, signal.toLatin1(), &b, slot.toLatin1(), Qt::AutoConnection);
|
||||||
QVERIFY(!ok);
|
QVERIFY(!ok);
|
||||||
QCOMPARE(connect_info.sender, (QObject *) 0);
|
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());
|
ok = QObject::disconnect(&a, signal.toLatin1(), &b, slot.toLatin1());
|
||||||
QVERIFY(!ok);
|
QVERIFY(!ok);
|
||||||
QCOMPARE(connect_info.sender, (QObject *) 0);
|
QCOMPARE(connect_info.sender, (QObject *) 0);
|
||||||
|
@ -2,5 +2,3 @@ load(qttest_p4)
|
|||||||
QT += widgets
|
QT += widgets
|
||||||
SOURCES += tst_qgraphicstransform.cpp
|
SOURCES += tst_qgraphicstransform.cpp
|
||||||
CONFIG += parallel_test
|
CONFIG += parallel_test
|
||||||
|
|
||||||
CONFIG+=insignificant_test
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user