--- /dev/null
+#!/usr/bin/perl\r
+\r
+my $nTabsFound = 0;\r
+\r
+brush() ;\r
+\r
+print "Tabs found: $nTabsFound\n" ;\r
+print "Done\n" ;\r
+\r
+exit ;\r
+\r
+sub brush() \r
+{\r
+ processDir( "./cds" ) ;\r
+ processDir( "./src" ) ;\r
+ processDir( "./tests/test-hdr" ) ;\r
+ processDir( "./tests/unit" ) ;\r
+ processDir( "./tests/cppunit" ) ;\r
+}\r
+\r
+sub processDir( $ )\r
+{\r
+ my $dirName = shift ;\r
+ print "Process $dirName directory...\n";\r
+ \r
+ opendir(my $dh, $dirName) || die "can't opendir $dirName: $!";\r
+ my @files = grep { /^[^\.]/ } readdir($dh);\r
+ closedir $dh;\r
+ \r
+ foreach my $file ( @files ) {\r
+ if ( -d "$dirName/$file" ) {\r
+ processDir("$dirName/$file") ;\r
+ }\r
+ elsif ( $file =~ /\.(h|cpp)$/ ) {\r
+ processFile( "$dirName/$file" ) ;\r
+ }\r
+ }\r
+}\r
+\r
+sub processFile( $ ) \r
+{\r
+ my $file = shift ;\r
+\r
+ \r
+ if ( open( my $fh, $file )) {\r
+ binmode $fh ;\r
+ my $str = '' ;\r
+ while (<$fh>) {\r
+ $nTabsFound += $_ =~ s/\t/ /g;\r
+ $_ =~ s/\s+$// ;\r
+ $_ =~ s/\s+;$/;/;\r
+ $str .= $_ ;\r
+ $str .= "\n" ;\r
+ }\r
+ close $fh ;\r
+ \r
+ if ( open( my $fh, ">$file" )) {\r
+ binmode $fh ;\r
+ print $fh $str ;\r
+ close $fh ;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+\r
--- /dev/null
+# Makefile
+#
+
+.PHONY: all
+.SUFFIXES:.cpp .c .ro
+
+# make_distrib.pl substitutes the correct version
+VERSION=1.6.0
+
+# boost_thread lib used by test application.
+# You may change the library name
+LD_BOOST_THREAD_LIB=-lboost_thread -lboost_system
+
+ifeq ($(platform),mingw)
+ LD_TEST_COMMON_LIBS=-lcds -lrtm
+ LD_TEST_COMMON_DEBUG_LIBS=-lcds-debug -lrtm
+ BASE_OPT = -D_REENTRANT -D_FILE_OFFSET_BITS=64 -I..
+ # -Wa,--hash-size=2048
+ CPP_BUILD_CDS_OPT=-DCDS_BUILD_LIB
+else
+ifeq ($(platform),darwin)
+ LD_TEST_COMMON_LIBS=-lcds
+ LD_TEST_COMMON_DEBUG_LIBS=-lcds-debug
+else
+ LD_TEST_COMMON_LIBS=-lcds -lpthread -lrt
+ LD_TEST_COMMON_DEBUG_LIBS=-lcds-debug -lpthread -lrt
+endif
+ BASE_OPT = -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -D_FILE_OFFSET_BITS=64 -I..
+ CPP_BUILD_CDS_OPT=
+endif
+
+COMP_OPT = -c $(CFLAGS) $(BASE_OPT)
+CPP_COMP_OPT = -std=c++0x -c $(CXXFLAGS) $(BASE_OPT)
+
+COMPILER_ROOT = $(shell dirname `dirname \`which $(CXX)\``)
+
+LD_OPTS = $(LDFLAGS)
+
+
+
+####################################
+# cds library
+
+include ../projects/source.libcds.mk
+CDS_OBJS := $(addprefix $(OBJ_PATH)/,$(notdir $(CDS_SOURCES)))
+CDS_OBJS :=$(CDS_OBJS:%.cpp=%.o)
+CDS_SOURCES := $(CDS_SOURCES:%.cpp=../%.cpp)
+
+ifeq ($(platform),mingw)
+ CDS_DEBUG_LIB=libcds-debug.dll
+ CDS_RELEASE_LIB=libcds.dll
+else
+ifeq ($(platform),darwin)
+ CDS_DEBUG_LIB=libcds-debug.dylib
+ CDS_RELEASE_LIB=libcds.dylib
+else
+ CDS_DEBUG_LIB=libcds-debug.so
+ CDS_RELEASE_LIB=libcds.so
+endif
+endif
+
+$(CDS_OBJS): $(OBJ_PATH)/%.o: ../src/%.cpp
+ $(CXX) $(CPP_COMP_OPT) $(CPP_BUILD_CDS_OPT) -o $@ $<
+
+ifeq ($(platform),mingw)
+$(CDS_DEBUG_LIB): $(BIN_PATH)/$(CDS_DEBUG_LIB)
+
+$(BIN_PATH)/$(CDS_DEBUG_LIB) : $(CDS_OBJS)
+ $(CXX) $(LD_OPTS) -Wl,--out-implib,$(BIN_PATH)/$(CDS_DEBUG_LIB).a $(CDS_OBJS) -o $@
+
+$(CDS_RELEASE_LIB) : $(BIN_PATH)/$(CDS_RELEASE_LIB)
+
+$(BIN_PATH)/$(CDS_RELEASE_LIB) : $(CDS_OBJS)
+ $(CXX) $(LD_OPTS) $(CDS_OBJS) -Wl,--out-implib,$(BIN_PATH)/$(CDS_RELEASE_LIB).a -o $@
+
+debug : $(CDS_DEBUG_LIB)
+release : $(CDS_RELEASE_LIB)
+else
+$(CDS_DEBUG_LIB).$(VERSION) : $(CDS_OBJS)
+ $(CXX) $(LD_OPTS) $(CDS_PLATFORM_RELEASE_LDFLAGS) $(CDS_OBJS) -o $@
+ mv ./$(CDS_DEBUG_LIB).$(VERSION) $(BIN_PATH)/$(CDS_DEBUG_LIB).$(VERSION)
+ ln -sf $(CDS_DEBUG_LIB).$(VERSION) $(BIN_PATH)/$(CDS_DEBUG_LIB)
+
+$(CDS_RELEASE_LIB).$(VERSION) : $(CDS_OBJS)
+ $(CXX) $(LD_OPTS) $(CDS_OBJS) $(CDS_PLATFORM_DEBUG_LDFLAGS) -o $@
+ mv ./$(CDS_RELEASE_LIB).$(VERSION) $(BIN_PATH)/$(CDS_RELEASE_LIB).$(VERSION)
+ ln -sf $(CDS_RELEASE_LIB).$(VERSION) $(BIN_PATH)/$(CDS_RELEASE_LIB)
+
+debug : $(CDS_DEBUG_LIB).$(VERSION)
+release : $(CDS_RELEASE_LIB).$(VERSION)
+
+endif
+
+all: debug release
+
+##########################################
+# Make tests
+
+OBJ_TEST_PATH=$(OBJ_PATH)
+
+include ../projects/source.test-common.mk
+CDS_TESTCOMMON_SOURCES := $(CDS_TESTCOMMON_SOURCES:%.cpp=../%.cpp)
+TEST_COMMON_OBJS := $(CDS_TESTCOMMON_SOURCES:%.cpp=%.o)
+
+TEST_COMMONHDR_SRC_DIR=../tests
+$(TEST_COMMON_OBJS) : %.o : %.cpp
+ $(CXX) $(CPP_COMP_OPT) -I$(TEST_COMMONHDR_SRC_DIR) $< -o $@
+
+
+include ../projects/source.test-hdr.mk
+CDS_TESTHDR_SOURCES := $(CDS_TESTHDR_SOURCES:%.cpp=../%.cpp)
+TESTHDR_OBJS := $(CDS_TESTHDR_SOURCES:%.cpp=%.o)
+
+TESTHDR_SRC_DIR=../tests/test-hdr
+$(TESTHDR_OBJS): %.o: %.cpp
+ $(CXX) $(CPP_COMP_OPT) -I$(TESTHDR_SRC_DIR) -I$(TEST_COMMONHDR_SRC_DIR) $< -o $@
+
+include ../projects/source.test-hdr.offsetof.mk
+CDS_TESTHDR_OFFSETOF_SOURCES := $(CDS_TESTHDR_OFFSETOF_SOURCES:%.cpp=../%.cpp)
+TESTHDR_OBJS_NO_OFFSETOF_WARN := $(CDS_TESTHDR_OFFSETOF_SOURCES:%.cpp=%.o)
+
+$(TESTHDR_OBJS_NO_OFFSETOF_WARN): %.o: %.cpp
+ $(CXX) $(CPP_COMP_OPT) -I$(TESTHDR_SRC_DIR) -I$(TEST_COMMONHDR_SRC_DIR) -Wno-invalid-offsetof $< -o $@
+
+
+TEST_SRC_DIR=../tests/unit
+TEST_DATA_DIR=`pwd`/../tests/data
+
+CDSUNIT_COMMON_FILE=
+
+include ../projects/source.unit.map.mk
+CDSUNIT_MAP_SOURCES := $(CDSUNIT_MAP_SOURCES:%.cpp=../%.cpp)
+CDSUNIT_MAP_FILE := $(CDSUNIT_MAP_SOURCES:%.cpp=%.o)
+
+include ../projects/source.unit.set.mk
+CDSUNIT_SET_SOURCES := $(CDSUNIT_SET_SOURCES:%.cpp=../%.cpp)
+CDSUNIT_SET_FILE := $(CDSUNIT_SET_SOURCES:%.cpp=%.o)
+
+include ../projects/source.unit.queue.mk
+CDSUNIT_QUEUE_SOURCES := $(CDSUNIT_QUEUE_SOURCES:%.cpp=../%.cpp)
+CDSUNIT_QUEUE_FILE := $(CDSUNIT_QUEUE_SOURCES:%.cpp=%.o)
+
+include ../projects/source.unit.pqueue.mk
+CDSUNIT_PQUEUE_SOURCES := $(CDSUNIT_PQUEUE_SOURCES:%.cpp=../%.cpp)
+CDSUNIT_PQUEUE_FILE := $(CDSUNIT_PQUEUE_SOURCES:%.cpp=%.o)
+
+include ../projects/source.unit.stack.mk
+CDSUNIT_STACK_SOURCES := $(CDSUNIT_STACK_SOURCES:%.cpp=../%.cpp)
+CDSUNIT_STACK_FILE := $(CDSUNIT_STACK_SOURCES:%.cpp=%.o)
+
+include ../projects/source.unit.misc.mk
+CDSUNIT_MISC_SOURCES := $(CDSUNIT_MISC_SOURCES:%.cpp=../%.cpp)
+CDSUNIT_MISC_FILE := $(CDSUNIT_MISC_SOURCES:%.cpp=%.o)
+
+TEST_OBJ_FILE= $(CDSUNIT_COMMON_FILE) $(CDSUNIT_MAP_FILE) $(CDSUNIT_SET_FILE) $(CDSUNIT_QUEUE_FILE) $(CDSUNIT_PQUEUE_FILE) \
+ $(CDSUNIT_STACK_FILE) $(CDSUNIT_MISC_FILE)
+
+$(TEST_OBJ_FILE): %.o: %.cpp
+ $(CXX) $(CPP_COMP_OPT) -I$(TEST_SRC_DIR) -I$(TEST_COMMONHDR_SRC_DIR) $< -o $@
+
+CDSUNIT_MAP_EXE=$(BIN_PATH)/cdsu-map
+CDSUNIT_SET_EXE=$(BIN_PATH)/cdsu-set
+CDSUNIT_QUEUE_EXE=$(BIN_PATH)/cdsu-queue
+CDSUNIT_PQUEUE_EXE=$(BIN_PATH)/cdsu-pqueue
+CDSUNIT_STACK_EXE=$(BIN_PATH)/cdsu-stack
+CDSUNIT_MISC_EXE=$(BIN_PATH)/cdsu-misc
+CDSUNIT_EXE_FILES= $(CDSUNIT_MAP_EXE) $(CDSUNIT_SET_EXE) $(CDSUNIT_QUEUE_EXE) $(CDSUNIT_PQUEUE_EXE) $(CDSUNIT_STACK_EXE) $(CDSUNIT_MISC_EXE)
+
+unit-map: $(CDSUNIT_MAP_EXE)
+unit-set: $(CDSUNIT_SET_EXE)
+unit-queue: $(CDSUNIT_QUEUE_EXE)
+unit-pqueue: $(CDSUNIT_PQUEUE_EXE)
+unit-stack: $(CDSUNIT_STACK_EXE)
+
+ifeq ($(platform),mingw)
+make_test : $(BIN_PATH)/test-hdr $(CDSUNIT_EXE_FILES)
+ cd $(TEST_DATA_DIR); perl -X split.pl
+ cp -f $(TEST_DATA_DIR)/test.conf $(TEST_DATA_DIR)/test-debug.conf $(TEST_DATA_DIR)/dictionary.txt $(BIN_PATH)
+else
+make_test : $(BIN_PATH)/test-hdr $(CDSUNIT_EXE_FILES)
+ cd $(TEST_DATA_DIR); perl -X split.pl
+ ln -sf $(TEST_DATA_DIR)/test.conf $(TEST_DATA_DIR)/test-debug.conf $(TEST_DATA_DIR)/dictionary.txt $(BIN_PATH)
+endif
+
+$(BIN_PATH)/test-hdr : $(TEST_COMMON_OBJS) $(TESTHDR_OBJS) $(TESTHDR_OBJS_NO_OFFSETOF_WARN)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) \
+ $(TESTHDR_OBJS) $(TESTHDR_OBJS_NO_OFFSETOF_WARN) $(TEST_COMMON_OBJS) \
+ $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_LIBS) -o $@
+
+$(CDSUNIT_MAP_EXE) : $(CDSUNIT_MAP_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_MAP_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_LIBS) -o $@
+
+$(CDSUNIT_SET_EXE) : $(CDSUNIT_SET_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_SET_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_LIBS) -o $@
+
+$(CDSUNIT_QUEUE_EXE) : $(CDSUNIT_QUEUE_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_QUEUE_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_LIBS) -o $@
+
+$(CDSUNIT_PQUEUE_EXE) : $(CDSUNIT_PQUEUE_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_PQUEUE_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_LIBS) -o $@
+
+$(CDSUNIT_STACK_EXE) : $(CDSUNIT_STACK_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_STACK_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_LIBS) -o $@
+
+$(CDSUNIT_MISC_EXE) : $(CDSUNIT_MISC_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_MISC_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_LIBS) -o $@
+
+
+CDSUNIT_MAP_EXE_DBG=$(CDSUNIT_MAP_EXE)-d
+CDSUNIT_SET_EXE_DBG=$(CDSUNIT_SET_EXE)-d
+CDSUNIT_QUEUE_EXE_DBG=$(CDSUNIT_QUEUE_EXE)-d
+CDSUNIT_PQUEUE_EXE_DBG=$(CDSUNIT_PQUEUE_EXE)-d
+CDSUNIT_STACK_EXE_DBG=$(CDSUNIT_STACK_EXE)-d
+CDSUNIT_MISC_EXE_DBG=$(CDSUNIT_MISC_EXE)-d
+CDSUNIT_EXE_DBG_FILES= $(CDSUNIT_MAP_EXE_DBG) $(CDSUNIT_SET_EXE_DBG) $(CDSUNIT_QUEUE_EXE_DBG) $(CDSUNIT_PQUEUE_EXE_DBG) \
+ $(CDSUNIT_STACK_EXE_DBG) $(CDSUNIT_MISC_EXE_DBG)
+
+unit-map-dbg: $(CDSUNIT_MAP_EXE_DBG)
+unit-set-dbg: $(CDSUNIT_SET_EXE_DBG)
+unit-queue-dbg: $(CDSUNIT_QUEUE_EXE_DBG)
+unit-pqueue-dbg: $(CDSUNIT_PQUEUE_EXE_DBG)
+unit-stack-dbg: $(CDSUNIT_STACK_EXE_DBG)
+
+ifeq ($(platform),mingw)
+make_debug_test : $(BIN_PATH)/test-hdr-debug $(CDSUNIT_EXE_DBG_FILES)
+ cd $(TEST_DATA_DIR); perl -X split.pl
+ cp -f $(TEST_DATA_DIR)/test.conf $(TEST_DATA_DIR)/test-debug.conf $(TEST_DATA_DIR)/dictionary.txt $(BIN_PATH)
+else
+make_debug_test : $(BIN_PATH)/test-hdr-debug $(CDSUNIT_EXE_DBG_FILES)
+ cd $(TEST_DATA_DIR); perl -X split.pl
+ ln -sf $(TEST_DATA_DIR)/test.conf $(TEST_DATA_DIR)/test-debug.conf $(TEST_DATA_DIR)/dictionary.txt $(BIN_PATH)
+endif
+
+$(BIN_PATH)/test-hdr-debug : $(TESTHDR_OBJS) $(TESTHDR_OBJS_NO_OFFSETOF_WARN) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) \
+ $(TESTHDR_OBJS) $(TESTHDR_OBJS_NO_OFFSETOF_WARN) $(TEST_COMMON_OBJS) \
+ $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_DEBUG_LIBS) -o $@
+
+$(CDSUNIT_MAP_EXE_DBG) : $(CDSUNIT_MAP_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_MAP_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_DEBUG_LIBS) -o $@
+
+$(CDSUNIT_SET_EXE_DBG) : $(CDSUNIT_SET_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_SET_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_DEBUG_LIBS) -o $@
+
+$(CDSUNIT_QUEUE_EXE_DBG) : $(CDSUNIT_QUEUE_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_QUEUE_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_DEBUG_LIBS) -o $@
+
+$(CDSUNIT_PQUEUE_EXE_DBG) : $(CDSUNIT_PQUEUE_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_PQUEUE_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_DEBUG_LIBS) -o $@
+
+$(CDSUNIT_STACK_EXE_DBG) : $(CDSUNIT_STACK_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_STACK_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_DEBUG_LIBS) -o $@
+
+$(CDSUNIT_MISC_EXE_DBG) : $(CDSUNIT_MISC_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS)
+ $(CXX) $(LD_OPTS) -L$(BIN_PATH) $(CDSUNIT_MISC_FILE) $(CDSUNIT_COMMON_FILE) $(TEST_COMMON_OBJS) $(LD_BOOST_THREAD_LIB) $(LD_TEST_COMMON_DEBUG_LIBS) -o $@
+
+test: make_test
+test_debug: make_debug_test
+
+test_hdr: $(BIN_PATH)/test-hdr
+test_hdr_debug: $(BIN_PATH)/test-hdr-debug
+
+##########################################
+#
+clean:
+ rm -f $(OBJ_PATH)/debug/*
+ rm -f $(OBJ_PATH)/release/*
+ rm -f $(TEST_COMMON_OBJS) $(TESTHDR_OBJS) $(TESTHDR_OBJS_NO_OFFSETOF_WARN) $(TEST_OBJ_FILE)
+ rm -f $(BIN_PATH)/libcds*
+ rm -f $(BIN_PATH)/cdsu-*
+ rm -f $(BIN_PATH)/test-hdr
+
--- /dev/null
+#!/bin/sh
+
+# cds library build script
+# Maxim Khiszinsky 04.01.2009
+
+# The following variables are defined and exported at the end of this script.
+#
+# LDFLAGS
+# CFLAGS
+# CXXFLAGS
+# CXX
+# CC
+# BITSTOBUILD
+
+usage()
+{
+ echo "Build helper script for one of the supported platforms"
+ echo "Usage: build.sh \"options\""
+ echo " where options may be any of the following:"
+ echo " -t make target"
+ echo " -c <C compiler name> Possible values are: gcc,clang"
+ echo " -x <C++ compiler name> (e.g. g++, CC)"
+ echo " -p <Processor architecture> Possible values are:"
+ echo " x86, amd64 (x86_64), sparc, ia64"
+ echo " -o <OS family> Possible values are:"
+ echo " linux, sunos (solaris), hpux, darwin"
+ echo " -D <define> define"
+ echo " -b <bitsToBuild> (accepts '64', '32')"
+ echo " -l <extra linker options>"
+ echo " -z <extra compiler options>"
+ echo " -j <number of make jobs. default 2>"
+ echo " -h (to get help on the above commands)"
+ echo " --with-boost <path to boost include>"
+ echo " --debug-cxx-options <extra compiler options for debug target>"
+ echo " --debug-ld-options <extra linker options for debug target>"
+ echo " --release-cxx-options <extra compiler options for release target>"
+ echo " --release-ld-options <extra linker options for release target>"
+ echo " --clean clean all before building"
+ echo " --debug-test make unit test in debug mode"
+ echo " --amd64-use-128bit use 128bit (16byte) CAS on amd64"
+ echo " --arch-tune march flag (only for x86/amd64), default = native"
+ echo " --nodefaultlibs - no default libs (pthread, stdc++)"
+ echo " --optimize-flags - optimization level flags for release target, default -O3"
+}
+
+ERROR_EXIT_CODE=1
+
+MAKE=make
+
+# Set up the default values for each parameter
+debug=off # by default debug is off
+bitsToBuild=0 # unknown
+makejobs=2
+cppcompiler=g++
+ccompiler=gcc
+processor_arch=unknown
+OS_FAMILY=unknown
+ArchFlag=native
+ld_nodefaultlibs=off
+
+BOOST_INCLUDE_PATH=
+makeclean=off
+
+MAKE_DEBUG_TEST=0
+ld_libs="-lpthread -ldl -lstdc++"
+
+cxx_debug_options=
+ld_debug_options=
+
+cxx_release_options=
+ld_release_options=
+
+cxx_test_release_options=
+ls_test_release_options=
+
+cxx_release_optimization="-fno-strict-aliasing"
+cxx_release_optimization_level="-O3"
+
+amd64_cxx_options=
+
+OS_VERSION=
+TOOLSET_SUFFIX=
+
+target=test
+
+while [ $# -gt 0 ]
+ do
+ case $1 in
+ -t)
+ target=$2
+ shift 2
+ ;;
+ -c)
+ ccompiler=$2
+ shift 2
+ ;;
+ -x)
+ cppcompiler=$2
+ shift 2
+ ;;
+ -o)
+ OS_FAMILY=$2
+ shift 2
+ ;;
+ -p)
+ processor_arch=$2; shift 2
+ ;;
+ -b)
+ bitsToBuild=$2
+ shift 2
+ ;;
+ -l)
+ linkeroptions="$linkeroptions $2"
+ shift 2
+ ;;
+ -z)
+ compileroptions="$compileroptions $2"
+ shift 2
+ ;;
+ -j)
+ makejobs=$2
+ shift 2
+ ;;
+ -h)
+ usage
+ exit $ERROR_EXIT_CODE;;
+
+ --clean)
+ makeclean=on
+ shift
+ ;;
+ --with-boost)
+ BOOST_INCLUDE_PATH=$2
+ shift 2
+ ;;
+ --debug-cxx-options)
+ cxx_debug_options=$2
+ shift 2
+ ;;
+ --debug-ld-options)
+ ld_debug_options=$2
+ shift 2
+ ;;
+ --release-cxx-options)
+ cxx_release_options=$2
+ shift 2
+ ;;
+ --optimize-flags)
+ cxx_release_optimization_level=$2
+ shift 2
+ ;;
+ --release-ld-options)
+ ld_release_options=$2
+ shift 2
+ ;;
+ --nodefaultlibs)
+ ld_libs=" "
+ shift
+ ;;
+ --with-make)
+ MAKE=$2
+ shift 2
+ ;;
+ --platform-suffix)
+ OS_VERSION=$2
+ shift 2
+ ;;
+ --toolset-suffix)
+ TOOLSET_SUFFIX=$2
+ shift 2
+ ;;
+ --debug-test)
+ MAKE_DEBUG_TEST=1
+ if test $target = 'test'; then
+ target=test_debug
+ fi
+ shift 1
+ ;;
+ --amd64-use-128bit)
+ amd64_cxx_options='-mcx16'
+ shift 1
+ ;;
+ --arch-tune)
+ ArchFlag=$2
+ shift 2
+ ;;
+ --)
+ shift; break;;
+
+ *)
+ echo "unknown option $1"
+ usage
+ exit $ERROR_EXIT_CODE;;
+ esac
+done
+
+cxx_release_optimization="$cxx_release_optimization_level $cxx_release_optimization"
+
+# Determine compiler
+case $ccompiler in
+ gcc)
+ if test $cppcompiler = ''; then
+ cppcompiler=g++
+ fi
+ ;;
+ clang)
+ if test $cppcompiler = ''; then
+ cppcompiler=clang++
+ fi
+ ;;
+ *)
+ echo "ERROR: Unknown compiler: $ccompiler"
+ exit $ERROR_EXIT_CODE
+ ;;
+esac
+
+# Determine OS family
+if test $OS_FAMILY = 'unknown'; then
+ OS_FAMILY=`uname |tr [A-Z] [a-z]|sed "s/-//"`
+fi
+case $OS_FAMILY in
+ hp-ux)
+ OS_FAMILY=hpux
+ ;;
+ solaris)
+ OS_FAMILY=sunos
+ ;;
+ mingw*)
+ OS_FAMILY=mingw
+ ;;
+ linux|sunos|hpux|aix|freebsd|mingw|darwin)
+ ;;
+ *)
+ echo "Warning: Unknown operation system: $OS_FAMILY"
+ #exit $ERROR_EXIT_CODE
+ ;;
+esac
+
+
+# Determine processor architecture
+if test $processor_arch = 'unknown'; then
+ processor_arch=`uname -m|tr [A-Z] [a-z]`
+fi
+case $processor_arch in
+ x86_64)
+ if test $bitsToBuild = 64; then
+ processor_arch='amd64'
+ else
+ processor_arch='x86'
+ fi;
+ ;;
+ x86|i686)
+ if test $bitsToBuild = 64; then
+ processor_arch='amd64'
+ else
+ processor_arch='x86'
+ fi
+ ;;
+ sparc64)
+ processor_arch='sparc'
+ ;;
+ amd64|x86|ia64|sparc)
+ ;;
+ *)
+ processor_arch=`uname -p|tr [A-Z] [a-z]`
+ case $processor_arch in
+ sparc|powerpc)
+ ;;
+ *)
+ echo "Warning: Unknown processor architecture: $processor_arch"
+ #exit ${ERROR_EXIT_CODE}
+ ;;
+ esac
+ 1;;
+esac
+
+# Determine compiler flags
+case $ccompiler in
+ gcc|clang)
+ case $processor_arch in
+ amd64)
+ case $OS_FAMILY in
+ linux|freebsd|darwin)
+ buildCXXflags="-m64 -fPIC -march=$ArchFlag $amd64_cxx_options"
+ buildCflags="-m64 -fPIC -march=$ArchFlag $amd64_cxx_options"
+ buildLDflags="-m64 -fPIC"
+ buildTestLDflags="-m64 -fPIC"
+ ;;
+ mingw)
+ buildCXXflags="-m64 -march=$ArchFlag $amd64_cxx_options"
+ buildCflags="-m64 -march=$ArchFlag $amd64_cxx_options"
+ buildLDflags="-m64"
+ buildTestLDflags="-m64"
+ ld_libs=""
+ ;;
+ *)
+ echo "Warning: cannot determine compiler flags for processor $processor_arch, OS $OS_FAMILY, and compiler $ccompiler"
+ #exit ${ERROR_EXIT_CODE}
+ ;;
+ esac
+ ;;
+ x86)
+ case $OS_FAMILY in
+ linux|freebsd|darwin)
+ buildCXXflags="-m32 -fPIC -march=$ArchFlag"
+ buildCflags="-m32 -fPIC -march=$ArchFlag"
+ buildLDflags="-m32 -fPIC"
+ buildTestLDflags="-m32 -fPIC"
+ ;;
+ mingw)
+ buildCXXflags="-m32 -march=$ArchFlag"
+ buildCflags="-m32 -march=$ArchFlag"
+ buildLDflags="-m32"
+ buildTestLDflags="-m32"
+ ld_libs=""
+ ;;
+ *)
+ echo "Warning: cannot determine compiler flags for processor $processor_arch, OS $OS_FAMILY, and compiler $ccompiler"
+ #exit ${ERROR_EXIT_CODE}
+ ;;
+ esac
+ ;;
+ ia64)
+ bitsToBuild=64
+ case $OS_FAMILY in
+ linux|freebsd)
+ buildCXXflags="-mtune=itanium2 -fPIC"
+ buildCflags="-mtune=itanium2 -fPIC"
+ buildLDflags="-mtune=itanium2 -fPIC"
+ buildTestLDflags="-mtune=itanium2 -fPIC"
+ ;;
+ hpux)
+ buildCXXflags="-mlp64 -mtune=itanium2 -fPIC"
+ buildCflags="-mlp64 -mtune=itanium2 -fPIC"
+ buildLDflags="-mlp64 -mtune=itanium2 -fPIC"
+ buildTestLDflags="-mlp64 -mtune=itanium2 -fPIC"
+ ;;
+ *)
+ echo "Warning: cannot determine compiler flags for processor $processor_arch, OS $OS_FAMILY, and compiler $ccompiler"
+ #exit ${ERROR_EXIT_CODE}
+ ;;
+ esac
+ ;;
+ sparc)
+ bitsToBuild=64
+ case $OS_FAMILY in
+ sunos)
+ buildCXXflags="-mcpu=v9 -mtune=ultrasparc3 -m64 -fPIC -pthreads"
+ buildCflags="-mcpu=v9 -mtune=ultrasparc3 -m64 -fPIC -pthreads"
+ buildLDflags="-mcpu=v9 -mtune=ultrasparc3 -m64 -fPIC -pthreads"
+ buildTestLDflags="-mcpu=v9 -mtune=ultrasparc3 -m64 -fPIC -pthreads"
+ cxx_test_release_options="-fPIC"
+ ld_test_release_options="-fPIC"
+ ;;
+ linux)
+ buildCXXflags="-mcpu=v9 -mtune=ultrasparc3 -m64 -fPIC"
+ buildCflags="-mcpu=v9 -mtune=ultrasparc3 -m64 -fPIC"
+ buildLDflags="-mcpu=v9 -mtune=ultrasparc3 -m64 -fPIC"
+ buildTestLDflags="-mcpu=v9 -mtune=ultrasparc3 -m64 -fPIC"
+ cxx_test_release_options="-fPIC"
+ ld_test_release_options="-fPIC"
+ ;;
+ *)
+ echo "Warning: cannot determine compiler flags for processor $processor_arch, OS $OS_FAMILY, and compiler $ccompiler"
+ #exit ${ERROR_EXIT_CODE}
+ ;;
+ esac
+ ;;
+ powerpc)
+ bitsToBuild=64
+ case $OS_FAMILY in
+ aix)
+ buildCXXflags="-maix64 -pthread -fPIC"
+ buildCflags="-maix64 -pthread -fPIC"
+ buildLDflags="-maix64 -pthread -fPIC"
+ buildTestLDflags="-maix64 -pthread -fPIC"
+ cxx_test_release_options="-fPIC"
+ ld_test_release_options="-fPIC"
+ ;;
+ *)
+ echo "Warning: cannot determine compiler flags for processor $processor_arch, OS $OS_FAMILY, and compiler $ccompiler"
+ #exit ${ERROR_EXIT_CODE}
+ ;;
+ esac
+ ;;
+ *)
+ echo "Warning: cannot determine compiler flags for processor $processor_arch and compiler $ccompiler"
+ #exit ${ERROR_EXIT_CODE}
+ ;;
+ esac
+
+ cppcompiler_version=`$cppcompiler -dumpversion`
+ echo g++ version=$gcc_version
+
+ # Setup target options
+ # buildCXXflags="-std=gnu++0x $buildCXXflags"
+ cxx_debug_options="-D_DEBUG -O0 -g $cxx_debug_options"
+ cxx_release_options="-DNDEBUG $cxx_release_optimization $cxx_release_options"
+ ;;
+ *)
+ echo "ERROR: Unknown compiler: $ccompiler"
+ exit ${ERROR_EXIT_CODE}
+ ;;
+esac
+
+if test $BOOST_INCLUDE_PATH != ''; then
+ buildCXXflags="$buildCXXflags -I$BOOST_INCLUDE_PATH"
+fi
+
+if test 'x$buildTestLDflags' = 'x'; then
+ buildTestLDflags=$buildLDflags
+fi
+
+
+EXTRA_CXXFLAGS="$buildCXXflags $EXTRA_CXXFLAGS"
+EXTRA_CFLAGS="$buildCflags $EXTRA_CFLAGS"
+EXTRA_LDFLAGS="$buildLDflags $EXTRA_LDFLAGS"
+
+EXTRA_TEST_LDFLAGS="$buildTestLDflags $EXTRA_TEST_LDFLAGS"
+
+
+echo "Building with the following options ..."
+echo "Processor: $processor_arch"
+echo "Platform: $OS_FAMILY"
+echo "C Compiler: $ccompiler"
+echo "C++ Compiler: $cppcompiler"
+echo "C++ Compiler version: $cppcompiler_version"
+echo "Bits to build: $bitsToBuild"
+echo "Compile options: $compileroptions $EXTRA_CXXFLAGS"
+echo "Link options: $linkeroptions $EXTRA_LDFLAGS"
+echo "Link options (for test cds-unit app): $linkeroptions $EXTRA_TEST_LDFLAGS"
+
+BITSTOBUILD=$bitsToBuild
+export BITSTOBUILD
+
+#
+# Set the C compiler and C++ compiler environment variables
+#
+
+CC="$ccompiler"
+export CC
+
+CXX="$cppcompiler"
+export CXX
+
+ROOT_DIR=..
+
+GOAL_DIR=$ccompiler$TOOLSET_SUFFIX-$processor_arch-$OS_FAMILY$OS_VERSION-$bitsToBuild
+BIN_PATH=$ROOT_DIR/bin/$GOAL_DIR
+mkdir -p $BIN_PATH
+
+OBJ_PATH=$ROOT_DIR/obj/$GOAL_DIR
+mkdir -p $OBJ_PATH
+
+echo PATH=$PATH
+echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH
+echo BIN_PATH=$BIN_PATH
+echo OBJ_PATH=$OBJ_PATH
+echo `${CXX} --version | head -1`
+echo Build started
+
+makegoals=
+if test $makeclean = 'on'; then
+ echo Clean all
+ $MAKE -f Makefile clean platform=$OS_FAMILY BIN_PATH=$BIN_PATH OBJ_PATH=$OBJ_PATH
+fi
+
+echo ---------------------------------
+echo Make debug library
+CXXFLAGS="$compileroptions $cxx_debug_options $EXTRA_CXXFLAGS"
+export CXXFLAGS
+CFLAGS="$compileroptions $cxx_debug_options $EXTRA_CFLAGS $debugflag "
+export CFLAGS
+LDFLAGS="$linkeroptions -shared $ld_debug_options $ld_libs $EXTRA_LDFLAGS "
+export LDFLAGS
+
+mkdir -p $OBJ_PATH/debug
+
+$MAKE -f Makefile \
+ platform=$OS_FAMILY \
+ BIN_PATH=$BIN_PATH \
+ OBJ_PATH=$OBJ_PATH/debug \
+ debug
+
+if test $? -gt 0; then
+ exit $?
+fi
+
+echo ---------------------------------
+echo Make release library
+
+CXXFLAGS="$compileroptions $cxx_release_options $EXTRA_CXXFLAGS "
+export CXXFLAGS
+CFLAGS="$compileroptions $cxx_release_options $EXTRA_CFLAGS "
+export CFLAGS
+LDFLAGS="$linkeroptions -shared $ld_resease_options $ld_libs $EXTRA_LDFLAGS "
+export LDFLAGS
+
+mkdir -p $OBJ_PATH/release
+
+$MAKE -f Makefile \
+ platform=$OS_FAMILY \
+ BIN_PATH=$BIN_PATH \
+ OBJ_PATH=$OBJ_PATH/release \
+ release
+
+if test $? -gt 0; then
+ exit $?
+fi
+
+
+echo ---------------------------------
+echo Make tests
+
+if test $MAKE_DEBUG_TEST = '0'; then
+ CXXFLAGS="$compileroptions $cxx_release_options $cxx_test_release_options $EXTRA_CXXFLAGS "
+ export CXXFLAGS
+ CFLAGS="$compileroptions $cxx_release_options $EXTRA_CFLAGS "
+ export CFLAGS
+ LDFLAGS="$linkeroptions $ld_release_options $ld_test_release_options $ld_libs $EXTRA_TEST_LDFLAGS "
+ export LDFLAGS
+
+ $MAKE -f Makefile -j $makejobs \
+ platform=$OS_FAMILY \
+ BIN_PATH=$BIN_PATH \
+ OBJ_PATH=$OBJ_PATH/test \
+ $target
+
+ if test $? -gt 0; then
+ exit $?
+ fi
+fi
+
+echo ---------------------------------
+echo Make tests debug
+
+if test $MAKE_DEBUG_TEST = '1'; then
+ CXXFLAGS="$compileroptions $cxx_debug_options $cxx_test_release_options $EXTRA_CXXFLAGS "
+ export CXXFLAGS
+ CFLAGS="$compileroptions $cxx_debug_options $EXTRA_CFLAGS "
+ export CFLAGS
+ LDFLAGS="$linkeroptions $ld_debug_options $ld_test_release_options $ld_libs $EXTRA_TEST_LDFLAGS "
+ export LDFLAGS
+
+ $MAKE -f Makefile -j $makejobs \
+ platform=$OS_FAMILY \
+ BIN_PATH=$BIN_PATH \
+ OBJ_PATH=$OBJ_PATH/test-debug \
+ $target
+
+ if test $? -gt 0; then
+ exit $?
+ fi
+fi
+
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+PATH=/usr/local/bin:$PATH
+export PATH
+
+./build.sh \
+--clean \
+--with-make gmake \
+--with-boost /usr/local/include \
+-x g++43 \
+-z '-std=c++0x -Wall -pedantic' \
+-l "-L/usr/local/lib" \
+2>&1 | tee build-freebsd-amd64.log
--- /dev/null
+#!/bin/sh
+clear
+
+export BOOST_ROOT=~/boost
+
+GCC_ROOT=/usr/local/gcc-433
+export PATH=${GCC_ROOT}/bin:${PATH}
+export LD_LIBRARY_PATH=${GCC_ROOT}/lib:${LD_LIBRARY_PATH}
+
+./build.sh -b 64 \
+--clean \
+-x 'g++' \
+-z '-std=c++0x -Wall -pedantic' \
+-l '-L${BOOST_ROOT}/bin/hpux1123-ia64' \
+--with-boost ${BOOST_ROOT} \
+--with-make gmake \
+--platform-suffix 11.23 \
+2>&1 | tee build-hpux11.23-ia64.log
+
--- /dev/null
+#!/bin/sh
+clear
+
+export BOOST_ROOT=~/boost
+
+GCC_ROOT=/usr/local/gcc-433
+export PATH=${GCC_ROOT}/bin:${PATH}
+export LD_LIBRARY_PATH=${GCC_ROOT}/lib:${LD_LIBRARY_PATH}
+
+./build.sh -b 64 \
+--clean \
+-x 'g++' \
+-z '-std=c++0x -Wall -pedantic' \
+-l '-L${BOOST_ROOT}/bin/hpux1131-ia64' \
+--with-boost ${BOOST_ROOT} \
+--with-make gmake \
+--platform-suffix 11.31 \
+2>&1 | tee build-hpux11.31-ia64.log
+
--- /dev/null
+#!/bin/sh
+clear
+
+export BOOST_ROOT=~/boost
+
+GCC_ROOT=/usr/local/gcc-4.3.3
+export PATH=${GCC_ROOT}/bin:${PATH}
+export LD_LIBRARY_PATH=${GCC_ROOT}/lib:${LD_LIBRARY_PATH}
+
+./build.sh -b 64 \
+--clean \
+-x 'g++' \
+-z '-std=c++0x -Wall -pedantic' \
+-l '-L${BOOST_ROOT}/bin/linux-amd64' \
+--with-boost ${BOOST_ROOT} \
+--amd64-use-128bit \
+2>&1 | tee build-linux-amd64.log
+
--- /dev/null
+#!/bin/sh
+clear
+
+export BOOST_ROOT=~/boost
+
+GCC_ROOT=/usr/local/gcc-4.3.3
+export PATH=${GCC_ROOT}/bin:${PATH}
+export LD_LIBRARY_PATH=${GCC_ROOT}/lib:${LD_LIBRARY_PATH}
+
+./build.sh -b 64 \
+--clean \
+-x 'g++' \
+-z '-std=c++0x -Wall -pedantic' \
+-l '-L${BOOST_ROOT}/bin/linux-ia64' \
+--with-boost ${BOOST_ROOT} \
+2>&1 | tee build-linux-ia64.log
+
--- /dev/null
+#!/bin/sh
+clear
+
+BOOST_ROOT=~/boost/boost_1_49_0
+export BOOST_ROOT
+
+./build.sh -b 64 -j 2 \
+-x 'g++' \
+-z '-std=c++0x -Wall -pedantic' \
+-l '-L/opt/cfarm/release/4.4.1-64/lib64 -L${BOOST_ROOT}/stage64/lib' \
+--with-boost ${BOOST_ROOT} \
+2>&1 | tee build-linux-sparc.log
+
+
--- /dev/null
+#!/bin/sh
+clear
+
+export BOOST_ROOT=~/boost
+
+GCC_ROOT=/usr/local/gcc-4.3.3
+export PATH=${GCC_ROOT}/bin:${PATH}
+export LD_LIBRARY_PATH=${GCC_ROOT}/lib:${LD_LIBRARY_PATH}
+
+./build.sh -b 32 \
+--clean \
+-x 'g++' \
+-z '-std=c++0x -Wall -pedantic' \
+-l '-L${BOOST_ROOT}/bin/linux-x86' \
+--with-boost ${BOOST_ROOT} \
+2>&1 | tee build-linux-x86.log
+
--- /dev/null
+
+:: This sample demonstrates how to build libcds in MinGW (clearly, with TDM-GCC).
+:: Run TDM-GCC console, change dir to libcds build directory and run this batch file
+::
+:: BOOST_PATH - environment variable that contains full path to boost root directory
+:: for example: set BOOST_PATH=d:\libs\boost_1_49_0
+::
+
+set BOOST_PATH=d:/Language/Lib/C/boost/boost_1_49_0
+
+:: We use -DBOOST_THREAD_USE_LIB flag since static libboost_thread is used
+
+build.sh -b 64 -x 'g++' -z '-std=c++0x -Wall -pedantic -DBOOST_THREAD_USE_LIB -D_WIN32_WINNT=0x0500' -l "-L%BOOST_PATH%/stage-mingw64/lib" --with-boost "%BOOST_PATH%" --with-make mingw32-make 2>&1 | tee build-mingw-amd64.log
+
--- /dev/null
+#! /bin/sh
+
+BOOST_ROOT=~/works/libs/boost_1_55_0
+./build.sh \
+ --clean \
+ -c clang \
+ -x clang \
+ -b 64 \
+ -z "--std=c++11 -DCDS_USE_LIBCDS_ATOMIC -I/usr/lib/c++/v1 -I$BOOST_ROOT" \
+ -l "-L$BOOST_ROOT/stage64-clang/lib -lc++ -lc++abi -lpthread -ldl" \
+ --nodefaultlibs \
+ --with-boost $BOOST_ROOT \
+ --arch-tune core2 \
+ 2>&1 |tee build.log
+
+# -z "--std=c++11 -DCDS_USE_LIBCDS_ATOMIC -I/usr/lib/c++/v1 -I/usr/include -I$BOOST_ROOT"
--- /dev/null
+#! /bin/sh
+
+BOOST_ROOT=~/works/libs/boost_1_55_0
+MACOS_SDK_INCLUDE=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include
+
+./build.sh \
+ --clean \
+ -c gcc \
+ -x gcc-4.8 \
+ -b 64 \
+ -z "--std=c++11 -I$BOOST_ROOT -I$MACOS_SDK_INCLUDE" \
+ -l "-L$BOOST_ROOT/stage64/lib" \
+ --with-boost $BOOST_ROOT \
+ --arch-tune core2 \
+ 2>&1 |tee build.log
+
--- /dev/null
+#!/bin/sh
+clear
+
+BOOST_ROOT=~/boost
+export BOOST_ROOT
+
+GCC_ROOT=/usr/local/gcc433
+PATH=${GCC_ROOT}/bin:${PATH}
+export PATH
+LD_LIBRARY_PATH=${GCC_ROOT}/lib:/usr/local/lib/mpfr-2.4.1/lib:/usr/local/lib/gmp-4.2.4/lib:${LD_LIBRARY_PATH}
+export LD_LIBRARY_PATH
+
+./build.sh -b 64 \
+--clean \
+-x 'g++' \
+-z '-std=c++0x -Wall -pedantic' \
+-l '-L${BOOST_ROOT}/bin/sun-sparc64' \
+--with-boost ${BOOST_ROOT} \
+2>&1 | tee build-sun-sparc.log
+
+
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_ALGO_BASE_H
+#define __CDS_ALGO_BASE_H
+
+#include <cds/details/defs.h>
+
+namespace cds {
+
+ /// Different approaches and techniques for supporting high-concurrent data structure
+ namespace algo {}
+
+} // namespace cds
+
+#endif // #ifndef __CDS_ALGO_BASE_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_ALGO_ELIMINATION_H
+#define __CDS_ALGO_ELIMINATION_H
+
+#include <cds/algo/elimination_tls.h>
+#include <cds/algo/elimination_opt.h>
+#include <cds/cxx11_atomic.h>
+#include <cds/threading/model.h>
+
+namespace cds { namespace algo {
+
+ /// Elimination technique
+ /** @anchor cds_elimination_description
+ Elimination technique allows highly distributed coupling and execution of operations with reverse
+ semantics like the pushes and pops on a stack. If a push followed by a pop are performed
+ on a stack, the data structure's state does not change (similarly for a pop followed by a push).
+ This means that if one can cause pairs of pushes and pops to meet and pair up in
+ separate locations, the threads can exchange values without having to touch a centralized structure
+ since they have anyhow "eliminated" each other's effect on it. Elimination can be implemented
+ by using a collision array in which threads pick random locations in order to try and collide.
+ Pairs of threads that "collide" in some location run through a synchronization protocol,
+ and all such disjoint collisions can be performed in parallel. If a thread has not met another
+ in the selected location or if it met a thread with an operation that cannot be eliminated
+ (such as two push operations), an alternative scheme must be used.
+ */
+ namespace elimination {
+
+ /// Base class describing an operation for eliminating
+ /**
+ This class contains some debugng info.
+ Actual operation descriptor depends on real container and its interface.
+ */
+ struct operation_desc
+ {
+ record * pOwner; ///< Owner of the descriptor
+ };
+
+ /// Acquires elimination record for the current thread
+ template <typename OperationDesc>
+ static inline record * init_record( OperationDesc& op )
+ {
+ record& rec = cds::threading::elimination_record();
+ assert( rec.is_free());
+ op.pOwner = &rec;
+ rec.pOp = static_cast<operation_desc *>( &op );
+ return &rec;
+ }
+
+ /// Releases elimination record for the current thread
+ static inline void clear_record()
+ {
+ cds::threading::elimination_record().pOp = null_ptr<operation_desc*>();
+ }
+ } // namespace elimination
+}} // namespace cds::algo
+
+#endif // __CDS_ALGO_ELIMINATION_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_ALGO_ELIMINATION_OPT_H
+#define __CDS_ALGO_ELIMINATION_OPT_H
+
+#include <cds/details/defs.h>
+
+namespace cds { namespace opt {
+
+ /// Enable \ref cds_elimination_description "elimination back-off" for the container
+ template <bool Enable>
+ struct enable_elimination {
+ //@cond
+ template <class Base> struct pack: public Base
+ {
+ static CDS_CONSTEXPR_CONST bool enable_elimination = Enable;
+ };
+ //@endcond
+ };
+
+ /// \ref cds_elimination_description "Elimination back-off strategy" option setter
+ /**
+ Back-off strategy for elimination.
+ Usually, elimination back-off strategy is \p cds::backoff::delay.
+ */
+ template <typename Type>
+ struct elimination_backoff {
+ //@cond
+ template <class Base> struct pack: public Base
+ {
+ typedef Type elimination_backoff;
+ };
+ //@endcond
+ };
+}} // namespace cds::opt
+
+#endif // #ifndef __CDS_ALGO_ELIMINATION_OPT_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_ALGO_ELIMINATION_TLS_H
+#define __CDS_ALGO_ELIMINATION_TLS_H
+
+#include <cds/algo/base.h>
+
+namespace cds { namespace algo { namespace elimination {
+
+ // Forwards
+ struct operation_desc;
+
+ /// Per-thread elimination record
+ /** @headerfile cds/algo/elimination.h
+ */
+ struct record
+ {
+ operation_desc * pOp ; ///< Operation descriptor
+
+ /// Initialization
+ record()
+ : pOp( null_ptr<operation_desc *>() )
+ {}
+
+ /// Checks if the record is free
+ bool is_free() const
+ {
+ return pOp == null_ptr<operation_desc *>();
+ }
+ };
+
+}}} // cds::algo::elimination
+
+#endif // #ifndef __CDS_ALGO_ELIMINATION_TLS_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_ALGO_FLAT_COMBINING_H
+#define __CDS_ALGO_FLAT_COMBINING_H
+
+#include <cds/cxx11_atomic.h>
+#include <cds/details/allocator.h>
+#include <cds/backoff_strategy.h>
+#include <cds/lock/spinlock.h>
+#include <cds/details/std/mutex.h> // lock_guard
+#include <cds/opt/options.h>
+#include <cds/int_algo.h>
+#include <boost/thread/tss.hpp> // thread_specific_ptr
+
+namespace cds { namespace algo {
+
+ /// @defgroup cds_flat_combining_intrusive Intrusive flat combining containers
+ /// @defgroup cds_flat_combining_container Non-intrusive flat combining containers
+
+ /// Flat combining
+ /**
+ @anchor cds_flat_combining_description
+ Flat combining (FC) technique is invented by Hendler, Incze, Shavit and Tzafrir in their paper
+ [2010] <i>"Flat Combining and the Synchronization-Parallelism Tradeoff"</i>.
+ The technique converts a sequential data structure to its concurrent implementation.
+ A few structures are added to the sequential implementation: a <i>global lock</i>,
+ a <i>count</i> of the number of combining passes, and a pointer to the <i>head</i>
+ of a <i>publication list</i>. The publication list is a list of thread-local records
+ of a size proportional to the number of threads that are concurrently accessing the shared object.
+
+ Each thread \p t accessing the structure to perform an invocation of some method \p m
+ on the shared object executes the following sequence of steps:
+ <ol>
+ <li>Write the invocation opcode and parameters (if any) of the method \p m to be applied
+ sequentially to the shared object in the <i>request</i> field of your thread local publication
+ record (there is no need to use a load-store memory barrier). The <i>request</i> field will later
+ be used to receive the response. If your thread local publication record is marked as active
+ continue to step 2, otherwise continue to step 5.</li>
+ <li>Check if the global lock is taken. If so (another thread is an active combiner), spin on the <i>request</i>
+ field waiting for a response to the invocation (one can add a yield at this point to allow other threads
+ on the same core to run). Once in a while while spinning check if the lock is still taken and that your
+ record is active. If your record is inactive proceed to step 5. Once the response is available,
+ reset the request field to null and return the response.</li>
+ <li>If the lock is not taken, attempt to acquire it and become a combiner. If you fail,
+ return to spinning in step 2.</li>
+ <li>Otherwise, you hold the lock and are a combiner.
+ <ul>
+ <li>Increment the combining pass count by one.</li>
+ <li>Execute a \p fc_apply() by traversing the publication list from the head,
+ combining all nonnull method call invocations, setting the <i>age</i> of each of these records
+ to the current <i>count</i>, applying the combined method calls to the structure D, and returning
+ responses to all the invocations. This traversal is guaranteed to be wait-free.</li>
+ <li>If the <i>count</i> is such that a cleanup needs to be performed, traverse the publication
+ list from the <i>head</i>. Starting from the second item (we always leave the item pointed to
+ by the head in the list), remove from the publication list all records whose <i>age</i> is
+ much smaller than the current <i>count</i>. This is done by removing the node and marking it
+ as inactive.</li>
+ <li>Release the lock.</li>
+ </ul>
+ <li>If you have no thread local publication record allocate one, marked as active. If you already
+ have one marked as inactive, mark it as active. Execute a store-load memory barrier. Proceed to insert
+ the record into the list with a successful CAS to the <i>head</i>. Then proceed to step 1.</li>
+ </ol>
+
+ As the test results show, the flat combining technique is suitable for non-intrusive containers
+ like stack, queue, deque. For intrusive concurrent containers the flat combining demonstrates
+ less impressive results.
+
+ \ref cds_flat_combining_container "List of FC-based containers" in libcds.
+
+ \ref cds_flat_combining_intrusive "List of intrusive FC-based containers" in libcds.
+ */
+ namespace flat_combining {
+
+ /// Special values of publication_record::nRequest
+ enum request_value
+ {
+ req_EmptyRecord, ///< Publication record is empty
+ req_Response, ///< Operation is done
+
+ req_Operation ///< First operation id for derived classes
+ };
+
+ /// publication_record state
+ enum record_state {
+ inactive, ///< Record is inactive
+ active, ///< Record is active
+ removed ///< Record should be removed
+ };
+
+ /// Record of publication list
+ /**
+ Each data structure based on flat combining contains a class derived from \p %publication_record
+ */
+ struct publication_record {
+ CDS_ATOMIC::atomic<unsigned int> nRequest; ///< Request field (depends on data structure)
+ CDS_ATOMIC::atomic<unsigned int> nState; ///< Record state: inactive, active, removed
+ unsigned int nAge; ///< Age of the record
+ CDS_ATOMIC::atomic<publication_record *> pNext; ///< Next record in publication list
+ void * pOwner; ///< [internal data] Pointer to \ref kernel object that manages the publication list
+
+ /// Initializes publication record
+ publication_record()
+ : nRequest( req_EmptyRecord )
+ , nState( inactive )
+ , nAge(0)
+ , pNext( null_ptr<publication_record *>() )
+ , pOwner( null_ptr<void *>() )
+ {}
+
+ /// Returns the value of \p nRequest field
+ unsigned int op() const
+ {
+ return nRequest.load( CDS_ATOMIC::memory_order_relaxed );
+ }
+
+ /// Checks if the operation is done
+ bool is_done() const
+ {
+ return nRequest.load( CDS_ATOMIC::memory_order_relaxed ) == req_Response;
+ }
+ };
+
+ /// Flat combining internal statistics
+ template <typename Counter = cds::atomicity::event_counter >
+ struct stat
+ {
+ typedef Counter counter_type; ///< Event counter type
+
+ counter_type m_nOperationCount ; ///< How many operations have been performed
+ counter_type m_nCombiningCount ; ///< Combining call count
+ counter_type m_nCompactPublicationList; ///< Count of publication list compacting
+ counter_type m_nDeactivatePubRecord; ///< How many publication records were deactivated during compacting
+ counter_type m_nActivatePubRecord; ///< Count of publication record activating
+ counter_type m_nPubRecordCreated ; ///< Count of created publication records
+ counter_type m_nPubRecordDeteted ; ///< Count of deleted publication records
+ counter_type m_nAcquirePubRecCount; ///< Count of acquiring publication record
+ counter_type m_nReleasePubRecCount; ///< Count on releasing publication record
+
+ /// Returns current combining factor
+ /**
+ Combining factor is how many operations perform in one combine pass:
+ <tt>combining_factor := m_nOperationCount / m_nCombiningCount</tt>
+ */
+ double combining_factor() const
+ {
+ return m_nCombiningCount.get() ? double( m_nOperationCount.get()) / m_nCombiningCount.get() : 0.0;
+ }
+
+ //@cond
+ void onOperation() { ++m_nOperationCount; }
+ void onCombining() { ++m_nCombiningCount; }
+ void onCompactPublicationList() { ++m_nCompactPublicationList; }
+ void onDeactivatePubRecord() { ++m_nDeactivatePubRecord; }
+ void onActivatPubRecord() { ++m_nActivatePubRecord; }
+ void onCreatePubRecord() { ++m_nPubRecordCreated; }
+ void onDeletePubRecord() { ++m_nPubRecordDeteted; }
+ void onAcquirePubRecord() { ++m_nAcquirePubRecCount; }
+ void onReleasePubRecord() { ++m_nReleasePubRecCount; }
+ //@endcond
+ };
+
+ /// Flat combining dummy internal statistics
+ struct empty_stat
+ {
+ //@cond
+ void onOperation() {}
+ void onCombining() {}
+ void onCompactPublicationList() {}
+ void onDeactivatePubRecord() {}
+ void onActivatPubRecord() {}
+ void onCreatePubRecord() {}
+ void onDeletePubRecord() {}
+ void onAcquirePubRecord() {}
+ void onReleasePubRecord() {}
+ //@endcond
+ };
+
+ /// Type traits of \ref kernel class
+ /**
+ You can define different type traits for \ref kernel
+ by specifying your struct based on \p %type_traits
+ or by using \ref make_traits metafunction.
+ */
+ struct type_traits
+ {
+ typedef cds::lock::Spin lock_type; ///< Lock type
+ typedef cds::backoff::delay_of<2> back_off; ///< Back-off strategy
+ typedef CDS_DEFAULT_ALLOCATOR allocator; ///< Allocator used for TLS data (allocating publication_record derivatives)
+ typedef empty_stat stat; ///< Internal statistics
+ typedef opt::v::relaxed_ordering memory_model; ///< /// C++ memory ordering model
+ };
+
+ /// Metafunction converting option list to traits
+ /**
+ This is a wrapper for <tt> cds::opt::make_options< type_traits, Options...> </tt>
+ \p Options are:
+ - \p opt::lock_type - mutex type, default is \p cds::lock::Spin
+ - \p opt::back_off - back-off strategy, defalt is \p cds::backoff::delay_of<2>
+ - \p opt::allocator - allocator type, default is \ref CDS_DEFAULT_ALLOCATOR
+ - \p opt::stat - internal statistics, possible type: \ref stat, \ref empty_stat (the default)
+ - \p opt::memory_model - C++ memory ordering model.
+ List of all available memory ordering see opt::memory_model.
+ Default if cds::opt::v:relaxed_ordering
+ */
+ template <CDS_DECL_OPTIONS6>
+ struct make_traits {
+# ifdef CDS_DOXYGEN_INVOKED
+ typedef implementation_defined type ; ///< Metafunction result
+# else
+ typedef typename cds::opt::make_options<
+ typename cds::opt::find_type_traits< type_traits, CDS_OPTIONS6 >::type
+ ,CDS_OPTIONS6
+ >::type type;
+# endif
+ };
+
+ /// The kernel of flat combining
+ /**
+ Template parameters:
+ - \p PublicationRecord - a type derived from \ref publication_record
+ - \p Traits - a type traits of flat combining, default is flat_combining::type_traits.
+ \ref make_traits metafunction can be used to create type traits
+
+ The kernel object should be a member of a container class. The container cooperates with flat combining
+ kernel object. There are two ways to interact with the kernel:
+ - One-by-one processing the active records of the publication list. This mode provides \ref combine function:
+ the container acquires its publication record by \ref acquire_record, fills its fields and calls
+ \p combine function of its kernel object. If the current thread becomes a combiner, the kernel
+ calls \p fc_apply function of the container for each active non-empty record. Then, the container
+ should release its publication record by \ref release_record. Only one pass through the publication
+ list is possible.
+ - Batch processing (\ref batch_combine function). It this mode the container obtains access
+ to entire publication list. This mode allows the container to perform an elimination, for example,
+ the stack can collide \p push and \p pop requests. The sequence of invocations is the following:
+ the container acquires its publication record by \ref acquire_record, fills its field and call
+ \p batch_combine function of its kernel object. If the current thread becomes a combiner,
+ the kernel calls \p fc_process function of the container passing two iterators pointing to
+ begin and end of publication list (see \ref iterator class). The iterators allows
+ multiple pass through active records of publication list. For each processed record the container
+ should call \ref operation_done function. On the end, the container should release
+ its record by \ref release_record.
+ */
+ template <
+ typename PublicationRecord
+ ,typename Traits = type_traits
+ >
+ class kernel
+ {
+ public:
+ typedef PublicationRecord publication_record_type; ///< publication record type
+ typedef Traits type_traits; ///< Type traits
+ typedef typename type_traits::lock_type global_lock_type; ///< Global lock type
+ typedef typename type_traits::back_off back_off; ///< back-off strategy type
+ typedef typename type_traits::allocator allocator; ///< Allocator type (used for allocating publication_record_type data)
+ typedef typename type_traits::stat stat; ///< Internal statistics
+ typedef typename type_traits::memory_model memory_model; ///< C++ memory model
+
+ protected:
+ //@cond
+ typedef cds::details::Allocator< publication_record_type, allocator > cxx11_allocator; ///< internal helper cds::details::Allocator
+ typedef cds_std::lock_guard<global_lock_type> lock_guard;
+ //@endcond
+
+ protected:
+ unsigned int m_nCount; ///< Count of combining passes
+ publication_record_type * m_pHead; ///< Head of publication list
+ boost::thread_specific_ptr< publication_record_type > m_pThreadRec; ///< Thread-local publication record
+ mutable global_lock_type m_Mutex; ///< Global mutex
+ mutable stat m_Stat; ///< Internal statistics
+ unsigned int const m_nCompactFactor; ///< Publication list compacting factor (the list will be compacted through \p %m_nCompactFactor combining passes)
+ unsigned int const m_nCombinePassCount; ///< Number of combining passes
+
+ public:
+ /// Initializes the object
+ /**
+ Compact factor = 64
+
+ Combiner pass count = 8
+ */
+ kernel()
+ : m_nCount(0)
+ , m_pHead( null_ptr< publication_record_type *>())
+ , m_pThreadRec( tls_cleanup )
+ , m_nCompactFactor( 64 - 1 ) // binary mask
+ , m_nCombinePassCount( 8 )
+ {
+ init();
+ }
+
+ /// Initializes the object
+ kernel(
+ unsigned int nCompactFactor ///< Publication list compacting factor (the list will be compacted through \p nCompactFactor combining passes)
+ ,unsigned int nCombinePassCount ///< Number of combining passes for combiner thread
+ )
+ : m_nCount(0)
+ , m_pHead( null_ptr< publication_record_type *>())
+ , m_pThreadRec( tls_cleanup )
+ , m_nCompactFactor( (unsigned int)( cds::beans::ceil2( nCompactFactor ) - 1 )) // binary mask
+ , m_nCombinePassCount( nCombinePassCount )
+ {
+ init();
+ }
+
+ /// Destroys the objects and mark all publication records as inactive
+ ~kernel()
+ {
+ // mark all publication record as detached
+ for ( publication_record * p = m_pHead; p; p = p->pNext.load( memory_model::memory_order_relaxed ))
+ p->pOwner = null_ptr<void *>();
+ }
+
+ /// Gets publication list record for the current thread
+ /**
+ If there is no publication record for the current thread
+ the function allocates it.
+ */
+ publication_record_type * acquire_record()
+ {
+ publication_record_type * pRec = m_pThreadRec.get();
+ if ( !pRec ) {
+ // Allocate new publication record
+ pRec = cxx11_allocator().New();
+ pRec->pOwner = reinterpret_cast<void *>( this );
+ m_pThreadRec.reset( pRec );
+ m_Stat.onCreatePubRecord();
+ }
+
+ if ( pRec->nState.load( memory_model::memory_order_acquire ) != active )
+ publish( pRec );
+
+ assert( pRec->nRequest.load( memory_model::memory_order_relaxed ) == req_EmptyRecord );
+
+ m_Stat.onAcquirePubRecord();
+ return pRec;
+ }
+
+ /// Marks publication record for the current thread as empty
+ void release_record( publication_record_type * pRec )
+ {
+ assert( pRec->is_done() );
+ pRec->nRequest.store( req_EmptyRecord, memory_model::memory_order_relaxed );
+ m_Stat.onReleasePubRecord();
+ }
+
+ /// Trying to execute operation \p nOpId
+ /**
+ \p pRec is the publication record acquiring by \ref acquire_record earlier.
+ \p owner is a container that is owner of flat combining kernel object.
+ As a result the current thread can become a combiner or can wait for
+ another combiner performs \p pRec operation.
+
+ If the thread becomes a combiner, the kernel calls \p owner.fc_apply
+ for each active non-empty publication record.
+ */
+ template <class Container>
+ void combine( unsigned int nOpId, publication_record_type * pRec, Container& owner )
+ {
+ assert( nOpId >= req_Operation );
+ assert( pRec );
+ //assert( pRec->nState.load( memory_model::memory_order_relaxed ) == active );
+ pRec->nRequest.store( nOpId, memory_model::memory_order_release );
+
+ m_Stat.onOperation();
+
+ try_combining( owner, pRec );
+ }
+
+ /// Trying to execute operation \p nOpId in batch-combine mode
+ /**
+ \p pRec is the publication record acquiring by \ref acquire_record earlier.
+ \p owner is a container that owns flat combining kernel object.
+ As a result the current thread can become a combiner or can wait for
+ another combiner performs \p pRec operation.
+
+ If the thread becomes a combiner, the kernel calls \p owner.fc_process
+ giving the container the full access over publication list. This function
+ is useful for an elimination technique if the container supports any kind of
+ that. The container can perform multiple pass through publication list.
+
+ \p owner.fc_process has two arguments - forward iterators on begin and end of
+ publication list, see \ref iterator class. For each processed record the container
+ should call \ref operation_done function to mark the record as processed.
+
+ On the end of \p %batch_combine the \ref combine function is called
+ to process rest of publication records.
+ */
+ template <class Container>
+ void batch_combine( unsigned int nOpId, publication_record_type * pRec, Container& owner )
+ {
+ assert( nOpId >= req_Operation );
+ assert( pRec );
+ //assert( pRec->nState.load( memory_model::memory_order_relaxed ) == active );
+ pRec->nRequest.store( nOpId, memory_model::memory_order_release );
+
+ m_Stat.onOperation();
+
+ try_batch_combining( owner, pRec );
+ }
+
+ /// Waits for end of combining
+ void wait_while_combining() const
+ {
+ lock_guard l( m_Mutex );
+ }
+
+ /// Marks \p rec as executed
+ /**
+ This function should be called by container if batch_combine mode is used.
+ For usual combining (see \ref combine) this function is excess.
+ */
+ void operation_done( publication_record& rec )
+ {
+ rec.nRequest.store( req_Response, memory_model::memory_order_release );
+ }
+
+ /// Internal statistics
+ stat const& statistics() const
+ {
+ return m_Stat;
+ }
+
+ //@cond
+ // For container classes based on flat combining
+ stat& internal_statistics() const
+ {
+ return m_Stat;
+ }
+ //@endcond
+
+ /// Returns the compact factor
+ unsigned int compact_factor() const
+ {
+ return m_nCompactFactor + 1;
+ }
+
+ /// Returns number of combining passes for combiner thread
+ unsigned int combine_pass_count() const
+ {
+ return m_nCombinePassCount;
+ }
+
+ public:
+ /// Publication list iterator
+ /**
+ Iterators are intended for batch processing by container's
+ \p fc_process function.
+ The iterator allows iterate through active publication list.
+ */
+ class iterator
+ {
+ //@cond
+ friend class kernel;
+ publication_record_type * m_pRec;
+ //@endcond
+
+ protected:
+ //@cond
+ iterator( publication_record_type * pRec )
+ : m_pRec( pRec )
+ {
+ skip_inactive();
+ }
+
+ void skip_inactive()
+ {
+ while ( m_pRec && (m_pRec->nState.load( memory_model::memory_order_acquire ) != active
+ || m_pRec->nRequest.load( memory_model::memory_order_relaxed) < req_Operation ))
+ {
+ m_pRec = static_cast<publication_record_type *>(m_pRec->pNext.load( memory_model::memory_order_acquire ));
+ }
+ }
+ //@endcond
+
+ public:
+ /// Initializes an empty iterator object
+ iterator()
+ : m_pRec( null_ptr<publication_record_type *>())
+ {}
+
+ /// Copy ctor
+ iterator( iterator const& src )
+ : m_pRec( src.m_pRec )
+ {}
+
+ /// Pre-increment
+ iterator& operator++()
+ {
+ assert( m_pRec );
+ m_pRec = static_cast<publication_record_type *>( m_pRec->pNext.load( memory_model::memory_order_acquire ));
+ skip_inactive();
+ return *this;
+ }
+
+ /// Post-increment
+ iterator operator++(int)
+ {
+ assert( m_pRec );
+ iterator it(*this);
+ ++(*this);
+ return it;
+ }
+
+ /// Dereference operator, can return \p nullptr
+ publication_record_type * operator ->()
+ {
+ return m_pRec;
+ }
+
+ /// Dereference operator, the iterator should not be an end iterator
+ publication_record_type& operator*()
+ {
+ assert( m_pRec );
+ return *m_pRec;
+ }
+
+ /// Iterator equality
+ friend bool operator==( iterator it1, iterator it2 )
+ {
+ return it1.m_pRec == it2.m_pRec;
+ }
+
+ /// Iterator inequality
+ friend bool operator!=( iterator it1, iterator it2 )
+ {
+ return !( it1 == it2 );
+ }
+ };
+
+ /// Returns an iterator to the first active publication record
+ iterator begin() { return iterator(m_pHead); }
+
+ /// Returns an iterator to the end of publication list. Should not be dereferenced.
+ iterator end() { return iterator(); }
+
+ private:
+ //@cond
+ static void tls_cleanup( publication_record_type * pRec )
+ {
+ // Thread done
+ // pRec that is TLS data should be excluded from publication list
+ if ( pRec ) {
+ if ( pRec->nState.load(memory_model::memory_order_relaxed) == active && pRec->pOwner ) {
+ // record is active and kernel is alive
+ unsigned int nState = active;
+ pRec->nState.compare_exchange_strong( nState, removed, memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed );
+ }
+ else {
+ // record is not in publication list or kernel already deleted
+ cxx11_allocator().Delete( pRec );
+ }
+ }
+ }
+
+ void init()
+ {
+ assert( m_pThreadRec.get() == null_ptr<publication_record_type *>() );
+ publication_record_type * pRec = cxx11_allocator().New();
+ m_pHead = pRec;
+ pRec->pOwner = this;
+ m_pThreadRec.reset( pRec );
+ m_Stat.onCreatePubRecord();
+ }
+
+ void publish( publication_record_type * pRec )
+ {
+ assert( pRec->nState.load( memory_model::memory_order_relaxed ) == inactive );
+
+ pRec->nAge = m_nCount;
+ pRec->nState.store( active, memory_model::memory_order_release );
+
+ // Insert record to publication list
+ if ( m_pHead != static_cast<publication_record *>(pRec) ) {
+ publication_record * p = m_pHead->pNext.load(memory_model::memory_order_relaxed);
+ if ( p != static_cast<publication_record *>( pRec )) {
+ do {
+ pRec->pNext = p;
+ // Failed CAS changes p
+ } while ( !m_pHead->pNext.compare_exchange_weak( p, static_cast<publication_record *>(pRec),
+ memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed ));
+ m_Stat.onActivatPubRecord();
+ }
+ }
+ }
+
+ void republish( publication_record_type * pRec )
+ {
+ if ( pRec->nState.load( memory_model::memory_order_relaxed ) != active ) {
+ // The record has been excluded from publication list. Reinsert it
+ publish( pRec );
+ }
+ }
+
+ template <class Container>
+ void try_combining( Container& owner, publication_record_type * pRec )
+ {
+ if ( m_Mutex.try_lock() ) {
+ // The thread becomes a combiner
+ lock_guard l( m_Mutex, cds_std::adopt_lock_t() );
+
+ // The record pRec can be excluded from publication list. Re-publish it
+ republish( pRec );
+
+ combining( owner );
+ assert( pRec->nRequest.load( memory_model::memory_order_relaxed ) == req_Response );
+ }
+ else {
+ // There is another combiner, wait while it executes our request
+ if ( !wait_for_combining( pRec ) ) {
+ // The thread becomes a combiner
+ lock_guard l( m_Mutex, cds_std::adopt_lock_t() );
+
+ // The record pRec can be excluded from publication list. Re-publish it
+ republish( pRec );
+
+ combining( owner );
+ assert( pRec->nRequest.load( memory_model::memory_order_relaxed ) == req_Response );
+ }
+ }
+ }
+
+ template <class Container>
+ void try_batch_combining( Container& owner, publication_record_type * pRec )
+ {
+ if ( m_Mutex.try_lock() ) {
+ // The thread becomes a combiner
+ lock_guard l( m_Mutex, cds_std::adopt_lock_t() );
+
+ // The record pRec can be excluded from publication list. Re-publish it
+ republish( pRec );
+
+ batch_combining( owner );
+ assert( pRec->nRequest.load( memory_model::memory_order_relaxed ) == req_Response );
+ }
+ else {
+ // There is another combiner, wait while it executes our request
+ if ( !wait_for_combining( pRec ) ) {
+ // The thread becomes a combiner
+ lock_guard l( m_Mutex, cds_std::adopt_lock_t() );
+
+ // The record pRec can be excluded from publication list. Re-publish it
+ republish( pRec );
+
+ batch_combining( owner );
+ assert( pRec->nRequest.load( memory_model::memory_order_relaxed ) == req_Response );
+ }
+ }
+ }
+
+ template <class Container>
+ void combining( Container& owner )
+ {
+ // The thread is a combiner
+ assert( !m_Mutex.try_lock() );
+
+ unsigned int const nCurAge = ++m_nCount;
+
+ for ( unsigned int nPass = 0; nPass < m_nCombinePassCount; ++nPass )
+ if ( !combining_pass( owner, nCurAge ))
+ break;
+
+ m_Stat.onCombining();
+ if ( (nCurAge & m_nCompactFactor) == 0 )
+ compact_list( nCurAge );
+ }
+
+ template <class Container>
+ bool combining_pass( Container& owner, unsigned int nCurAge )
+ {
+ publication_record * pPrev = null_ptr<publication_record *>();
+ publication_record * p = m_pHead;
+ bool bOpDone = false;
+ while ( p ) {
+ switch ( p->nState.load( memory_model::memory_order_acquire )) {
+ case active:
+ if ( p->op() >= req_Operation ) {
+ p->nAge = nCurAge;
+ owner.fc_apply( static_cast<publication_record_type *>(p) );
+ operation_done( *p );
+ bOpDone = true;
+ }
+ break;
+ case inactive:
+ // Only m_pHead can be inactive in the publication list
+ assert( p == m_pHead );
+ break;
+ case removed:
+ // The record should be removed
+ p = unlink_and_delete_record( pPrev, p );
+ continue;
+ default:
+ /// ??? That is impossible
+ assert(false);
+ }
+ pPrev = p;
+ p = p->pNext.load( memory_model::memory_order_acquire );
+ }
+ return bOpDone;
+ }
+
+ template <class Container>
+ void batch_combining( Container& owner )
+ {
+ // The thread is a combiner
+ assert( !m_Mutex.try_lock() );
+
+ unsigned int const nCurAge = ++m_nCount;
+
+ for ( unsigned int nPass = 0; nPass < m_nCombinePassCount; ++nPass )
+ owner.fc_process( begin(), end() );
+
+ combining_pass( owner, nCurAge );
+ m_Stat.onCombining();
+ if ( (nCurAge & m_nCompactFactor) == 0 )
+ compact_list( nCurAge );
+ }
+
+ bool wait_for_combining( publication_record_type * pRec )
+ {
+ back_off bkoff;
+ while ( pRec->nRequest.load( memory_model::memory_order_acquire ) != req_Response ) {
+
+ // The record can be excluded from publication list. Reinsert it
+ republish( pRec );
+
+ bkoff();
+
+ if ( m_Mutex.try_lock() ) {
+ if ( pRec->nRequest.load( memory_model::memory_order_acquire ) == req_Response ) {
+ m_Mutex.unlock();
+ break;
+ }
+ // The thread becomes a combiner
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void compact_list( unsigned int const nCurAge )
+ {
+ // Thinning publication list
+ publication_record * pPrev = null_ptr<publication_record *>();
+ for ( publication_record * p = m_pHead; p; ) {
+ if ( p->nState.load( memory_model::memory_order_acquire ) == active && p->nAge + m_nCompactFactor < nCurAge ) {
+ if ( pPrev ) {
+ publication_record * pNext = p->pNext.load( memory_model::memory_order_acquire );
+ if ( pPrev->pNext.compare_exchange_strong( p, pNext,
+ memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed ))
+ {
+ p->nState.store( inactive, memory_model::memory_order_release );
+ p = pNext;
+ m_Stat.onDeactivatePubRecord();
+ continue;
+ }
+ }
+ }
+ pPrev = p;
+ p = p->pNext.load( memory_model::memory_order_acquire );
+ }
+
+ m_Stat.onCompactPublicationList();
+ }
+
+ publication_record * unlink_and_delete_record( publication_record * pPrev, publication_record * p )
+ {
+ if ( pPrev ) {
+ publication_record * pNext = p->pNext.load( memory_model::memory_order_acquire );
+ if ( pPrev->pNext.compare_exchange_strong( p, pNext,
+ memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed ))
+ {
+ cxx11_allocator().Delete( static_cast<publication_record_type *>( p ));
+ m_Stat.onDeletePubRecord();
+ }
+ return pNext;
+ }
+ else {
+ m_pHead = static_cast<publication_record_type *>( p->pNext.load( memory_model::memory_order_acquire ));
+ cxx11_allocator().Delete( static_cast<publication_record_type *>( p ));
+ m_Stat.onDeletePubRecord();
+ return m_pHead;
+ }
+ }
+ //@endcond
+ };
+
+ //@cond
+ class container
+ {
+ public:
+ template <typename PubRecord>
+ void fc_apply( PubRecord * )
+ {
+ assert( false );
+ }
+
+ template <typename Iterator>
+ void fc_process( Iterator, Iterator )
+ {
+ assert( false );
+ }
+ };
+ //@endcond
+
+ } // namespace flat_combining
+}} // namespace cds::algo
+
+#endif // #ifndef __CDS_ALGO_FLAT_COMBINING_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_BACKOFF_STRATEGY_H
+#define __CDS_BACKOFF_STRATEGY_H
+
+/*
+ Filename: backoff_strategy.h
+ Created 2007.03.01 by Maxim Khiszinsky
+
+ Description:
+ Generic back-off strategies
+
+ Editions:
+ 2007.03.01 Maxim Khiszinsky Created
+ 2008.10.02 Maxim Khiszinsky Backoff action transfers from contructor to operator() for all backoff schemas
+ 2009.09.10 Maxim Khiszinsky reset() function added
+*/
+
+#include <cds/compiler/backoff.h>
+#include <cds/details/std/thread.h>
+#include <cds/details/std/chrono.h>
+
+namespace cds {
+ /// Different backoff schemes
+ /**
+ Back-off schema may be used in lock-free algorithms when the algorithm cannot perform some action because a conflict
+ with the other concurrent operation is encountered. In this case current thread can do another work or can call
+ processor's performance hint.
+
+ The interface of back-off strategy is following:
+ \code
+ struct backoff_strategy {
+ void operator()();
+ template <typename Predicate> bool operator()( Predicate pr );
+ void reset();
+ };
+ \endcode
+
+ \p operator() operator calls back-off strategy's action. It is main part of back-off strategy.
+
+ Interruptible back-off <tt>template < typename Predicate > bool operator()( Predicate pr )</tt>
+ allows to interrupt back-off spinning if \p pr predicate returns \p true.
+ \p Predicate is a functor with the following interface:
+ \code
+ struct predicate {
+ bool operator()();
+ };
+ \endcode
+
+ \p reset() function resets internal state of back-off strategy to initial state. It is required for some
+ back-off strategies, for example, exponential back-off.
+ */
+ namespace backoff {
+
+ /// Empty backoff strategy. Do nothing
+ struct empty {
+ //@cond
+ void operator ()()
+ {}
+
+ template <typename Predicate>
+ bool operator()( Predicate pr )
+ {
+ return pr();
+ }
+
+ void reset()
+ {}
+ //@endcond
+ };
+
+ /// Switch to another thread (yield). Good for thread preemption architecture.
+ struct yield {
+ //@cond
+ void operator ()()
+ {
+ cds_std::this_thread::yield();
+ //OS::yield();
+ }
+
+ template <typename Predicate>
+ bool operator()( Predicate pr )
+ {
+ if ( pr() )
+ return true;
+ operator()();
+ return false;
+ }
+
+ void reset()
+ {}
+ //@endcond
+ };
+
+ /// Random pause
+ /**
+ This back-off strategy calls processor-specific pause hint instruction
+ if one is available for the processor architecture.
+ */
+ struct pause {
+ //@cond
+ void operator ()()
+ {
+# ifdef CDS_backoff_pause_defined
+ platform::backoff_pause();
+# endif
+ }
+
+ template <typename Predicate>
+ bool operator()( Predicate pr )
+ {
+ if ( pr() )
+ return true;
+ operator()();
+ return false;
+ }
+
+ void reset()
+ {}
+ //@endcond
+ };
+
+ /// Processor hint back-off
+ /**
+ This back-off schema calls performance hint instruction if it is available for current processor.
+ Otherwise, it calls \p nop.
+ */
+ struct hint
+ {
+ //@cond
+ void operator ()()
+ {
+# if defined(CDS_backoff_hint_defined)
+ platform::backoff_hint();
+# elif defined(CDS_backoff_nop_defined)
+ platform::backoff_nop();
+# endif
+ }
+
+ template <typename Predicate>
+ bool operator()( Predicate pr )
+ {
+ if ( pr() )
+ return true;
+ operator()();
+ return false;
+ }
+
+ void reset()
+ {}
+ //@endcond
+ };
+
+ /// Exponential back-off
+ /**
+ This back-off strategy is composite. It consists of \p SpinBkoff and \p YieldBkoff
+ back-off strategy. In first, the strategy tries to apply repeatedly \p SpinBkoff
+ (spinning phase) until internal counter of failed attempts reaches its maximum
+ spinning value. Then, the strategy transits to high-contention phase
+ where it applies \p YieldBkoff until \p reset() is called.
+ On each spinning iteration the internal spinning counter is doubled.
+
+ Choosing the best value for maximum spinning bound is platform and task specific.
+ In this implementation, the default values for maximum and minimum spinning is statically
+ declared so you can set its value globally for your platform.
+ The third template argument, \p Tag, is used to separate implementation. For
+ example, you may define two \p exponential back-offs that is the best for your task A and B:
+ \code
+
+ #include <cds/backoff_strategy.h>
+ namespace bkoff = cds::backoff;
+
+ struct tagA ; // tag to select task A implementation
+ struct tagB ; // tag to select task B implementation
+
+ // // define your back-off specialization
+ typedef bkoff::exponential<bkoff::hint, bkoff::yield, tagA> expBackOffA;
+ typedef bkoff::exponential<bkoff::hint, bkoff::yield, tagB> expBackOffB;
+
+ // // set up the best bounds for task A
+ expBackOffA::s_nExpMin = 32;
+ expBackOffA::s_nExpMax = 1024;
+
+ // // set up the best bounds for task B
+ expBackOffB::s_nExpMin = 2;
+ expBackOffB::s_nExpMax = 512;
+
+ \endcode
+
+ Another way of solving this problem is subclassing \p exponential back-off class:
+ \code
+ #include <cds/backoff_strategy.h>
+ namespace bkoff = cds::backoff;
+ typedef bkoff::exponential<bkoff::hint, bkoff::yield> base_bkoff;
+
+ class expBackOffA: public base_bkoff
+ {
+ public:
+ expBackOffA()
+ : base_bkoff( 32, 1024 )
+ {}
+ };
+
+ class expBackOffB: public base_bkoff
+ {
+ public:
+ expBackOffB()
+ : base_bkoff( 2, 512 )
+ {}
+ };
+ \endcode
+ */
+ template <typename SpinBkoff, typename YieldBkoff, typename Tag=void>
+ class exponential
+ {
+ public:
+ typedef SpinBkoff spin_backoff ; ///< spin back-off strategy
+ typedef YieldBkoff yield_backoff ; ///< yield back-off strategy
+ typedef Tag impl_tag ; ///< implementation separation tag
+
+ static size_t s_nExpMin ; ///< Default minimum spinning bound (16)
+ static size_t s_nExpMax ; ///< Default maximum spinning bound (16384)
+
+ protected:
+ size_t m_nExpCur ; ///< Current spinning
+ size_t m_nExpMin ; ///< Minimum spinning bound
+ size_t m_nExpMax ; ///< Maximum spinning bound
+
+ spin_backoff m_bkSpin ; ///< Spinning (fast-path) phase back-off strategy
+ yield_backoff m_bkYield ; ///< Yield phase back-off strategy
+
+ public:
+ /// Initializes m_nExpMin and m_nExpMax from default s_nExpMin and s_nExpMax respectively
+ exponential()
+ : m_nExpMin( s_nExpMin )
+ , m_nExpMax( s_nExpMax )
+ {
+ m_nExpCur = m_nExpMin;
+ }
+
+ /// Explicitly defined bounds of spinning
+ /**
+ The \p libcds library never calls this ctor.
+ */
+ exponential(
+ size_t nExpMin, ///< Minimum spinning
+ size_t nExpMax ///< Maximum spinning
+ )
+ : m_nExpMin( nExpMin )
+ , m_nExpMax( nExpMax )
+ {
+ m_nExpCur = m_nExpMin;
+ }
+
+ //@cond
+ void operator ()()
+ {
+ if ( m_nExpCur <= m_nExpMax ) {
+ for ( size_t n = 0; n < m_nExpCur; ++n )
+ m_bkSpin();
+ m_nExpCur *= 2;
+ }
+ else
+ m_bkYield();
+ }
+
+ template <typename Predicate>
+ bool operator()( Predicate pr )
+ {
+ if ( m_nExpCur <= m_nExpMax ) {
+ for ( size_t n = 0; n < m_nExpCur; ++n ) {
+ if ( m_bkSpin(pr) )
+ return true;
+ }
+ m_nExpCur *= 2;
+ }
+ else
+ return m_bkYield(pr);
+ return false;
+ }
+
+ void reset()
+ {
+ m_nExpCur = m_nExpMin;
+ m_bkSpin.reset();
+ m_bkYield.reset();
+ }
+ //@endcond
+ };
+
+ //@cond
+ template <typename SpinBkoff, typename YieldBkoff, typename Tag>
+ size_t exponential<SpinBkoff, YieldBkoff, Tag>::s_nExpMin = 16;
+
+ template <typename SpinBkoff, typename YieldBkoff, typename Tag>
+ size_t exponential<SpinBkoff, YieldBkoff, Tag>::s_nExpMax = 16 * 1024;
+ //@endcond
+
+ /// Delay back-off strategy
+ /**
+ Template arguments:
+ - \p Duration - duration type, default is \p std::chrono::milliseconds
+ - \p Tag - a selector tag
+
+ Choosing the best value for th timeout is platform and task specific.
+ In this implementation, the default values for timeout is statically
+ declared so you can set its value globally for your platform.
+ The second template argument, \p Tag, is used to separate implementation. For
+ example, you may define two \p delay back-offs for 5 and 10 ms timeout:
+ \code
+
+ #include <cds/backoff_strategy.h>
+ namespace bkoff = cds::backoff;
+
+ struct ms5 ; // tag to select 5ms
+ struct ms10 ; // tag to select 10ms
+
+ // // define your back-off specialization
+ typedef bkoff::delay<std::chrono::milliseconds, ms5> delay5;
+ typedef bkoff::delay<std::chrono::milliseconds, ms10> delay10;
+
+ // // set up the timeouts
+ delay5::s_nTimeout = 5;
+ delay10::s_nTimeout = 10;
+ \endcode
+
+ Another way of solving this problem is subclassing \p delay back-off class:
+ \code
+ #include <cds/backoff_strategy.h>
+ namespace bkoff = cds::backoff;
+ typedef bkoff::delay<> delay_bkoff;
+
+ class delay5: public delay_bkoff {
+ public:
+ delay5(): delay_bkoff( 5 ) {}
+ };
+
+ class delay10: public delay_bkoff {
+ public:
+ delay10(): delay_bkoff( 10 ) {}
+ };
+ \endcode
+
+ */
+ template <class Duration = cds_std::chrono::milliseconds, typename Tag=void >
+ class delay
+ {
+ public:
+ typedef Duration duration_type; ///< Duration type (default \p std::chrono::milliseconds)
+ static unsigned int s_nTimeout; ///< default timeout, =5
+
+ protected:
+ ///@cond
+ unsigned int const m_nTimeout;
+ ///@endcond
+
+ public:
+ /// Default ctor takes the timeout from s_nTimeout
+ delay()
+ : m_nTimeout( s_nTimeout )
+ {}
+
+ /// Initializes timeout from \p nTimeout
+ CDS_CONSTEXPR delay( unsigned int nTimeout )
+ : m_nTimeout( nTimeout )
+ {}
+
+ //@cond
+ void operator()() const
+ {
+ cds_std::this_thread::sleep_for( duration_type( m_nTimeout ));
+ }
+
+ template <typename Predicate>
+ bool operator()( Predicate pr ) const
+ {
+ for ( unsigned int i = 0; i < m_nTimeout; i += 2 ) {
+ if ( pr() )
+ return true;
+ cds_std::this_thread::sleep_for( duration_type( 2 ));
+ }
+ return false;
+ }
+
+ void reset() const
+ {}
+ //@endcond
+ };
+
+ //@cond
+ template <class Duration, typename Tag>
+ unsigned int delay<Duration, Tag>::s_nTimeout = 5;
+ //@endcond
+
+
+ /// Delay back-off strategy, template version
+ /**
+ This is a template version of backoff::delay class.
+ Template parameter \p Timeout sets a delay timeout.
+ The declaration <tt>cds::backoff::delay_of< 5 > bkoff</tt> is equal for
+ <tt>cds::backoff::delay<> bkoff(5)</tt>.
+ */
+ template <unsigned int Timeout, class Duration = cds_std::chrono::milliseconds >
+ class delay_of: public delay<Duration>
+ {
+ //@cond
+ typedef delay<Duration> base_class;
+ public:
+ delay_of()
+ : base_class( Timeout )
+ {}
+ //@endcond
+ };
+
+
+ /// Default backoff strategy
+ typedef exponential<hint, yield> Default;
+
+ /// Default back-off strategy for lock primitives
+ typedef exponential<hint, yield> LockDefault;
+
+ } // namespace backoff
+} // namespace cds
+
+
+#endif // #ifndef __CDS_BACKOFF_STRATEGY_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_BITOP_H
+#define __CDS_BITOP_H
+
+/*
+ Different bit algorithms:
+ LSB get least significant bit number
+ MSB get most significant bit number
+ bswap swap byte order of word
+ RBO reverse bit order of word
+
+ Editions:
+ 2007.10.08 Maxim.Khiszinsky Created
+*/
+
+#include <cds/details/defs.h>
+#include <cds/compiler/bitop.h>
+
+namespace cds {
+ /// Bit operations
+ namespace bitop {
+
+ ///@cond none
+ namespace details {
+ template <int> struct BitOps;
+
+ // 32-bit bit ops
+ template <> struct BitOps<4> {
+ typedef atomic32u_t TUInt;
+
+ static int MSB( TUInt x ) { return bitop::platform::msb32( x ); }
+ static int LSB( TUInt x ) { return bitop::platform::lsb32( x ); }
+ static int MSBnz( TUInt x ) { return bitop::platform::msb32nz( x ); }
+ static int LSBnz( TUInt x ) { return bitop::platform::lsb32nz( x ); }
+ static int SBC( TUInt x ) { return bitop::platform::sbc32( x ) ; }
+ static int ZBC( TUInt x ) { return bitop::platform::zbc32( x ) ; }
+
+ static TUInt RBO( TUInt x ) { return bitop::platform::rbo32( x ); }
+ static bool complement( TUInt& x, int nBit ) { return bitop::platform::complement32( &x, nBit ); }
+
+ static TUInt RandXorShift(TUInt x) { return bitop::platform::RandXorShift32(x); }
+ };
+
+ // 64-bit bit ops
+ template <> struct BitOps<8> {
+ typedef atomic64u_unaligned TUInt;
+
+ static int MSB( TUInt x ) { return bitop::platform::msb64( x ); }
+ static int LSB( TUInt x ) { return bitop::platform::lsb64( x ); }
+ static int MSBnz( TUInt x ) { return bitop::platform::msb64nz( x ); }
+ static int LSBnz( TUInt x ) { return bitop::platform::lsb64nz( x ); }
+ static int SBC( TUInt x ) { return bitop::platform::sbc64( x ) ; }
+ static int ZBC( TUInt x ) { return bitop::platform::zbc64( x ) ; }
+
+ static TUInt RBO( TUInt x ) { return bitop::platform::rbo64( x ); }
+ static bool complement( TUInt& x, int nBit ) { return bitop::platform::complement64( &x, nBit ); }
+
+ static TUInt RandXorShift(TUInt x) { return bitop::platform::RandXorShift64(x); }
+ };
+ } // namespace details
+ //@endcond
+
+
+ /// Get least significant bit (LSB) number (1..32/64), 0 if nArg == 0
+ template <typename T>
+ static inline int LSB( T nArg )
+ {
+ return details::BitOps< sizeof(T) >::LSB( (typename details::BitOps<sizeof(T)>::TUInt) nArg );
+ }
+
+ /// Get least significant bit (LSB) number (0..31/63)
+ /**
+ Precondition: nArg != 0
+ */
+ template <typename T>
+ static inline int LSBnz( T nArg )
+ {
+ assert( nArg != 0 );
+ return details::BitOps< sizeof(T) >::LSBnz( (typename details::BitOps<sizeof(T)>::TUInt) nArg );
+ }
+
+ /// Get most significant bit (MSB) number (1..32/64), 0 if nArg == 0
+ template <typename T>
+ static inline int MSB( T nArg )
+ {
+ return details::BitOps< sizeof(T) >::MSB( (typename details::BitOps<sizeof(T)>::TUInt) nArg );
+ }
+
+ /// Get most significant bit (MSB) number (0..31/63)
+ /**
+ Precondition: nArg != 0
+ */
+ template <typename T>
+ static inline int MSBnz( T nArg )
+ {
+ assert( nArg != 0 );
+ return details::BitOps< sizeof(T) >::MSBnz( (typename details::BitOps<sizeof(T)>::TUInt) nArg );
+ }
+
+ /// Get non-zero bit count of a word
+ template <typename T>
+ static inline int SBC( T nArg )
+ {
+ return details::BitOps< sizeof(T) >::SBC( (typename details::BitOps<sizeof(T)>::TUInt) nArg );
+ }
+
+ /// Get zero bit count of a word
+ template <typename T>
+ static inline int ZBC( T nArg )
+ {
+ return details::BitOps< sizeof(T) >::ZBC( (typename details::BitOps<sizeof(T)>::TUInt) nArg );
+ }
+
+ /// Reverse bit order of \p nArg
+ template <typename T>
+ static inline T RBO( T nArg )
+ {
+ return (T) details::BitOps< sizeof(T) >::RBO( (typename details::BitOps<sizeof(T)>::TUInt) nArg );
+ }
+
+ /// Complement bit \p nBit in \p nArg
+ template <typename T>
+ static inline bool complement( T& nArg, int nBit )
+ {
+ return details::BitOps< sizeof(T) >::complement( reinterpret_cast< typename details::BitOps<sizeof(T)>::TUInt& >( nArg ), nBit );
+ }
+
+ /// Simple random number generator
+ template <typename T>
+ static inline T RandXorShift( T x)
+ {
+ return (T) details::BitOps< sizeof(T) >::RandXorShift(x);
+ }
+
+ } // namespace bitop
+} //namespace cds
+
+#endif // #ifndef __CDS_BITOP_H
+
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_COMPILER_BACKOFF_IMPL_H
+#define __CDS_COMPILER_BACKOFF_IMPL_H
+
+#if CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS)
+# if CDS_PROCESSOR_ARCH == CDS_PROCESSOR_X86
+# include <cds/compiler/vc/x86/backoff.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_AMD64
+# include <cds/compiler/vc/amd64/backoff.h>
+# else
+# error "MS VC++ compiler: unsupported processor architecture"
+# endif
+#elif CDS_COMPILER == CDS_COMPILER_GCC || CDS_COMPILER == CDS_COMPILER_CLANG || CDS_COMPILER == CDS_COMPILER_INTEL
+# if CDS_PROCESSOR_ARCH == CDS_PROCESSOR_X86
+# include <cds/compiler/gcc/x86/backoff.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_AMD64
+# include <cds/compiler/gcc/amd64/backoff.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_IA64
+# include <cds/compiler/gcc/ia64/backoff.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_SPARC
+# include <cds/compiler/gcc/sparc/backoff.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_PPC64
+# include <cds/compiler/gcc/ppc64/backoff.h>
+//# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_ARM7
+//# include <cds/compiler/gcc/arm7/backoff.h>
+# endif
+#else
+# error "Undefined compiler"
+#endif
+
+#endif // #ifndef __CDS_COMPILER_BACKOFF_IMPL_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_COMPILER_BITOP_H
+#define __CDS_COMPILER_BITOP_H
+
+// Choose appropriate header for current architecture and compiler
+
+#if CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS)
+/************************************************************************/
+/* MS Visual C++ */
+/************************************************************************/
+
+# if CDS_PROCESSOR_ARCH == CDS_PROCESSOR_X86
+# include <cds/compiler/vc/x86/bitop.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_AMD64
+# include <cds/compiler/vc/amd64/bitop.h>
+# endif
+
+#elif CDS_COMPILER == CDS_COMPILER_GCC || CDS_COMPILER == CDS_COMPILER_CLANG || CDS_COMPILER == CDS_COMPILER_INTEL
+/************************************************************************/
+/* GCC */
+/************************************************************************/
+
+# if CDS_PROCESSOR_ARCH == CDS_PROCESSOR_X86
+# include <cds/compiler/gcc/x86/bitop.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_AMD64
+# include <cds/compiler/gcc/amd64/bitop.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_SPARC
+# include <cds/compiler/gcc/sparc/bitop.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_IA64
+# include <cds/compiler/gcc/ia64/bitop.h>
+# elif CDS_PROCESSOR_ARCH == CDS_PROCESSOR_PPC64
+# include <cds/compiler/gcc/ppc64/bitop.h>
+# endif
+#endif // Compiler choice
+
+// Generic (C) implementation
+#include <cds/details/bitop_generic.h>
+
+#endif // #ifndef __CDS_COMPILER_BITOP_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_COMPILER_CLANG_CXX11_ATOMIC_PREPATCHES_H
+#define __CDS_COMPILER_CLANG_CXX11_ATOMIC_PREPATCHES_H
+
+#if CDS_CXX11_ATOMIC_SUPPORT == 1
+# if CDS_COMPILER_VERSION == 30100
+ // Clang 3.1 workaround
+ // Clang 3.1 does not support __atomic_is_lock_free intrinsic function from GCC
+ template <typename T>
+ static inline bool __atomic_is_lock_free( size_t, T* ) CDS_NOEXCEPT
+ {
+ return sizeof(T) <= 8;
+ }
+
+ // clang does not implement GCC 4.7 low-level __atomic_xxx intrinsics
+ // See http://comments.gmane.org/gmane.comp.compilers.clang.devel/20093
+
+ // In Clang 3.1 the following workaround results in
+ // Assertion `Proto && "Functions without a prototype cannot be overloaded"' failed
+ // and clang crashed
+ // So, we cannot use Clang with GCC 4.7 atomics
+/*
+ template <typename T>
+ static inline void __atomic_load(T *ptr, T *ret, int memmodel)
+ {
+ *ret = __atomic_load( ptr, memmodel );
+ }
+
+ template <typename T>
+ static inline void __atomic_store(T *ptr, T *val, int memmodel)
+ {
+ __atomic_store( ptr, *val, memmodel );
+ }
+
+ template <typename T>
+ static inline void __atomic_exchange(T *ptr, T *val, T *ret, int memmodel)
+ {
+ *ret = __atomic_exchange( ptr, *val, memmodel );
+ }
+
+ template <typename T>
+ static inline bool __atomic_compare_exchange(T *ptr, T *expected, T *desired, bool weak, int success_memmodel, int failure_memmodel)
+ {
+ if ( weak )
+ return __atomic_compare_exchange_weak( ptr, expected, *desired, success_memmodel, failure_memmodel );
+ else
+ return __atomic_compare_exchange_strong( ptr, expected, *desired, success_memmodel, failure_memmodel );
+ }
+*/
+# endif
+#endif
+
+#endif // #ifndef __CDS_COMPILER_CLANG_CXX11_ATOMIC_PREPATCHES_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef __CDS_COMPILER_CLANG_DEFS_H
+#define __CDS_COMPILER_CLANG_DEFS_H
+
+// Compiler version
+#define CDS_COMPILER_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
+
+// Compiler name
+#define CDS_COMPILER__NAME ("clang " __clang_version__)
+#define CDS_COMPILER__NICK "clang"
+
+// C++11 atomic support - only for libc++
+// Note: Clang libc++ atomic leads to program crash.
+// So, we use libcds atomic implementation
+//#if __has_feature(cxx_atomic) && defined(_LIBCPP_VERSION)
+//# define CDS_CXX11_ATOMIC_SUPPORT 1
+//#endif
+
+
+#include <cds/compiler/gcc/compiler_macro.h>
+
+
+#define alignof __alignof__
+
+// Variadic template support (only if -std=c++0x compile-line option provided)
+#if __has_feature(cxx_variadic_templates)
+# define CDS_CXX11_VARIADIC_TEMPLATE_SUPPORT
+#endif
+
+// Default template arguments for function templates
+#if __has_feature(cxx_default_function_template_args)
+# define CDS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS_SUPPORT
+#endif
+
+#if __has_feature(cxx_deleted_functions)
+// C++11 delete definition ( function declaration = delete)
+# define CDS_CXX11_DELETE_DEFINITION_SUPPORT
+#endif
+
+#if __has_feature(cxx_defaulted_functions)
+// C++11 explicitly-defaulted function (= default) [std 8.4.2 [dcl.fct.def.default]]
+# define CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
+#endif
+
+// Explicit conversion operators
+#if __has_feature(cxx_explicit_conversions)
+# define CDS_CXX11_EXPLICIT_CONVERSION_OPERATOR_SUPPORT
+#endif
+
+// C++11 template alias
+#if __has_feature(cxx_alias_templates)
+# define CDS_CXX11_TEMPLATE_ALIAS_SUPPORT
+#endif
+
+// C++11 inline namespace
+#if __has_feature(cxx_inline_namespaces)
+# define CDS_CXX11_INLINE_NAMESPACE_SUPPORT
+#endif
+
+// Lambda
+#if __has_feature(cxx_lambdas)
+# define CDS_CXX11_LAMBDA_SUPPORT
+#endif
+
+// RValue
+#if __has_feature(cxx_rvalue_references)
+# define CDS_RVALUE_SUPPORT
+# define CDS_MOVE_SEMANTICS_SUPPORT
+#endif
+
+#if __has_feature(cxx_constexpr)
+# define CDS_CONSTEXPR constexpr
+# define CDS_CONSTEXPR_CONST constexpr const
+#else
+# define CDS_CONSTEXPR
+# define CDS_CONSTEXPR_CONST const
+#endif
+
+#if __has_feature(cxx_noexcept)
+# define CDS_NOEXCEPT_SUPPORT noexcept
+# define CDS_NOEXCEPT_SUPPORT_(expr) noexcept(expr)
+#else
+# define CDS_NOEXCEPT_SUPPORT
+# define CDS_NOEXCEPT_SUPPORT_(expr)
+#endif
+
+// C++11 thread_local keyword
+#if __has_feature(cxx_thread_local) // CLang 3.3
+# define CDS_CXX11_THREAD_LOCAL_SUPPORT
+#endif
+
+
+#include <cds/compiler/cstdint_std.h>
+
+// Thread support library (thread, mutex, condition variable, chrono)
+#if CDS_COMPILER_VERSION >= 30100
+# if __has_include(<thread>)
+# define CDS_CXX11_STDLIB_THREAD
+# endif
+
+# if __has_include(<chrono>)
+# define CDS_CXX11_STDLIB_CHRONO
+# endif
+
+# if __has_include(<mutex>)
+# define CDS_CXX11_STDLIB_MUTEX
+# endif
+
+# if __has_include(<condition_variable>)
+# define CDS_CXX11_STDLIB_CONDITION_VARIABLE
+# endif
+#endif
+
+// Full SFINAE support
+#define CDS_CXX11_SFINAE
+
+// *************************************************
+// Alignment macro
+
+#define CDS_TYPE_ALIGNMENT(n) __attribute__ ((aligned (n)))
+#define CDS_CLASS_ALIGNMENT(n) __attribute__ ((aligned (n)))
+#define CDS_DATA_ALIGNMENT(n) __attribute__ ((aligned (n)))
+
+
+#include <cds/compiler/gcc/compiler_barriers.h>
+
+#endif // #ifndef __CDS_COMPILER_GCC_DEFS_H