Commit 07815d95 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.1 into 10.2

parents 940f0c78 3c3c4ae2
...@@ -163,7 +163,7 @@ int pthread_cancel(pthread_t thread); ...@@ -163,7 +163,7 @@ int pthread_cancel(pthread_t thread);
#define pthread_key(T,V) pthread_key_t V #define pthread_key(T,V) pthread_key_t V
#define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V)) #define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V))
#define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V)) #define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V))
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); } #define pthread_detach_this_thread()
#define pthread_handler_t EXTERNC void * #define pthread_handler_t EXTERNC void *
typedef void *(* pthread_handler)(void *); typedef void *(* pthread_handler)(void *);
......
...@@ -41,3 +41,5 @@ galera_gc_fc_limit : MDEV-17061 Test failure on galera.galera_gc_fc_limit ...@@ -41,3 +41,5 @@ galera_gc_fc_limit : MDEV-17061 Test failure on galera.galera_gc_fc_limit
partition : MDEV-13881 galera.partition failed in buildbot with wrong result partition : MDEV-13881 galera.partition failed in buildbot with wrong result
galera_as_slave_replication_budle : MDEV-15785 Test case galera_as_slave_replication_bundle caused debug assertion galera_as_slave_replication_budle : MDEV-15785 Test case galera_as_slave_replication_bundle caused debug assertion
galera_wan : MDEV-17259: Test failure on galera.galera_wan galera_wan : MDEV-17259: Test failure on galera.galera_wan
galera_pc_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb
galera_drop_database : test
CREATE DATABASE fts;
USE fts;
CREATE TABLE fts_t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
CREATE TABLE fts_t2 (f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
INSERT INTO fts_t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
INSERT INTO fts_t2 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
DROP TABLE ten;
UPDATE fts_t1 SET f2 = 'abcd';
UPDATE fts_t2 SET f2 = 'efjh';
USE fts;
DROP TABLE fts_t1;
DROP TABLE fts_t2;
SHOW TABLES;
Tables_in_fts
DROP DATABASE fts;
...@@ -6,25 +6,25 @@ INSERT IGNORE INTO t1 VALUES (0), (1), (2); ...@@ -6,25 +6,25 @@ INSERT IGNORE INTO t1 VALUES (0), (1), (2);
Warnings: Warnings:
Warning 1265 Data truncated for column 'f1' at row 1 Warning 1265 Data truncated for column 'f1' at row 1
connection node_2; connection node_2;
SELECT COUNT(*) = 6 FROM t1; SELECT COUNT(*) FROM t1;
COUNT(*) = 6 COUNT(*)
1 6
SELECT COUNT(*) = 2 FROM t1 where f1 = ''; SELECT COUNT(*) FROM t1 where f1 = '';
COUNT(*) = 2 COUNT(*)
1 2
SELECT COUNT(*) = 2 FROM t1 where f1 = 'one'; SELECT COUNT(*) FROM t1 where f1 = 'one';
COUNT(*) = 2 COUNT(*)
1 2
DROP TABLE t1; DROP TABLE t1;
connection node_1; connection node_1;
CREATE TABLE t1 (f1 ENUM('', 'one', 'two', 'three', 'four') PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t1 (f1 ENUM('', 'one', 'two', 'three', 'four') PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (''), ('one'), ('two'); INSERT INTO t1 VALUES (''), ('one'), ('two');
connection node_2; connection node_2;
SELECT COUNT(*) = 3 FROM t1; SELECT COUNT(*) FROM t1;
COUNT(*) = 3 COUNT(*)
1 3
SELECT COUNT(*) = 1 FROM t1 WHERE f1 = ''; SELECT COUNT(*) FROM t1 WHERE f1 = '';
COUNT(*) = 1 COUNT(*)
1 1
connection node_1; connection node_1;
SET AUTOCOMMIT=OFF; SET AUTOCOMMIT=OFF;
...@@ -40,7 +40,12 @@ connection node_2; ...@@ -40,7 +40,12 @@ connection node_2;
COMMIT; COMMIT;
ERROR 40001: Deadlock: wsrep aborted transaction ERROR 40001: Deadlock: wsrep aborted transaction
connection node_1; connection node_1;
SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'three'; SELECT COUNT(*) FROM t1 WHERE f1 = 'three';
COUNT(*) = 1 COUNT(*)
1 1
SELECT * FROM t1;
f1
one
two
three
DROP TABLE t1; DROP TABLE t1;
connection node_1; connection node_1;
connection node_2; connection node_2;
connection node_1; connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; SET @wsrep_cluster_address_orig = @@GLOBAL.wsrep_cluster_address;
SET @wsrep_provider_options_orig = @@GLOBAL.wsrep_provider_options;
SET GLOBAL wsrep_provider_options ='pc.ignore_sb=true';
connection node_2; connection node_2;
Killing server ... Killing server ...
connection node_1; connection node_1;
...@@ -15,6 +17,9 @@ SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABL ...@@ -15,6 +17,9 @@ SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABL
VARIABLE_VALUE = 'ON' VARIABLE_VALUE = 'ON'
1 1
SET GLOBAL wsrep_cluster_address = ''; SET GLOBAL wsrep_cluster_address = '';
SET GLOBAL wsrep_cluster_address = @wsrep_cluster_address_orig;
connection node_2; connection node_2;
connection node_1;
SET GLOBAL wsrep_provider_options = @wsrep_provider_options_orig;
disconnect node_2; disconnect node_2;
disconnect node_1; disconnect node_1;
#
# This test tests a DROP empty database
#
--source include/galera_cluster.inc
--source include/have_innodb.inc
# Save original auto_increment_offset values.
--let $node_1=node_1
--let $node_2=node_2
--source include/auto_increment_offset_save.inc
CREATE DATABASE fts;
USE fts;
CREATE TABLE fts_t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
CREATE TABLE fts_t2 (f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
# Insert 1K rows
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
INSERT INTO fts_t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
INSERT INTO fts_t2 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
DROP TABLE ten;
UPDATE fts_t1 SET f2 = 'abcd';
UPDATE fts_t2 SET f2 = 'efjh';
--connection node_2
let $wsrep_cluster_address = `SELECT @@global.wsrep_node_incoming_address`;
--source include/restart_mysqld.inc
--connection node_1
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--let $galera_connection_name = node_2a
--let $galera_server_number = 2
--source include/galera_connect.inc
--connection node_2a
--source include/wait_until_ready.inc
--connection node_1
--let $restart_parameters = --wsrep-cluster-address=gcomm://$wsrep_cluster_address
--source include/restart_mysqld.inc
--connection node_2a
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--let $galera_connection_name = node_1a
--let $galera_server_number = 1
--source include/galera_connect.inc
--connection node_1a
--source include/wait_until_ready.inc
USE fts;
DROP TABLE fts_t1;
DROP TABLE fts_t2;
SHOW TABLES;
DROP DATABASE fts;
# Restore original auto_increment_offset values.
--let $node_1=node_1a
--let $node_2=node_2a
--source include/auto_increment_offset_restore.inc
--source include/galera_end.inc
...@@ -17,9 +17,12 @@ INSERT INTO t1 VALUES ('one'), ('two'); ...@@ -17,9 +17,12 @@ INSERT INTO t1 VALUES ('one'), ('two');
INSERT IGNORE INTO t1 VALUES (0), (1), (2); INSERT IGNORE INTO t1 VALUES (0), (1), (2);
--connection node_2 --connection node_2
SELECT COUNT(*) = 6 FROM t1; --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1';
SELECT COUNT(*) = 2 FROM t1 where f1 = ''; --source include/wait_condition.inc
SELECT COUNT(*) = 2 FROM t1 where f1 = 'one';
SELECT COUNT(*) FROM t1;
SELECT COUNT(*) FROM t1 where f1 = '';
SELECT COUNT(*) FROM t1 where f1 = 'one';
DROP TABLE t1; DROP TABLE t1;
...@@ -33,8 +36,10 @@ CREATE TABLE t1 (f1 ENUM('', 'one', 'two', 'three', 'four') PRIMARY KEY) ENGINE= ...@@ -33,8 +36,10 @@ CREATE TABLE t1 (f1 ENUM('', 'one', 'two', 'three', 'four') PRIMARY KEY) ENGINE=
INSERT INTO t1 VALUES (''), ('one'), ('two'); INSERT INTO t1 VALUES (''), ('one'), ('two');
--connection node_2 --connection node_2
SELECT COUNT(*) = 3 FROM t1; --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1';
SELECT COUNT(*) = 1 FROM t1 WHERE f1 = ''; --source include/wait_condition.inc
SELECT COUNT(*) FROM t1;
SELECT COUNT(*) FROM t1 WHERE f1 = '';
# Conflict # Conflict
...@@ -57,6 +62,7 @@ COMMIT; ...@@ -57,6 +62,7 @@ COMMIT;
--connection node_1 --connection node_1
SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'three'; SELECT COUNT(*) FROM t1 WHERE f1 = 'three';
SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
...@@ -11,10 +11,13 @@ ...@@ -11,10 +11,13 @@
--source include/auto_increment_offset_save.inc --source include/auto_increment_offset_save.inc
--connection node_1 --connection node_1
--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` SET @wsrep_cluster_address_orig = @@GLOBAL.wsrep_cluster_address;
--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` SET @wsrep_provider_options_orig = @@GLOBAL.wsrep_provider_options;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
SET GLOBAL wsrep_provider_options ='pc.ignore_sb=true';
--connection node_2 --connection node_2
--source include/kill_galera.inc --source include/kill_galera.inc
...@@ -33,14 +36,18 @@ SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABL ...@@ -33,14 +36,18 @@ SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABL
# Reset the master and restart the slave so that post-test checks can run # Reset the master and restart the slave so that post-test checks can run
SET GLOBAL wsrep_cluster_address = ''; SET GLOBAL wsrep_cluster_address = '';
--disable_query_log SET GLOBAL wsrep_cluster_address = @wsrep_cluster_address_orig;
--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig';
--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig';
--enable_query_log
--connection node_2 --connection node_2
--source include/start_mysqld.inc --source include/start_mysqld.inc
--connection node_1
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
SET GLOBAL wsrep_provider_options = @wsrep_provider_options_orig;
# Restore original auto_increment_offset values. # Restore original auto_increment_offset values.
--source include/auto_increment_offset_restore.inc --source include/auto_increment_offset_restore.inc
......
...@@ -5,5 +5,6 @@ log-slave-updates=0 ...@@ -5,5 +5,6 @@ log-slave-updates=0
loose-innodb loose-innodb
[mysqld.2] [mysqld.2]
slave-transaction-retries=100
log-slave-updates=0 log-slave-updates=0
loose-innodb loose-innodb
...@@ -30,7 +30,7 @@ CALL mtr.add_suppression("WSREP: Could not open saved state file for reading.*") ...@@ -30,7 +30,7 @@ CALL mtr.add_suppression("WSREP: Could not open saved state file for reading.*")
--disable_result_log --disable_result_log
--disable_query_log --disable_query_log
eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER';
--let $galera_version=25.3.17 --let $galera_version=25.3.24
source include/check_galera_version.inc; source include/check_galera_version.inc;
--enable_result_log --enable_result_log
--enable_query_log --enable_query_log
......
...@@ -4016,14 +4016,16 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) ...@@ -4016,14 +4016,16 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific)
{ {
THD *thd= current_thd; THD *thd= current_thd;
if (is_thread_specific) /* If thread specific memory */
{
/* /*
When thread specfic is set, both mysqld_server_initialized and thd When thread specific is set, both mysqld_server_initialized and thd
must be set must be set, and we check that with DBUG_ASSERT.
However, do not crash, if current_thd is NULL, in release version.
*/ */
DBUG_ASSERT(mysqld_server_initialized && thd); DBUG_ASSERT(!is_thread_specific || (mysqld_server_initialized && thd));
if (is_thread_specific && likely(thd)) /* If thread specific memory */
{
DBUG_PRINT("info", ("thd memory_used: %lld size: %lld", DBUG_PRINT("info", ("thd memory_used: %lld size: %lld",
(longlong) thd->status_var.local_memory_used, (longlong) thd->status_var.local_memory_used,
size)); size));
......
...@@ -1659,21 +1659,31 @@ int rpl_parallel_resize_pool_if_no_slaves(void) ...@@ -1659,21 +1659,31 @@ int rpl_parallel_resize_pool_if_no_slaves(void)
/** /**
Resize pool if not active or busy (in which case we may be in Pool activation is preceeded by taking a "lock" of pool_mark_busy
resize to 0 which guarantees the number of running slaves drops to zero atomicly
with the number of pool workers.
This resolves race between the function caller thread and one
that may be attempting to deactivate the pool.
*/ */
int int
rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool) rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool)
{ {
bool resize; int rc= 0;
mysql_mutex_lock(&pool->LOCK_rpl_thread_pool);
resize= !pool->count || pool->busy; if ((rc= pool_mark_busy(pool, current_thd)))
mysql_mutex_unlock(&pool->LOCK_rpl_thread_pool); return rc; // killed
if (resize)
return rpl_parallel_change_thread_count(pool, opt_slave_parallel_threads, if (!pool->count)
{
pool_mark_not_busy(pool);
rc= rpl_parallel_change_thread_count(pool, opt_slave_parallel_threads,
0); 0);
return 0; }
else
{
pool_mark_not_busy(pool);
}
return rc;
} }
......
...@@ -31,6 +31,7 @@ Created 2012/04/12 by Sunny Bains ...@@ -31,6 +31,7 @@ Created 2012/04/12 by Sunny Bains
#include <my_rdtsc.h> #include <my_rdtsc.h>
#include "univ.i" #include "univ.i"
#include "os0thread.h" #include "os0thread.h"
#include "my_atomic.h"
/** CPU cache line size */ /** CPU cache line size */
#ifdef CPU_LEVEL1_DCACHE_LINESIZE #ifdef CPU_LEVEL1_DCACHE_LINESIZE
...@@ -86,8 +87,8 @@ struct counter_indexer_t : public generic_indexer_t<Type, N> { ...@@ -86,8 +87,8 @@ struct counter_indexer_t : public generic_indexer_t<Type, N> {
#define default_indexer_t counter_indexer_t #define default_indexer_t counter_indexer_t
/** Class for using fuzzy counters. The counter is not protected by any /** Class for using fuzzy counters. The counter is relaxed atomic
mutex and the results are not guaranteed to be 100% accurate but close so the results are not guaranteed to be 100% accurate but close
enough. Creates an array of counters and separates each element by the enough. Creates an array of counters and separates each element by the
CACHE_LINE_SIZE bytes */ CACHE_LINE_SIZE bytes */
template < template <
...@@ -96,20 +97,6 @@ template < ...@@ -96,20 +97,6 @@ template <
template<typename, int> class Indexer = default_indexer_t> template<typename, int> class Indexer = default_indexer_t>
struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t
{ {
#ifdef UNIV_DEBUG
~ib_counter_t()
{
size_t n = (CACHE_LINE_SIZE / sizeof(Type));
/* Check that we aren't writing outside our defined bounds. */
for (size_t i = 0; i < UT_ARR_SIZE(m_counter); i += n) {
for (size_t j = 1; j < n - 1; ++j) {
ut_ad(m_counter[i + j] == 0);
}
}
}
#endif /* UNIV_DEBUG */
/** Increment the counter by 1. */ /** Increment the counter by 1. */
void inc() UNIV_NOTHROW { add(1); } void inc() UNIV_NOTHROW { add(1); }
...@@ -129,15 +116,36 @@ struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t ...@@ -129,15 +116,36 @@ struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t
ut_ad(i < UT_ARR_SIZE(m_counter)); ut_ad(i < UT_ARR_SIZE(m_counter));
m_counter[i] += n; if (sizeof(Type) == 8) {
my_atomic_add64_explicit(
reinterpret_cast<int64*>(&m_counter[i]),
static_cast<int64>(n), MY_MEMORY_ORDER_RELAXED);
} else if (sizeof(Type) == 4) {
my_atomic_add32_explicit(
reinterpret_cast<int32*>(&m_counter[i]),
static_cast<int32>(n), MY_MEMORY_ORDER_RELAXED);
}
compile_time_assert(sizeof(Type) == 8 || sizeof(Type) == 4);
} }
/* @return total value - not 100% accurate, since it is not atomic. */ /* @return total value - not 100% accurate, since it is relaxed atomic. */
operator Type() const UNIV_NOTHROW { operator Type() const UNIV_NOTHROW {
Type total = 0; Type total = 0;
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
total += m_counter[m_policy.offset(i)]; if (sizeof(Type) == 8) {
total += static_cast<
Type>(my_atomic_load64_explicit(
reinterpret_cast<int64*>(const_cast<Type*>(
&m_counter[m_policy.offset(i)])),
MY_MEMORY_ORDER_RELAXED));
} else if (sizeof(Type) == 4) {
total += static_cast<
Type>(my_atomic_load32_explicit(
reinterpret_cast<int32*>(const_cast<Type*>(
&m_counter[m_policy.offset(i)])),
MY_MEMORY_ORDER_RELAXED));
}
} }
return(total); return(total);
......
...@@ -31,6 +31,7 @@ Created 2012/04/12 by Sunny Bains ...@@ -31,6 +31,7 @@ Created 2012/04/12 by Sunny Bains
#include "univ.i" #include "univ.i"
#include <string.h> #include <string.h>
#include "os0thread.h" #include "os0thread.h"
#include "my_atomic.h"
/** CPU cache line size */ /** CPU cache line size */
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
...@@ -91,8 +92,8 @@ struct thread_id_indexer_t : public generic_indexer_t<Type, N> { ...@@ -91,8 +92,8 @@ struct thread_id_indexer_t : public generic_indexer_t<Type, N> {
} }
}; };
/** Class for using fuzzy counters. The counter is not protected by any /** Class for using fuzzy counters. The counter is relaxed atomic
mutex and the results are not guaranteed to be 100% accurate but close so the results are not guaranteed to be 100% accurate but close
enough. Creates an array of counters and separates each element by the enough. Creates an array of counters and separates each element by the
CACHE_LINE_SIZE bytes */ CACHE_LINE_SIZE bytes */
template < template <
...@@ -101,20 +102,6 @@ template < ...@@ -101,20 +102,6 @@ template <
template<typename, int> class Indexer = thread_id_indexer_t> template<typename, int> class Indexer = thread_id_indexer_t>
struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t
{ {
#ifdef UNIV_DEBUG
~ib_counter_t()
{
size_t n = (CACHE_LINE_SIZE / sizeof(Type));
/* Check that we aren't writing outside our defined bounds. */
for (size_t i = 0; i < UT_ARR_SIZE(m_counter); i += n) {
for (size_t j = 1; j < n - 1; ++j) {
ut_ad(m_counter[i + j] == 0);
}
}
}
#endif /* UNIV_DEBUG */
/** Increment the counter by 1. */ /** Increment the counter by 1. */
void inc() UNIV_NOTHROW { add(1); } void inc() UNIV_NOTHROW { add(1); }
...@@ -134,15 +121,36 @@ struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t ...@@ -134,15 +121,36 @@ struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t
ut_ad(i < UT_ARR_SIZE(m_counter)); ut_ad(i < UT_ARR_SIZE(m_counter));
m_counter[i] += n; if (sizeof(Type) == 8) {
my_atomic_add64_explicit(
reinterpret_cast<int64*>(&m_counter[i]),
static_cast<int64>(n), MY_MEMORY_ORDER_RELAXED);
} else if (sizeof(Type) == 4) {
my_atomic_add32_explicit(
reinterpret_cast<int32*>(&m_counter[i]),
static_cast<int32>(n), MY_MEMORY_ORDER_RELAXED);
}
compile_time_assert(sizeof(Type) == 8 || sizeof(Type) == 4);
} }
/* @return total value - not 100% accurate, since it is not atomic. */ /* @return total value - not 100% accurate, since it is relaxed atomic. */
operator Type() const UNIV_NOTHROW { operator Type() const UNIV_NOTHROW {
Type total = 0; Type total = 0;
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
total += m_counter[m_policy.offset(i)]; if (sizeof(Type) == 8) {
total += static_cast<
Type>(my_atomic_load64_explicit(
reinterpret_cast<int64*>(const_cast<Type*>(
&m_counter[m_policy.offset(i)])),
MY_MEMORY_ORDER_RELAXED));
} else if (sizeof(Type) == 4) {
total += static_cast<
Type>(my_atomic_load32_explicit(
reinterpret_cast<int32*>(const_cast<Type*>(
&m_counter[m_policy.offset(i)])),
MY_MEMORY_ORDER_RELAXED));
}
} }
return(total); return(total);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment