diff options
Diffstat (limited to '3rdParty/Boost/src/libs')
55 files changed, 4274 insertions, 1613 deletions
diff --git a/3rdParty/Boost/src/libs/atomic/README.md b/3rdParty/Boost/src/libs/atomic/README.md new file mode 100644 index 0000000..9c82949 --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/README.md @@ -0,0 +1,19 @@ +# + +Boost.Atomic, part of collection of the [Boost C++ Libraries](http://github.com/boostorg), implements atomic operations for various CPU architectures, reflecting the standard interface defined in C++11. + +### Directories + +* **build** - Boost.Atomic build scripts +* **doc** - QuickBook documentation sources +* **include** - Interface headers of Boost.Atomic +* **src** - Compilable source code of Boost.Atomic +* **test** - Boost.Atomic unit tests + +### More information + +* [Documentation](http://boost.org/libs/atomic) + +### License + +Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). diff --git a/3rdParty/Boost/src/libs/atomic/doc/Jamfile.v2 b/3rdParty/Boost/src/libs/atomic/doc/Jamfile.v2 new file mode 100644 index 0000000..c293a66 --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/doc/Jamfile.v2 @@ -0,0 +1,26 @@ +# Boost.Atomic library documentation Jamfile +# +# Copyright Helge Bahmann 2011. +# Copyright Tim Blechmann 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import quickbook ; +import boostbook : boostbook ; + +xml atomic : atomic.qbk ; + +boostbook standalone + : atomic + : <xsl:param>boost.root=../../../.. + <xsl:param>boost.libraries=../../../libraries.htm + <format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/atomic/doc/html + ; + +install css : [ glob $(BOOST_ROOT)/doc/src/*.css ] + : <location>html ; +install images : [ glob $(BOOST_ROOT)/doc/src/images/*.png ] + : <location>html/images ; +explicit css ; +explicit images ; diff --git a/3rdParty/Boost/src/libs/atomic/doc/atomic.hpp b/3rdParty/Boost/src/libs/atomic/doc/atomic.hpp new file mode 100644 index 0000000..60e61c2 --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/doc/atomic.hpp @@ -0,0 +1,547 @@ +/** \file boost/atomic.hpp */ + +// Copyright (c) 2009 Helge Bahmann +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +/* this is just a pseudo-header file fed to doxygen +to more easily generate the class documentation; will +be replaced by proper documentation down the road */ + +namespace boost { + +/** + \brief Memory ordering constraints + + This defines the relative order of one atomic operation + and other memory operations (loads, stores, other atomic operations) + executed by the same thread. + + The order of operations specified by the programmer in the + source code ("program order") does not necessarily match + the order in which they are actually executed on the target system: + Both compiler as well as processor may reorder operations + quite arbitrarily. <B>Specifying the wrong ordering + constraint will therefore generally result in an incorrect program.</B> +*/ +enum memory_order { + /** + \brief No constraint + Atomic operation and other memory operations may be reordered freely. + */ + memory_order_relaxed, + /** + \brief Data dependence constraint + Atomic operation must strictly precede any memory operation that + computationally depends on the outcome of the atomic operation. + */ + memory_order_consume, + /** + \brief Acquire memory + Atomic operation must strictly precede all memory operations that + follow in program order. + */ + memory_order_acquire, + /** + \brief Release memory + Atomic operation must strictly follow all memory operations that precede + in program order. + */ + memory_order_release, + /** + \brief Acquire and release memory + Combines the effects of \ref memory_order_acquire and \ref memory_order_release + */ + memory_order_acq_rel, + /** + \brief Sequentially consistent + Produces the same result \ref memory_order_acq_rel, but additionally + enforces globally sequential consistent execution + */ + memory_order_seq_cst +}; + +/** + \brief Atomic datatype + + An atomic variable. Provides methods to modify this variable atomically. + Valid template parameters are: + + - integral data types (char, short, int, ...) + - pointer data types + - any other data type that has a non-throwing default + constructor and that can be copied via <TT>memcpy</TT> + + Unless specified otherwise, any memory ordering constraint can be used + with any of the atomic operations. +*/ +template<typename Type> +class atomic { +public: + /** + \brief Create uninitialized atomic variable + Creates an atomic variable. Its initial value is undefined. + */ + atomic(); + /** + \brief Create an initialize atomic variable + \param value Initial value + Creates and initializes an atomic variable. + */ + explicit atomic(Type value); + + /** + \brief Read the current value of the atomic variable + \param order Memory ordering constraint, see \ref memory_order + \return Current value of the variable + + Valid memory ordering constraints are: + - @c memory_order_relaxed + - @c memory_order_consume + - @c memory_order_acquire + - @c memory_order_seq_cst + */ + Type load(memory_order order=memory_order_seq_cst) const; + + /** + \brief Write new value to atomic variable + \param value New value + \param order Memory ordering constraint, see \ref memory_order + + Valid memory ordering constraints are: + - @c memory_order_relaxed + - @c memory_order_release + - @c memory_order_seq_cst + */ + void store(Type value, memory_order order=memory_order_seq_cst); + + /** + \brief Atomically compare and exchange variable + \param expected Expected old value + \param desired Desired new value + \param order Memory ordering constraint, see \ref memory_order + \return @c true if value was changed + + Atomically performs the following operation + + \code + if (variable==expected) { + variable=desired; + return true; + } else { + expected=variable; + return false; + } + \endcode + + This operation may fail "spuriously", i.e. the state of the variable + is unchanged even though the expected value was found (this is the + case on architectures using "load-linked"/"store conditional" to + implement the operation). + + The established memory order will be @c order if the operation + is successful. If the operation is unsuccessful, the + memory order will be + + - @c memory_order_relaxed if @c order is @c memory_order_acquire , + @c memory_order_relaxed or @c memory_order_consume + - @c memory_order_release if @c order is @c memory_order_acq_release + or @c memory_order_release + - @c memory_order_seq_cst if @c order is @c memory_order_seq_cst + */ + bool compare_exchange_weak( + Type &expected, + Type desired, + memory_order order=memory_order_seq_cst); + + /** + \brief Atomically compare and exchange variable + \param expected Expected old value + \param desired Desired new value + \param success_order Memory ordering constraint if operation + is successful + \param failure_order Memory ordering constraint if operation is unsuccessful + \return @c true if value was changed + + Atomically performs the following operation + + \code + if (variable==expected) { + variable=desired; + return true; + } else { + expected=variable; + return false; + } + \endcode + + This operation may fail "spuriously", i.e. the state of the variable + is unchanged even though the expected value was found (this is the + case on architectures using "load-linked"/"store conditional" to + implement the operation). + + The constraint imposed by @c success_order may not be + weaker than the constraint imposed by @c failure_order. + */ + bool compare_exchange_weak( + Type &expected, + Type desired, + memory_order success_order, + memory_order failure_order); + /** + \brief Atomically compare and exchange variable + \param expected Expected old value + \param desired Desired new value + \param order Memory ordering constraint, see \ref memory_order + \return @c true if value was changed + + Atomically performs the following operation + + \code + if (variable==expected) { + variable=desired; + return true; + } else { + expected=variable; + return false; + } + \endcode + + In contrast to \ref compare_exchange_weak, this operation will never + fail spuriously. Since compare-and-swap must generally be retried + in a loop, implementors are advised to prefer \ref compare_exchange_weak + where feasible. + + The established memory order will be @c order if the operation + is successful. If the operation is unsuccessful, the + memory order will be + + - @c memory_order_relaxed if @c order is @c memory_order_acquire , + @c memory_order_relaxed or @c memory_order_consume + - @c memory_order_release if @c order is @c memory_order_acq_release + or @c memory_order_release + - @c memory_order_seq_cst if @c order is @c memory_order_seq_cst + */ + bool compare_exchange_strong( + Type &expected, + Type desired, + memory_order order=memory_order_seq_cst); + + /** + \brief Atomically compare and exchange variable + \param expected Expected old value + \param desired Desired new value + \param success_order Memory ordering constraint if operation + is successful + \param failure_order Memory ordering constraint if operation is unsuccessful + \return @c true if value was changed + + Atomically performs the following operation + + \code + if (variable==expected) { + variable=desired; + return true; + } else { + expected=variable; + return false; + } + \endcode + + In contrast to \ref compare_exchange_weak, this operation will never + fail spuriously. Since compare-and-swap must generally be retried + in a loop, implementors are advised to prefer \ref compare_exchange_weak + where feasible. + + The constraint imposed by @c success_order may not be + weaker than the constraint imposed by @c failure_order. + */ + bool compare_exchange_strong( + Type &expected, + Type desired, + memory_order success_order, + memory_order failure_order); + /** + \brief Atomically exchange variable + \param value New value + \param order Memory ordering constraint, see \ref memory_order + \return Old value of the variable + + Atomically exchanges the value of the variable with the new + value and returns its old value. + */ + Type exchange(Type value, memory_order order=memory_order_seq_cst); + + /** + \brief Atomically add and return old value + \param operand Operand + \param order Memory ordering constraint, see \ref memory_order + \return Old value of the variable + + Atomically adds operand to the variable and returns its + old value. + */ + Type fetch_add(Type operand, memory_order order=memory_order_seq_cst); + /** + \brief Atomically subtract and return old value + \param operand Operand + \param order Memory ordering constraint, see \ref memory_order + \return Old value of the variable + + Atomically subtracts operand from the variable and returns its + old value. + + This method is available only if \c Type is an integral type + or a non-void pointer type. If it is a pointer type, + @c operand is of type @c ptrdiff_t and the operation + is performed following the rules for pointer arithmetic + in C++. + */ + Type fetch_sub(Type operand, memory_order order=memory_order_seq_cst); + + /** + \brief Atomically perform bitwise "AND" and return old value + \param operand Operand + \param order Memory ordering constraint, see \ref memory_order + \return Old value of the variable + + Atomically performs bitwise "AND" with the variable and returns its + old value. + + This method is available only if \c Type is an integral type + or a non-void pointer type. If it is a pointer type, + @c operand is of type @c ptrdiff_t and the operation + is performed following the rules for pointer arithmetic + in C++. + */ + Type fetch_and(Type operand, memory_order order=memory_order_seq_cst); + + /** + \brief Atomically perform bitwise "OR" and return old value + \param operand Operand + \param order Memory ordering constraint, see \ref memory_order + \return Old value of the variable + + Atomically performs bitwise "OR" with the variable and returns its + old value. + + This method is available only if \c Type is an integral type. + */ + Type fetch_or(Type operand, memory_order order=memory_order_seq_cst); + + /** + \brief Atomically perform bitwise "XOR" and return old value + \param operand Operand + \param order Memory ordering constraint, see \ref memory_order + \return Old value of the variable + + Atomically performs bitwise "XOR" with the variable and returns its + old value. + + This method is available only if \c Type is an integral type. + */ + Type fetch_xor(Type operand, memory_order order=memory_order_seq_cst); + + /** + \brief Implicit load + \return Current value of the variable + + The same as <tt>load(memory_order_seq_cst)</tt>. Avoid using + the implicit conversion operator, use \ref load with + an explicit memory ordering constraint. + */ + operator Type(void) const; + /** + \brief Implicit store + \param value New value + \return Copy of @c value + + The same as <tt>store(value, memory_order_seq_cst)</tt>. Avoid using + the implicit conversion operator, use \ref store with + an explicit memory ordering constraint. + */ + Type operator=(Type v); + + /** + \brief Atomically perform bitwise "AND" and return new value + \param operand Operand + \return New value of the variable + + The same as <tt>fetch_and(operand, memory_order_seq_cst)&operand</tt>. + Avoid using the implicit bitwise "AND" operator, use \ref fetch_and + with an explicit memory ordering constraint. + */ + Type operator&=(Type operand); + + /** + \brief Atomically perform bitwise "OR" and return new value + \param operand Operand + \return New value of the variable + + The same as <tt>fetch_or(operand, memory_order_seq_cst)|operand</tt>. + Avoid using the implicit bitwise "OR" operator, use \ref fetch_or + with an explicit memory ordering constraint. + + This method is available only if \c Type is an integral type. + */ + Type operator|=(Type operand); + + /** + \brief Atomically perform bitwise "XOR" and return new value + \param operand Operand + \return New value of the variable + + The same as <tt>fetch_xor(operand, memory_order_seq_cst)^operand</tt>. + Avoid using the implicit bitwise "XOR" operator, use \ref fetch_xor + with an explicit memory ordering constraint. + + This method is available only if \c Type is an integral type. + */ + Type operator^=(Type operand); + + /** + \brief Atomically add and return new value + \param operand Operand + \return New value of the variable + + The same as <tt>fetch_add(operand, memory_order_seq_cst)+operand</tt>. + Avoid using the implicit add operator, use \ref fetch_add + with an explicit memory ordering constraint. + + This method is available only if \c Type is an integral type + or a non-void pointer type. If it is a pointer type, + @c operand is of type @c ptrdiff_t and the operation + is performed following the rules for pointer arithmetic + in C++. + */ + Type operator+=(Type operand); + + /** + \brief Atomically subtract and return new value + \param operand Operand + \return New value of the variable + + The same as <tt>fetch_sub(operand, memory_order_seq_cst)-operand</tt>. + Avoid using the implicit subtract operator, use \ref fetch_sub + with an explicit memory ordering constraint. + + This method is available only if \c Type is an integral type + or a non-void pointer type. If it is a pointer type, + @c operand is of type @c ptrdiff_t and the operation + is performed following the rules for pointer arithmetic + in C++. + */ + Type operator-=(Type operand); + + /** + \brief Atomically increment and return new value + \return New value of the variable + + The same as <tt>fetch_add(1, memory_order_seq_cst)+1</tt>. + Avoid using the implicit increment operator, use \ref fetch_add + with an explicit memory ordering constraint. + + This method is available only if \c Type is an integral type + or a non-void pointer type. If it is a pointer type, + the operation + is performed following the rules for pointer arithmetic + in C++. + */ + Type operator++(void); + /** + \brief Atomically increment and return old value + \return Old value of the variable + + The same as <tt>fetch_add(1, memory_order_seq_cst)</tt>. + Avoid using the implicit increment operator, use \ref fetch_add + with an explicit memory ordering constraint. + + This method is available only if \c Type is an integral type + or a non-void pointer type. If it is a pointer type, + the operation + is performed following the rules for pointer arithmetic + in C++. + */ + Type operator++(int); + /** + \brief Atomically subtract and return new value + \return New value of the variable + + The same as <tt>fetch_sub(1, memory_order_seq_cst)-1</tt>. + Avoid using the implicit increment operator, use \ref fetch_sub + with an explicit memory ordering constraint. + + This method is available only if \c Type is an integral type + or a non-void pointer type. If it is a pointer type, + the operation + is performed following the rules for pointer arithmetic + in C++. + */ + Type operator--(void); + /** + \brief Atomically subtract and return old value + \return Old value of the variable + + The same as <tt>fetch_sub(1, memory_order_seq_cst)</tt>. + Avoid using the implicit increment operator, use \ref fetch_sub + with an explicit memory ordering constraint. + + This method is available only if \c Type is an integral type + or a non-void pointer type. If it is a pointer type, + the operation + is performed following the rules for pointer arithmetic + in C++. + */ + Type operator--(int); + + /** \brief Deleted copy constructor */ + atomic(const atomic &) = delete; + /** \brief Deleted copy assignment */ + const atomic & operator=(const atomic &) = delete; +}; + +/** + \brief Insert explicit fence for thread synchronization + \param order Memory ordering constraint + + Inserts an explicit fence. The exact semantic depends on the + type of fence inserted: + + - \c memory_order_relaxed: No operation + - \c memory_order_release: Performs a "release" operation + - \c memory_order_acquire or \c memory_order_consume: Performs an + "acquire" operation + - \c memory_order_acq_rel: Performs both an "acquire" and a "release" + operation + - \c memory_order_seq_cst: Performs both an "acquire" and a "release" + operation and in addition there exists a global total order of + all \c memory_order_seq_cst operations + +*/ +void atomic_thread_fence(memory_order order); + +/** + \brief Insert explicit fence for synchronization with a signal handler + \param order Memory ordering constraint + + Inserts an explicit fence to synchronize with a signal handler called within + the context of the same thread. The fence ensures the corresponding operations + around it are complete and/or not started. The exact semantic depends on the + type of fence inserted: + + - \c memory_order_relaxed: No operation + - \c memory_order_release: Ensures the operations before the fence are complete + - \c memory_order_acquire or \c memory_order_consume: Ensures the operations + after the fence are not started. + - \c memory_order_acq_rel or \c memory_order_seq_cst: Ensures the operations + around the fence do not cross it. + + Note that this call does not affect visibility order of the memory operations + to other threads. It is functionally similar to \c atomic_thread_fence, only + it does not generate any instructions to synchronize hardware threads. +*/ +void atomic_signal_fence(memory_order order); + +} diff --git a/3rdParty/Boost/src/libs/atomic/doc/atomic.qbk b/3rdParty/Boost/src/libs/atomic/doc/atomic.qbk new file mode 100644 index 0000000..880fab5 --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/doc/atomic.qbk @@ -0,0 +1,828 @@ +[/ + / Copyright (c) 2009 Helge Bahmann + / Copyright (c) 2014 Andrey Semashev + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[library Boost.Atomic + [quickbook 1.4] + [authors [Bahmann, Helge][Semashev, Andrey]] + [copyright 2011 Helge Bahmann] + [copyright 2012 Tim Blechmann] + [copyright 2013 Andrey Semashev] + [id atomic] + [dirname atomic] + [purpose Atomic operations] + [license + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + [@http://www.boost.org/LICENSE_1_0.txt]) + ] +] + +[section:introduction Introduction] + +[section:introduction_presenting Presenting Boost.Atomic] + +[*Boost.Atomic] is a library that provides [^atomic] +data types and operations on these data types, as well as memory +ordering constraints required for coordinating multiple threads through +atomic variables. It implements the interface as defined by the C++11 +standard, but makes this feature available for platforms lacking +system/compiler support for this particular C++11 feature. + +Users of this library should already be familiar with concurrency +in general, as well as elementary concepts such as "mutual exclusion". + +The implementation makes use of processor-specific instructions where +possible (via inline assembler, platform libraries or compiler +intrinsics), and falls back to "emulating" atomic operations through +locking. + +[endsect] + +[section:introduction_purpose Purpose] + +Operations on "ordinary" variables are not guaranteed to be atomic. +This means that with [^int n=0] initially, two threads concurrently +executing + +[c++] + + void function() + { + n ++; + } + +might result in [^n==1] instead of 2: Each thread will read the +old value into a processor register, increment it and write the result +back. Both threads may therefore write [^1], unaware that the other thread +is doing likewise. + +Declaring [^atomic<int> n=0] instead, the same operation on +this variable will always result in [^n==2] as each operation on this +variable is ['atomic]: This means that each operation behaves as if it +were strictly sequentialized with respect to the other. + +Atomic variables are useful for two purposes: + +* as a means for coordinating multiple threads via custom + coordination protocols +* as faster alternatives to "locked" access to simple variables + +Take a look at the [link atomic.usage_examples examples] section +for common patterns. + +[endsect] + +[endsect] + +[section:thread_coordination Thread coordination using Boost.Atomic] + +The most common use of [*Boost.Atomic] is to realize custom +thread synchronization protocols: The goal is to coordinate +accesses of threads to shared variables in order to avoid +"conflicts". The +programmer must be aware of the fact that +compilers, CPUs and the cache +hierarchies may generally reorder memory references at will. +As a consequence a program such as: + +[c++] + + int x = 0, int y = 0; + + thread1: + x = 1; + y = 1; + + thread2 + if (y == 1) { + assert(x == 1); + } + +might indeed fail as there is no guarantee that the read of `x` +by thread2 "sees" the write by thread1. + +[*Boost.Atomic] uses a synchronisation concept based on the +['happens-before] relation to describe the guarantees under +which situations such as the above one cannot occur. + +The remainder of this section will discuss ['happens-before] in +a "hands-on" way instead of giving a fully formalized definition. +The reader is encouraged to additionally have a +look at the discussion of the correctness of a few of the +[link atomic.usage_examples examples] afterwards. + +[section:mutex Enforcing ['happens-before] through mutual exclusion] + +As an introductory example to understand how arguing using +['happens-before] works, consider two threads synchronizing +using a common mutex: + +[c++] + + mutex m; + + thread1: + m.lock(); + ... /* A */ + m.unlock(); + + thread2: + m.lock(); + ... /* B */ + m.unlock(); + +The "lockset-based intuition" would be to argue that A and B +cannot be executed concurrently as the code paths require a +common lock to be held. + +One can however also arrive at the same conclusion using +['happens-before]: Either thread1 or thread2 will succeed first +at [^m.lock()]. If this is be thread1, then as a consequence, +thread2 cannot succeed at [^m.lock()] before thread1 has executed +[^m.unlock()], consequently A ['happens-before] B in this case. +By symmetry, if thread2 succeeds at [^m.lock()] first, we can +conclude B ['happens-before] A. + +Since this already exhausts all options, we can conclude that +either A ['happens-before] B or B ['happens-before] A must +always hold. Obviously cannot state ['which] of the two relationships +holds, but either one is sufficient to conclude that A and B +cannot conflict. + +Compare the [link boost_atomic.usage_examples.example_spinlock spinlock] +implementation to see how the mutual exclusion concept can be +mapped to [*Boost.Atomic]. + +[endsect] + +[section:release_acquire ['happens-before] through [^release] and [^acquire]] + +The most basic pattern for coordinating threads via [*Boost.Atomic] +uses [^release] and [^acquire] on an atomic variable for coordination: If ... + +* ... thread1 performs an operation A, +* ... thread1 subsequently writes (or atomically + modifies) an atomic variable with [^release] semantic, +* ... thread2 reads (or atomically reads-and-modifies) + the value this value from the same atomic variable with + [^acquire] semantic and +* ... thread2 subsequently performs an operation B, + +... then A ['happens-before] B. + +Consider the following example + +[c++] + + atomic<int> a(0); + + thread1: + ... /* A */ + a.fetch_add(1, memory_order_release); + + thread2: + int tmp = a.load(memory_order_acquire); + if (tmp == 1) { + ... /* B */ + } else { + ... /* C */ + } + +In this example, two avenues for execution are possible: + +* The [^store] operation by thread1 precedes the [^load] by thread2: + In this case thread2 will execute B and "A ['happens-before] B" + holds as all of the criteria above are satisfied. +* The [^load] operation by thread2 precedes the [^store] by thread1: + In this case, thread2 will execute C, but "A ['happens-before] C" + does ['not] hold: thread2 does not read the value written by + thread1 through [^a]. + +Therefore, A and B cannot conflict, but A and C ['can] conflict. + +[endsect] + +[section:fences Fences] + +Ordering constraints are generally specified together with an access to +an atomic variable. It is however also possible to issue "fence" +operations in isolation, in this case the fence operates in +conjunction with preceding (for `acquire`, `consume` or `seq_cst` +operations) or succeeding (for `release` or `seq_cst`) atomic +operations. + +The example from the previous section could also be written in +the following way: + +[c++] + + atomic<int> a(0); + + thread1: + ... /* A */ + atomic_thread_fence(memory_order_release); + a.fetch_add(1, memory_order_relaxed); + + thread2: + int tmp = a.load(memory_order_relaxed); + if (tmp == 1) { + atomic_thread_fence(memory_order_acquire); + ... /* B */ + } else { + ... /* C */ + } + +This provides the same ordering guarantees as previously, but +elides a (possibly expensive) memory ordering operation in +the case C is executed. + +[endsect] + +[section:release_consume ['happens-before] through [^release] and [^consume]] + +The second pattern for coordinating threads via [*Boost.Atomic] +uses [^release] and [^consume] on an atomic variable for coordination: If ... + +* ... thread1 performs an operation A, +* ... thread1 subsequently writes (or atomically modifies) an + atomic variable with [^release] semantic, +* ... thread2 reads (or atomically reads-and-modifies) + the value this value from the same atomic variable with [^consume] semantic and +* ... thread2 subsequently performs an operation B that is ['computationally + dependent on the value of the atomic variable], + +... then A ['happens-before] B. + +Consider the following example + +[c++] + + atomic<int> a(0); + complex_data_structure data[2]; + + thread1: + data[1] = ...; /* A */ + a.store(1, memory_order_release); + + thread2: + int index = a.load(memory_order_consume); + complex_data_structure tmp = data[index]; /* B */ + +In this example, two avenues for execution are possible: + +* The [^store] operation by thread1 precedes the [^load] by thread2: + In this case thread2 will read [^data\[1\]] and "A ['happens-before] B" + holds as all of the criteria above are satisfied. +* The [^load] operation by thread2 precedes the [^store] by thread1: + In this case thread2 will read [^data\[0\]] and "A ['happens-before] B" + does ['not] hold: thread2 does not read the value written by + thread1 through [^a]. + +Here, the ['happens-before] relationship helps ensure that any +accesses (presumable writes) to [^data\[1\]] by thread1 happen before +before the accesses (presumably reads) to [^data\[1\]] by thread2: +Lacking this relationship, thread2 might see stale/inconsistent +data. + +Note that in this example, the fact that operation B is computationally +dependent on the atomic variable, therefore the following program would +be erroneous: + +[c++] + + atomic<int> a(0); + complex_data_structure data[2]; + + thread1: + data[1] = ...; /* A */ + a.store(1, memory_order_release); + + thread2: + int index = a.load(memory_order_consume); + complex_data_structure tmp; + if (index == 0) + tmp = data[0]; + else + tmp = data[1]; + +[^consume] is most commonly (and most safely! see +[link atomic.limitations limitations]) used with +pointers, compare for example the +[link boost_atomic.usage_examples.singleton singleton with double-checked locking]. + +[endsect] + +[section:seq_cst Sequential consistency] + +The third pattern for coordinating threads via [*Boost.Atomic] +uses [^seq_cst] for coordination: If ... + +* ... thread1 performs an operation A, +* ... thread1 subsequently performs any operation with [^seq_cst], +* ... thread1 subsequently performs an operation B, +* ... thread2 performs an operation C, +* ... thread2 subsequently performs any operation with [^seq_cst], +* ... thread2 subsequently performs an operation D, + +then either "A ['happens-before] D" or "C ['happens-before] B" holds. + +In this case it does not matter whether thread1 and thread2 operate +on the same or different atomic variables, or use a "stand-alone" +[^atomic_thread_fence] operation. + +[endsect] + +[endsect] + +[section:interface Programming interfaces] + +[section:configuration Configuration and building] + +The library contains header-only and compiled parts. The library is +header-only for lock-free cases but requires a separate binary to +implement the lock-based emulation. Users are able to detect whether +linking to the compiled part is required by checking the +[link atomic.interface.feature_macros feature macros]. + +The following macros affect library behavior: + +[table + [[Macro] [Description]] + [[`BOOST_ATOMIC_NO_CMPXCHG16B`] [Affects 64-bit x86 MSVC builds. When defined, + the library assumes the target CPU does not support `cmpxchg16b` instruction used + to support 128-bit atomic operations. This is the case with some early 64-bit AMD CPUs, + all Intel CPUs and current AMD CPUs support this instruction. The library does not + perform runtime detection of this instruction, so running the code that uses 128-bit + atomics on such CPUs will result in crashes, unless this macro is defined. Note that + the macro does not affect GCC and compatible compilers because the library infers + this information from the compiler-defined macros.]] + [[`BOOST_ATOMIC_FORCE_FALLBACK`] [When defined, all operations are implemented with locks. + This is mostly used for testing and should not be used in real world projects.]] + [[`BOOST_ATOMIC_DYN_LINK` and `BOOST_ALL_DYN_LINK`] [Control library linking. If defined, + the library assumes dynamic linking, otherwise static. The latter macro affects all Boost + libraries, not just [*Boost.Atomic].]] + [[`BOOST_ATOMIC_NO_LIB` and `BOOST_ALL_NO_LIB`] [Control library auto-linking on Windows. + When defined, disables auto-linking. The latter macro affects all Boost libraries, + not just [*Boost.Atomic].]] +] + +Besides macros, it is important to specify the correct compiler options for the target CPU. +With GCC and compatible compilers this affects whether particular atomic operations are +lock-free or not. + +Boost building process is described in the [@http://www.boost.org/doc/libs/release/more/getting_started/ Getting Started guide]. +For example, you can build [*Boost.Atomic] with the following command line: + +[pre + bjam --with-atomic variant=release instruction-set=core2 stage +] + +[endsect] + +[section:interface_memory_order Memory order] + + #include <boost/memory_order.hpp> + +The enumeration [^boost::memory_order] defines the following +values to represent memory ordering constraints: + +[table + [[Constant] [Description]] + [[`memory_order_relaxed`] [No ordering constraint. + Informally speaking, following operations may be reordered before, + preceding operations may be reordered after the atomic + operation. This constraint is suitable only when + either a) further operations do not depend on the outcome + of the atomic operation or b) ordering is enforced through + stand-alone `atomic_thread_fence` operations. The operation on + the atomic value itself is still atomic though. + ]] + [[`memory_order_release`] [ + Perform `release` operation. Informally speaking, + prevents all preceding memory operations to be reordered + past this point. + ]] + [[`memory_order_acquire`] [ + Perform `acquire` operation. Informally speaking, + prevents succeeding memory operations to be reordered + before this point. + ]] + [[`memory_order_consume`] [ + Perform `consume` operation. More relaxed (and + on some architectures more efficient) than `memory_order_acquire` + as it only affects succeeding operations that are + computationally-dependent on the value retrieved from + an atomic variable. + ]] + [[`memory_order_acq_rel`] [Perform both `release` and `acquire` operation]] + [[`memory_order_seq_cst`] [ + Enforce sequential consistency. Implies `memory_order_acq_rel`, but + additionally enforces total order for all operations such qualified. + ]] +] + +See section [link atomic.thread_coordination ['happens-before]] for explanation +of the various ordering constraints. + +[endsect] + +[section:interface_atomic_object Atomic objects] + + #include <boost/atomic/atomic.hpp> + +[^boost::atomic<['T]>] provides methods for atomically accessing +variables of a suitable type [^['T]]. The type is suitable if +it is /trivially copyable/ (3.9/9 \[basic.types\]). Following are +examples of the types compatible with this requirement: + +* a scalar type (e.g. integer, boolean, enum or pointer type) +* a [^class] or [^struct] that has no non-trivial copy or move + constructors or assignment operators, has a trivial destructor, + and that is comparable via [^memcmp]. + +Note that classes with virtual functions or virtual base classes +do not satisfy the requirements. Also be warned +that structures with "padding" between data members may compare +non-equal via [^memcmp] even though all members are equal. + +[section:interface_atomic_generic [^boost::atomic<['T]>] template class] + +All atomic objects supports the following operations: + +[table + [[Syntax] [Description]] + [ + [`atomic()`] + [Initialize to an unspecified value] + ] + [ + [`atomic(T initial_value)`] + [Initialize to [^initial_value]] + ] + [ + [`bool is_lock_free()`] + [Checks if the atomic object is lock-free] + ] + [ + [`T load(memory_order order)`] + [Return current value] + ] + [ + [`void store(T value, memory_order order)`] + [Write new value to atomic variable] + ] + [ + [`T exchange(T new_value, memory_order order)`] + [Exchange current value with `new_value`, returning current value] + ] + [ + [`bool compare_exchange_weak(T & expected, T desired, memory_order order)`] + [Compare current value with `expected`, change it to `desired` if matches. + Returns `true` if an exchange has been performed, and always writes the + previous value back in `expected`. May fail spuriously, so must generally be + retried in a loop.] + ] + [ + [`bool compare_exchange_weak(T & expected, T desired, memory_order success_order, memory_order failure_order)`] + [Compare current value with `expected`, change it to `desired` if matches. + Returns `true` if an exchange has been performed, and always writes the + previous value back in `expected`. May fail spuriously, so must generally be + retried in a loop.] + ] + [ + [`bool compare_exchange_strong(T & expected, T desired, memory_order order)`] + [Compare current value with `expected`, change it to `desired` if matches. + Returns `true` if an exchange has been performed, and always writes the + previous value back in `expected`.] + ] + [ + [`bool compare_exchange_strong(T & expected, T desired, memory_order success_order, memory_order failure_order))`] + [Compare current value with `expected`, change it to `desired` if matches. + Returns `true` if an exchange has been performed, and always writes the + previous value back in `expected`.] + ] +] + +`order` always has `memory_order_seq_cst` as default parameter. + +The `compare_exchange_weak`/`compare_exchange_strong` variants +taking four parameters differ from the three parameter variants +in that they allow a different memory ordering constraint to +be specified in case the operation fails. + +In addition to these explicit operations, each +[^atomic<['T]>] object also supports +implicit [^store] and [^load] through the use of "assignment" +and "conversion to [^T]" operators. Avoid using these operators, +as they do not allow explicit specification of a memory ordering +constraint. + +[endsect] + +[section:interface_atomic_integral [^boost::atomic<['integral]>] template class] + +In addition to the operations listed in the previous section, +[^boost::atomic<['I]>] for integral +types [^['I]] supports the following operations: + +[table + [[Syntax] [Description]] + [ + [`T fetch_add(T v, memory_order order)`] + [Add `v` to variable, returning previous value] + ] + [ + [`T fetch_sub(T v, memory_order order)`] + [Subtract `v` from variable, returning previous value] + ] + [ + [`T fetch_and(T v, memory_order order)`] + [Apply bit-wise "and" with `v` to variable, returning previous value] + ] + [ + [`T fetch_or(T v, memory_order order)`] + [Apply bit-wise "or" with `v` to variable, returning previous value] + ] + [ + [`T fetch_xor(T v, memory_order order)`] + [Apply bit-wise "xor" with `v` to variable, returning previous value] + ] +] + +`order` always has `memory_order_seq_cst` as default parameter. + +In addition to these explicit operations, each +[^boost::atomic<['I]>] object also +supports implicit pre-/post- increment/decrement, as well +as the operators `+=`, `-=`, `&=`, `|=` and `^=`. +Avoid using these operators, +as they do not allow explicit specification of a memory ordering +constraint. + +[endsect] + +[section:interface_atomic_pointer [^boost::atomic<['pointer]>] template class] + +In addition to the operations applicable to all atomic object, +[^boost::atomic<['P]>] for pointer +types [^['P]] (other than [^void] pointers) support the following operations: + +[table + [[Syntax] [Description]] + [ + [`T fetch_add(ptrdiff_t v, memory_order order)`] + [Add `v` to variable, returning previous value] + ] + [ + [`T fetch_sub(ptrdiff_t v, memory_order order)`] + [Subtract `v` from variable, returning previous value] + ] +] + +`order` always has `memory_order_seq_cst` as default parameter. + +In addition to these explicit operations, each +[^boost::atomic<['P]>] object also +supports implicit pre-/post- increment/decrement, as well +as the operators `+=`, `-=`. Avoid using these operators, +as they do not allow explicit specification of a memory ordering +constraint. + +[endsect] + +[endsect] + +[section:interface_fences Fences] + + #include <boost/atomic/fences.hpp> + +[table + [[Syntax] [Description]] + [ + [`void atomic_thread_fence(memory_order order)`] + [Issue fence for coordination with other threads.] + ] + [ + [`void atomic_signal_fence(memory_order order)`] + [Issue fence for coordination with signal handler (only in same thread).] + ] +] + +[endsect] + +[section:feature_macros Feature testing macros] + + #include <boost/atomic/capabilities.hpp> + +[*Boost.Atomic] defines a number of macros to allow compile-time +detection whether an atomic data type is implemented using +"true" atomic operations, or whether an internal "lock" is +used to provide atomicity. The following macros will be +defined to `0` if operations on the data type always +require a lock, to `1` if operations on the data type may +sometimes require a lock, and to `2` if they are always lock-free: + +[table + [[Macro] [Description]] + [ + [`BOOST_ATOMIC_FLAG_LOCK_FREE`] + [Indicate whether `atomic_flag` is lock-free] + ] + [ + [`BOOST_ATOMIC_BOOL_LOCK_FREE`] + [Indicate whether `atomic<bool>` is lock-free] + ] + [ + [`BOOST_ATOMIC_CHAR_LOCK_FREE`] + [Indicate whether `atomic<char>` (including signed/unsigned variants) is lock-free] + ] + [ + [`BOOST_ATOMIC_CHAR16_T_LOCK_FREE`] + [Indicate whether `atomic<char16_t>` (including signed/unsigned variants) is lock-free] + ] + [ + [`BOOST_ATOMIC_CHAR32_T_LOCK_FREE`] + [Indicate whether `atomic<char32_t>` (including signed/unsigned variants) is lock-free] + ] + [ + [`BOOST_ATOMIC_WCHAR_T_LOCK_FREE`] + [Indicate whether `atomic<wchar_t>` (including signed/unsigned variants) is lock-free] + ] + [ + [`BOOST_ATOMIC_SHORT_LOCK_FREE`] + [Indicate whether `atomic<short>` (including signed/unsigned variants) is lock-free] + ] + [ + [`BOOST_ATOMIC_INT_LOCK_FREE`] + [Indicate whether `atomic<int>` (including signed/unsigned variants) is lock-free] + ] + [ + [`BOOST_ATOMIC_LONG_LOCK_FREE`] + [Indicate whether `atomic<long>` (including signed/unsigned variants) is lock-free] + ] + [ + [`BOOST_ATOMIC_LLONG_LOCK_FREE`] + [Indicate whether `atomic<long long>` (including signed/unsigned variants) is lock-free] + ] + [ + [`BOOST_ATOMIC_ADDRESS_LOCK_FREE` or `BOOST_ATOMIC_POINTER_LOCK_FREE`] + [Indicate whether `atomic<T *>` is lock-free] + ] + [ + [`BOOST_ATOMIC_THREAD_FENCE`] + [Indicate whether `atomic_thread_fence` function is lock-free] + ] + [ + [`BOOST_ATOMIC_SIGNAL_FENCE`] + [Indicate whether `atomic_signal_fence` function is lock-free] + ] +] + +In addition to these standard macros, [*Boost.Atomic] also defines a number of extension macros, +which can also be useful. Like the standard ones, these macros are defined to values `0`, `1` and `2` +to indicate whether the corresponding operations are lock-free or not. + +[table + [[Macro] [Description]] + [ + [`BOOST_ATOMIC_INT8_LOCK_FREE`] + [Indicate whether `atomic<int8_type>` is lock-free.] + ] + [ + [`BOOST_ATOMIC_INT16_LOCK_FREE`] + [Indicate whether `atomic<int16_type>` is lock-free.] + ] + [ + [`BOOST_ATOMIC_INT32_LOCK_FREE`] + [Indicate whether `atomic<int32_type>` is lock-free.] + ] + [ + [`BOOST_ATOMIC_INT64_LOCK_FREE`] + [Indicate whether `atomic<int64_type>` is lock-free.] + ] + [ + [`BOOST_ATOMIC_INT128_LOCK_FREE`] + [Indicate whether `atomic<int128_type>` is lock-free.] + ] + [ + [`BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT`] + [Defined after including `atomic_flag.hpp`, if the implementation + does not support the `BOOST_ATOMIC_FLAG_INIT` macro for static + initialization of `atomic_flag`. This macro is typically defined + for pre-C++11 compilers.] + ] +] + +In the table above, `intN_type` is a type that fits storage of contiguous `N` bits, suitably aligned for atomic operations. + +[endsect] + +[endsect] + +[section:usage_examples Usage examples] + +[include examples.qbk] + +[endsect] + +[/ +[section:platform_support Implementing support for additional platforms] + +[include platform.qbk] + +[endsect] +] + +[/ [xinclude autodoc.xml] ] + +[section:limitations Limitations] + +While [*Boost.Atomic] strives to implement the atomic operations +from C++11 as faithfully as possible, there are a few +limitations that cannot be lifted without compiler support: + +* [*Using non-POD-classes as template parameter to `atomic<T>` results + in undefined behavior]: This means that any class containing a + constructor, destructor, virtual methods or access control + specifications is not a valid argument in C++98. C++11 relaxes + this slightly by allowing "trivial" classes containing only + empty constructors. [*Advise]: Use only POD types. +* [*C++98 compilers may transform computation- to control-dependency]: + Crucially, `memory_order_consume` only affects computationally-dependent + operations, but in general there is nothing preventing a compiler + from transforming a computation dependency into a control dependency. + A C++11 compiler would be forbidden from such a transformation. + [*Advise]: Use `memory_order_consume` only in conjunction with + pointer values, as the compiler cannot speculate and transform + these into control dependencies. +* [*Fence operations enforce "too strong" compiler ordering]: + Semantically, `memory_order_acquire`/`memory_order_consume` + and `memory_order_release` need to restrain reordering of + memory operations only in one direction. Since there is no + way to express this constraint to the compiler, these act + as "full compiler barriers" in this implementation. In corner + cases this may result in a less efficient code than a C++11 compiler + could generate. +* [*No interprocess fallback]: using `atomic<T>` in shared memory only works + correctly, if `atomic<T>::is_lock_free() == true`. + +[endsect] + +[section:porting Porting] + +[section:unit_tests Unit tests] + +[*Boost.Atomic] provides a unit test suite to verify that the +implementation behaves as expected: + +* [*fallback_api.cpp] verifies that the fallback-to-locking aspect + of [*Boost.Atomic] compiles and has correct value semantics. +* [*native_api.cpp] verifies that all atomic operations have correct + value semantics (e.g. "fetch_add" really adds the desired value, + returning the previous). It is a rough "smoke-test" to help weed + out the most obvious mistakes (for example width overflow, + signed/unsigned extension, ...). +* [*lockfree.cpp] verifies that the [*BOOST_ATOMIC_*_LOCKFREE] macros + are set properly according to the expectations for a given + platform, and that they match up with the [*is_lock_free] member + functions of the [*atomic] object instances. +* [*atomicity.cpp] lets two threads race against each other modifying + a shared variable, verifying that the operations behave atomic + as appropriate. By nature, this test is necessarily stochastic, and + the test self-calibrates to yield 99% confidence that a + positive result indicates absence of an error. This test is + very useful on uni-processor systems with preemption already. +* [*ordering.cpp] lets two threads race against each other accessing + multiple shared variables, verifying that the operations + exhibit the expected ordering behavior. By nature, this test is + necessarily stochastic, and the test attempts to self-calibrate to + yield 99% confidence that a positive result indicates absence + of an error. This only works on true multi-processor (or multi-core) + systems. It does not yield any result on uni-processor systems + or emulators (due to there being no observable reordering even + the order=relaxed case) and will report that fact. + +[endsect] + +[section:tested_compilers Tested compilers] + +[*Boost.Atomic] has been tested on and is known to work on +the following compilers/platforms: + +* gcc 4.x: i386, x86_64, ppc32, ppc64, sparcv9, armv6, alpha +* Visual Studio Express 2008/Windows XP, x86, x64, ARM + +[endsect] + +[section:acknowledgements Acknowledgements] + +* Adam Wulkiewicz created the logo used on the [@https://github.com/boostorg/atomic GitHub project page]. The logo was taken from his [@https://github.com/awulkiew/boost-logos collection] of Boost logos. + +[endsect] + +[endsect] diff --git a/3rdParty/Boost/src/libs/atomic/doc/examples.qbk b/3rdParty/Boost/src/libs/atomic/doc/examples.qbk new file mode 100644 index 0000000..e34c402 --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/doc/examples.qbk @@ -0,0 +1,398 @@ +[/ + / Copyright (c) 2009 Helge Bahmann + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:example_reference_counters Reference counting] + +The purpose of a ['reference counter] is to count the number +of pointers to an object. The object can be destroyed as +soon as the reference counter reaches zero. + +[section Implementation] + +[c++] + + #include <boost/intrusive_ptr.hpp> + #include <boost/atomic.hpp> + + class X { + public: + typedef boost::intrusive_ptr<X> pointer; + X() : refcount_(0) {} + + private: + mutable boost::atomic<int> refcount_; + friend void intrusive_ptr_add_ref(const X * x) + { + x->refcount_.fetch_add(1, boost::memory_order_relaxed); + } + friend void intrusive_ptr_release(const X * x) + { + if (x->refcount_.fetch_sub(1, boost::memory_order_release) == 1) { + boost::atomic_thread_fence(boost::memory_order_acquire); + delete x; + } + } + }; + +[endsect] + +[section Usage] + +[c++] + + X::pointer x = new X; + +[endsect] + +[section Discussion] + +Increasing the reference counter can always be done with +[^memory_order_relaxed]: New references to an object can only +be formed from an existing reference, and passing an existing +reference from one thread to another must already provide any +required synchronization. + +It is important to enforce any possible access to the object in +one thread (through an existing reference) to ['happen before] +deleting the object in a different thread. This is achieved +by a "release" operation after dropping a reference (any +access to the object through this reference must obviously +happened before), and an "acquire" operation before +deleting the object. + +It would be possible to use [^memory_order_acq_rel] for the +[^fetch_sub] operation, but this results in unneeded "acquire" +operations when the reference counter does not yet reach zero +and may impose a performance penalty. + +[endsect] + +[endsect] + +[section:example_spinlock Spinlock] + +The purpose of a ['spin lock] is to prevent multiple threads +from concurrently accessing a shared data structure. In contrast +to a mutex, threads will busy-wait and waste CPU cycles instead +of yielding the CPU to another thread. ['Do not use spinlocks +unless you are certain that you understand the consequences.] + +[section Implementation] + +[c++] + + #include <boost/atomic.hpp> + + class spinlock { + private: + typedef enum {Locked, Unlocked} LockState; + boost::atomic<LockState> state_; + + public: + spinlock() : state_(Unlocked) {} + + void lock() + { + while (state_.exchange(Locked, boost::memory_order_acquire) == Locked) { + /* busy-wait */ + } + } + void unlock() + { + state_.store(Unlocked, boost::memory_order_release); + } + }; + +[endsect] + +[section Usage] + +[c++] + + spinlock s; + + s.lock(); + // access data structure here + s.unlock(); + +[endsect] + +[section Discussion] + +The purpose of the spinlock is to make sure that one access +to the shared data structure always strictly "happens before" +another. The usage of acquire/release in lock/unlock is required +and sufficient to guarantee this ordering. + +It would be correct to write the "lock" operation in the following +way: + +[c++] + + lock() + { + while (state_.exchange(Locked, boost::memory_order_relaxed) == Locked) { + /* busy-wait */ + } + atomic_thread_fence(boost::memory_order_acquire); + } + +This "optimization" is however a) useless and b) may in fact hurt: +a) Since the thread will be busily spinning on a blocked spinlock, +it does not matter if it will waste the CPU cycles with just +"exchange" operations or with both useless "exchange" and "acquire" +operations. b) A tight "exchange" loop without any +memory-synchronizing instruction introduced through an "acquire" +operation will on some systems monopolize the memory subsystem +and degrade the performance of other system components. + +[endsect] + +[endsect] + +[section:singleton Singleton with double-checked locking pattern] + +The purpose of the ['Singleton with double-checked locking pattern] is to ensure +that at most one instance of a particular object is created. +If one instance has been created already, access to the existing +object should be as light-weight as possible. + +[section Implementation] + +[c++] + + #include <boost/atomic.hpp> + #include <boost/thread/mutex.hpp> + + class X { + public: + static X * instance() + { + X * tmp = instance_.load(boost::memory_order_consume); + if (!tmp) { + boost::mutex::scoped_lock guard(instantiation_mutex); + tmp = instance_.load(boost::memory_order_consume); + if (!tmp) { + tmp = new X; + instance_.store(tmp, boost::memory_order_release); + } + } + return tmp; + } + private: + static boost::atomic<X *> instance_; + static boost::mutex instantiation_mutex; + }; + + boost::atomic<X *> X::instance_(0); + +[endsect] + +[section Usage] + +[c++] + + X * x = X::instance(); + // dereference x + +[endsect] + +[section Discussion] + +The mutex makes sure that only one instance of the object is +ever created. The [^instance] method must make sure that any +dereference of the object strictly "happens after" creating +the instance in another thread. The use of [^memory_order_release] +after creating and initializing the object and [^memory_order_consume] +before dereferencing the object provides this guarantee. + +It would be permissible to use [^memory_order_acquire] instead of +[^memory_order_consume], but this provides a stronger guarantee +than is required since only operations depending on the value of +the pointer need to be ordered. + +[endsect] + +[endsect] + +[section:example_ringbuffer Wait-free ring buffer] + +A ['wait-free ring buffer] provides a mechanism for relaying objects +from one single "producer" thread to one single "consumer" thread without +any locks. The operations on this data structure are "wait-free" which +means that each operation finishes within a constant number of steps. +This makes this data structure suitable for use in hard real-time systems +or for communication with interrupt/signal handlers. + +[section Implementation] + +[c++] + + #include <boost/atomic.hpp> + + template<typename T, size_t Size> + class ringbuffer { + public: + ringbuffer() : head_(0), tail_(0) {} + + bool push(const T & value) + { + size_t head = head_.load(boost::memory_order_relaxed); + size_t next_head = next(head); + if (next_head == tail_.load(boost::memory_order_acquire)) + return false; + ring_[head] = value; + head_.store(next_head, boost::memory_order_release); + return true; + } + bool pop(T & value) + { + size_t tail = tail_.load(boost::memory_order_relaxed); + if (tail == head_.load(boost::memory_order_acquire)) + return false; + value = ring_[tail]; + tail_.store(next(tail), boost::memory_order_release); + return true; + } + private: + size_t next(size_t current) + { + return (current + 1) % Size; + } + T ring_[Size]; + boost::atomic<size_t> head_, tail_; + }; + +[endsect] + +[section Usage] + +[c++] + + ringbuffer<int, 32> r; + + // try to insert an element + if (r.push(42)) { /* succeeded */ } + else { /* buffer full */ } + + // try to retrieve an element + int value; + if (r.pop(value)) { /* succeeded */ } + else { /* buffer empty */ } + +[endsect] + +[section Discussion] + +The implementation makes sure that the ring indices do +not "lap-around" each other to ensure that no elements +are either lost or read twice. + +Furthermore it must guarantee that read-access to a +particular object in [^pop] "happens after" it has been +written in [^push]. This is achieved by writing [^head_ ] +with "release" and reading it with "acquire". Conversely +the implementation also ensures that read access to +a particular ring element "happens before" before +rewriting this element with a new value by accessing [^tail_] +with appropriate ordering constraints. + +[endsect] + +[endsect] + +[section:mp_queue Wait-free multi-producer queue] + +The purpose of the ['wait-free multi-producer queue] is to allow +an arbitrary number of producers to enqueue objects which are +retrieved and processed in FIFO order by a single consumer. + +[section Implementation] + +[c++] + + template<typename T> + class waitfree_queue { + public: + struct node { + T data; + node * next; + }; + void push(const T &data) + { + node * n = new node; + n->data = data; + node * stale_head = head_.load(boost::memory_order_relaxed); + do { + n->next = stale_head; + } while (!head_.compare_exchange_weak(stale_head, n, boost::memory_order_release)); + } + + node * pop_all(void) + { + T * last = pop_all_reverse(), * first = 0; + while(last) { + T * tmp = last; + last = last->next; + tmp->next = first; + first = tmp; + } + return first; + } + + waitfree_queue() : head_(0) {} + + // alternative interface if ordering is of no importance + node * pop_all_reverse(void) + { + return head_.exchange(0, boost::memory_order_consume); + } + private: + boost::atomic<node *> head_; + }; + +[endsect] + +[section Usage] + +[c++] + + waitfree_queue<int> q; + + // insert elements + q.push(42); + q.push(2); + + // pop elements + waitfree_queue<int>::node * x = q.pop_all() + while(x) { + X * tmp = x; + x = x->next; + // process tmp->data, probably delete it afterwards + delete tmp; + } + +[endsect] + +[section Discussion] + +The implementation guarantees that all objects enqueued are +processed in the order they were enqueued by building a singly-linked +list of object in reverse processing order. The queue is atomically +emptied by the consumer and brought into correct order. + +It must be guaranteed that any access to an object to be enqueued +by the producer "happens before" any access by the consumer. This +is assured by inserting objects into the list with ['release] and +dequeuing them with ['consume] memory order. It is not +necessary to use ['acquire] memory order in [^waitfree_queue::pop_all] +because all operations involved depend on the value of +the atomic pointer through dereference + +[endsect] + +[endsect] diff --git a/3rdParty/Boost/src/libs/atomic/doc/logo.png b/3rdParty/Boost/src/libs/atomic/doc/logo.png Binary files differnew file mode 100644 index 0000000..8b12104 --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/doc/logo.png diff --git a/3rdParty/Boost/src/libs/atomic/doc/logo.svg b/3rdParty/Boost/src/libs/atomic/doc/logo.svg new file mode 100644 index 0000000..50d078e --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/doc/logo.svg @@ -0,0 +1,1053 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="744.09448819" + height="1052.3622047" + id="svg7933" + version="1.1" + inkscape:version="0.48.4 r9939" + sodipodi:docname="atomic.svg"> + <defs + id="defs7935"> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4453-7-8-6-7-87" + id="linearGradient10687-9" + gradientUnits="userSpaceOnUse" + x1="753.02301" + y1="3132.0801" + x2="1146.25" + y2="3132.0801" /> + <linearGradient + id="linearGradient4453-7-8-6-7-87"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop4455-61-8-7-1-8" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop4457-4-1-9-1-4" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4453-7-8-6-7-87" + id="linearGradient10685-44" + gradientUnits="userSpaceOnUse" + x1="753.02301" + y1="3132.0801" + x2="1146.25" + y2="3132.0801" /> + <linearGradient + id="linearGradient7822"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop7824" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop7826" /> + </linearGradient> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3387-3-6-4-2-3"> + <path + inkscape:connector-curvature="0" + d="m 862.109,3289.75 -109.086,-190.45 69.122,-124.42 164.511,-0.47 c 0,0 111.044,188.28 116.564,197.63 7.66,0 43.03,0 43.03,0 l -67.03,117.71 -217.111,0 z" + id="path3389-2-0-7-7-58" /> + </clipPath> + <linearGradient + y2="3132.0801" + x2="1146.25" + y1="3132.0801" + x1="753.02301" + gradientUnits="userSpaceOnUse" + id="linearGradient4492-0" + xlink:href="#linearGradient4453-7-8-6-7-87" + inkscape:collect="always" /> + <linearGradient + id="linearGradient7831"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop7833" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop7835" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4453-7-8-6-7-87" + id="linearGradient10691-2" + gradientUnits="userSpaceOnUse" + x1="1026.6899" + y1="2937.73" + x2="1463.14" + y2="2937.73" /> + <linearGradient + id="linearGradient7838"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop7840" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop7842" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4453-7-8-6-7-87" + id="linearGradient10689-9" + gradientUnits="userSpaceOnUse" + x1="1026.6899" + y1="2937.73" + x2="1463.14" + y2="2937.73" /> + <linearGradient + id="linearGradient7845"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop7847" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop7849" /> + </linearGradient> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3369-1-5-6-1-49"> + <path + inkscape:connector-curvature="0" + d="m 1131.64,3128.5 -104.95,-181.12 116.38,-200.42 208.05,0.94 112.02,191.63 -112.08,188.97 -219.42,0 z" + id="path3371-89-4-1-6-8" /> + </clipPath> + <linearGradient + y2="2937.73" + x2="1463.14" + y1="2937.73" + x1="1026.6899" + gradientUnits="userSpaceOnUse" + id="linearGradient4498-3" + xlink:href="#linearGradient4453-7-8-6-7-87" + inkscape:collect="always" /> + <linearGradient + id="linearGradient7854"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop7856" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop7858" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4459-1-2-8-9-0" + id="linearGradient10695-5" + gradientUnits="userSpaceOnUse" + x1="646.55499" + y1="2736.25" + x2="1088.27" + y2="2736.25" /> + <linearGradient + id="linearGradient4459-1-2-8-9-0"> + <stop + id="stop4461-2-1-5-2-43" + offset="0" + style="stop-color:#839bc2;stop-opacity:1;" /> + <stop + id="stop4463-3-2-8-7-5" + offset="1" + style="stop-color:#9fb6d4;stop-opacity:1;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4459-1-2-8-9-0" + id="linearGradient10693-2" + gradientUnits="userSpaceOnUse" + x1="646.55499" + y1="2736.25" + x2="1088.27" + y2="2736.25" /> + <linearGradient + id="linearGradient7865"> + <stop + id="stop7867" + offset="0" + style="stop-color:#839bc2;stop-opacity:1;" /> + <stop + id="stop7869" + offset="1" + style="stop-color:#9fb6d4;stop-opacity:1;" /> + </linearGradient> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3351-4-7-3-5-57"> + <path + inkscape:connector-curvature="0" + d="m 757.242,2926.25 -110.687,-189.11 110.656,-190.89 219.437,0 111.622,189.1 -111.59,190.9 -219.438,0 z" + id="path3353-1-9-3-4-77" /> + </clipPath> + <linearGradient + y2="2736.25" + x2="1088.27" + y1="2736.25" + x1="646.55499" + gradientUnits="userSpaceOnUse" + id="linearGradient4510-4" + xlink:href="#linearGradient4459-1-2-8-9-0" + inkscape:collect="always" /> + <linearGradient + id="linearGradient7874"> + <stop + id="stop7876" + offset="0" + style="stop-color:#839bc2;stop-opacity:1;" /> + <stop + id="stop7878" + offset="1" + style="stop-color:#9fb6d4;stop-opacity:1;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#radialGradient3327-8-4-8-0-0" + id="radialGradient10699-4" + gradientUnits="userSpaceOnUse" + cx="997.46997" + cy="2896.25" + fx="997.46997" + fy="2896.25" + r="583.73999" /> + <radialGradient + fx="0" + fy="0" + cx="0" + cy="0" + r="1" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)" + spreadMethod="pad" + id="radialGradient3327-8-4-8-0-0"> + <stop + style="stop-opacity:1;stop-color:#aeaeb3" + offset="0" + id="stop3329-7-0-1-0-4" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="0.949438" + id="stop3331-4-3-0-0-11" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="1" + id="stop3333-2-4-9-7-54" /> + </radialGradient> + <radialGradient + r="583.73999" + fy="2896.25" + fx="997.46997" + cy="2896.25" + cx="997.46997" + gradientUnits="userSpaceOnUse" + id="radialGradient15837" + xlink:href="#radialGradient3327-8-4-8-0-0" + inkscape:collect="always" /> + <radialGradient + fx="0" + fy="0" + cx="0" + cy="0" + r="1" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)" + spreadMethod="pad" + id="radialGradient7886"> + <stop + style="stop-opacity:1;stop-color:#aeaeb3" + offset="0" + id="stop7888" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="0.949438" + id="stop7890" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="1" + id="stop7892" /> + </radialGradient> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3323-7-2-4-5-2"> + <path + inkscape:connector-curvature="0" + d="m 997.469,2312.51 c -322.379,0 -583.739,261.36 -583.739,583.74 0,322.38 261.36,583.74 583.739,583.74 322.381,0 583.741,-261.36 583.741,-583.74 0,-322.38 -261.36,-583.74 -583.741,-583.74" + id="path3325-9-2-9-5-8" /> + </clipPath> + <radialGradient + r="583.73999" + fy="2896.25" + fx="997.46997" + cy="2896.25" + cx="997.46997" + gradientUnits="userSpaceOnUse" + id="radialGradient4516-6" + xlink:href="#radialGradient3327-8-4-8-0-0" + inkscape:collect="always" /> + <radialGradient + fx="0" + fy="0" + cx="0" + cy="0" + r="1" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)" + spreadMethod="pad" + id="radialGradient7897"> + <stop + style="stop-opacity:1;stop-color:#aeaeb3" + offset="0" + id="stop7899" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="0.949438" + id="stop7901" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="1" + id="stop7903" /> + </radialGradient> + <radialGradient + r="583.73999" + fy="2896.25" + fx="997.46997" + cy="2896.25" + cx="997.46997" + gradientUnits="userSpaceOnUse" + id="radialGradient7931" + xlink:href="#radialGradient3327-8-4-8-0-0" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4453-7-8-6-7-87-7" + id="linearGradient10687-9-1" + gradientUnits="userSpaceOnUse" + x1="753.02301" + y1="3132.0801" + x2="1146.25" + y2="3132.0801" /> + <linearGradient + id="linearGradient4453-7-8-6-7-87-7"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop4455-61-8-7-1-8-4" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop4457-4-1-9-1-4-0" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4453-7-8-6-7-87-7" + id="linearGradient10685-44-9" + gradientUnits="userSpaceOnUse" + x1="753.02301" + y1="3132.0801" + x2="1146.25" + y2="3132.0801" /> + <linearGradient + id="linearGradient3083"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop3085" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop3087" /> + </linearGradient> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3387-3-6-4-2-3-4"> + <path + inkscape:connector-curvature="0" + d="m 862.109,3289.75 -109.086,-190.45 69.122,-124.42 164.511,-0.47 c 0,0 111.044,188.28 116.564,197.63 7.66,0 43.03,0 43.03,0 l -67.03,117.71 -217.111,0 z" + id="path3389-2-0-7-7-58-8" /> + </clipPath> + <linearGradient + y2="3132.0801" + x2="1146.25" + y1="3132.0801" + x1="753.02301" + gradientUnits="userSpaceOnUse" + id="linearGradient4492-0-8" + xlink:href="#linearGradient4453-7-8-6-7-87-7" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3092"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop3094" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop3096" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4453-7-8-6-7-87-7" + id="linearGradient10691-2-2" + gradientUnits="userSpaceOnUse" + x1="1026.6899" + y1="2937.73" + x2="1463.14" + y2="2937.73" /> + <linearGradient + id="linearGradient3099"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop3101" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop3103" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4453-7-8-6-7-87-7" + id="linearGradient10689-9-4" + gradientUnits="userSpaceOnUse" + x1="1026.6899" + y1="2937.73" + x2="1463.14" + y2="2937.73" /> + <linearGradient + id="linearGradient3106"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop3108" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop3110" /> + </linearGradient> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3369-1-5-6-1-49-5"> + <path + inkscape:connector-curvature="0" + d="m 1131.64,3128.5 -104.95,-181.12 116.38,-200.42 208.05,0.94 112.02,191.63 -112.08,188.97 -219.42,0 z" + id="path3371-89-4-1-6-8-5" /> + </clipPath> + <linearGradient + y2="2937.73" + x2="1463.14" + y1="2937.73" + x1="1026.6899" + gradientUnits="userSpaceOnUse" + id="linearGradient4498-3-1" + xlink:href="#linearGradient4453-7-8-6-7-87-7" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3115"> + <stop + style="stop-color:#aac4dd;stop-opacity:1;" + offset="0" + id="stop3117" /> + <stop + style="stop-color:#c2dbe9;stop-opacity:1;" + offset="1" + id="stop3119" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4459-1-2-8-9-0-1" + id="linearGradient10695-5-7" + gradientUnits="userSpaceOnUse" + x1="646.55499" + y1="2736.25" + x2="1088.27" + y2="2736.25" /> + <linearGradient + id="linearGradient4459-1-2-8-9-0-1"> + <stop + id="stop4461-2-1-5-2-43-1" + offset="0" + style="stop-color:#839bc2;stop-opacity:1;" /> + <stop + id="stop4463-3-2-8-7-5-5" + offset="1" + style="stop-color:#9fb6d4;stop-opacity:1;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4459-1-2-8-9-0-1" + id="linearGradient10693-2-2" + gradientUnits="userSpaceOnUse" + x1="646.55499" + y1="2736.25" + x2="1088.27" + y2="2736.25" /> + <linearGradient + id="linearGradient3126"> + <stop + id="stop3128" + offset="0" + style="stop-color:#839bc2;stop-opacity:1;" /> + <stop + id="stop3130" + offset="1" + style="stop-color:#9fb6d4;stop-opacity:1;" /> + </linearGradient> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3351-4-7-3-5-57-7"> + <path + inkscape:connector-curvature="0" + d="m 757.242,2926.25 -110.687,-189.11 110.656,-190.89 219.437,0 111.622,189.1 -111.59,190.9 -219.438,0 z" + id="path3353-1-9-3-4-77-6" /> + </clipPath> + <linearGradient + y2="2736.25" + x2="1088.27" + y1="2736.25" + x1="646.55499" + gradientUnits="userSpaceOnUse" + id="linearGradient4510-4-1" + xlink:href="#linearGradient4459-1-2-8-9-0-1" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3135"> + <stop + id="stop3137" + offset="0" + style="stop-color:#839bc2;stop-opacity:1;" /> + <stop + id="stop3139" + offset="1" + style="stop-color:#9fb6d4;stop-opacity:1;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#radialGradient3327-8-4-8-0-0-2" + id="radialGradient10699-4-4" + gradientUnits="userSpaceOnUse" + cx="997.46997" + cy="2896.25" + fx="997.46997" + fy="2896.25" + r="583.73999" /> + <radialGradient + fx="0" + fy="0" + cx="0" + cy="0" + r="1" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)" + spreadMethod="pad" + id="radialGradient3327-8-4-8-0-0-2"> + <stop + style="stop-opacity:1;stop-color:#aeaeb3" + offset="0" + id="stop3329-7-0-1-0-4-3" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="0.949438" + id="stop3331-4-3-0-0-11-2" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="1" + id="stop3333-2-4-9-7-54-2" /> + </radialGradient> + <radialGradient + r="583.73999" + fy="2896.25" + fx="997.46997" + cy="2896.25" + cx="997.46997" + gradientUnits="userSpaceOnUse" + id="radialGradient7931-1" + xlink:href="#radialGradient3327-8-4-8-0-0-2" + inkscape:collect="always" /> + <radialGradient + fx="0" + fy="0" + cx="0" + cy="0" + r="1" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)" + spreadMethod="pad" + id="radialGradient3147"> + <stop + style="stop-opacity:1;stop-color:#aeaeb3" + offset="0" + id="stop3149" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="0.949438" + id="stop3151" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="1" + id="stop3153" /> + </radialGradient> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath3323-7-2-4-5-2-6"> + <path + inkscape:connector-curvature="0" + d="m 997.469,2312.51 c -322.379,0 -583.739,261.36 -583.739,583.74 0,322.38 261.36,583.74 583.739,583.74 322.381,0 583.741,-261.36 583.741,-583.74 0,-322.38 -261.36,-583.74 -583.741,-583.74" + id="path3325-9-2-9-5-8-8" /> + </clipPath> + <radialGradient + r="583.73999" + fy="2896.25" + fx="997.46997" + cy="2896.25" + cx="997.46997" + gradientUnits="userSpaceOnUse" + id="radialGradient4516-6-5" + xlink:href="#radialGradient3327-8-4-8-0-0-2" + inkscape:collect="always" /> + <radialGradient + fx="0" + fy="0" + cx="0" + cy="0" + r="1" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(58.375,0,0,-58.375,99.75,289.625)" + spreadMethod="pad" + id="radialGradient3158"> + <stop + style="stop-opacity:1;stop-color:#aeaeb3" + offset="0" + id="stop3160" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="0.949438" + id="stop3162" /> + <stop + style="stop-opacity:1;stop-color:#ffffff" + offset="1" + id="stop3164" /> + </radialGradient> + <radialGradient + r="583.73999" + fy="2896.25" + fx="997.46997" + cy="2896.25" + cx="997.46997" + gradientUnits="userSpaceOnUse" + id="radialGradient3192" + xlink:href="#radialGradient3327-8-4-8-0-0-2" + inkscape:collect="always" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.98994949" + inkscape:cx="194.37763" + inkscape:cy="577.68232" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1680" + inkscape:window-height="982" + inkscape:window-x="-8" + inkscape:window-y="-8" + inkscape:window-maximized="1" /> + <metadata + id="metadata7938"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <g + id="g3319-1-2-5-1-8" + transform="matrix(0.10419818,0,0,-0.10419818,149.49392,819.86044)" + style="fill:url(#radialGradient10699-4);fill-opacity:1" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <g + clip-path="url(#clipPath3323-7-2-4-5-2)" + id="g3321-9-2-7-4-14" + style="fill:url(#radialGradient7931);fill-opacity:1"> + <path + id="path3335-8-7-3-8-7" + style="fill:url(#radialGradient4516-6);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 997.469,2312.51 c -322.379,0 -583.739,261.36 -583.739,583.74 0,322.38 261.36,583.74 583.739,583.74 322.381,0 583.741,-261.36 583.741,-583.74 0,-322.38 -261.36,-583.74 -583.741,-583.74" + inkscape:connector-curvature="0" /> + </g> + </g> + <g + id="g3347-6-8-3-7-64" + transform="matrix(0.125,0,0,-0.125,124.46742,882.67914)" + style="fill:url(#linearGradient10695-5);fill-opacity:1" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <g + clip-path="url(#clipPath3351-4-7-3-5-57)" + id="g3349-5-5-4-7-98" + style="fill:url(#linearGradient10693-2);fill-opacity:1"> + <path + id="path3361-0-8-2-9-7" + style="fill:url(#linearGradient4510-4);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 757.242,2926.25 -110.687,-189.11 110.656,-190.89 219.437,0 111.622,189.1 -111.59,190.9 -219.438,0" + inkscape:connector-curvature="0" /> + </g> + </g> + <path + id="path3363-6-9-0-1-3" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 206.73253,540.54045 13.106,-22.3925 25.99649,0 13.21487,22.6087 -13.21487,22.39129 -25.99649,0 -13.106,-22.60749 z m 40.53761,-24.8925 -28.86524,0 -0.72412,1.2375 -13.106,22.3925 -0.73575,1.2563 0.73087,1.26 13.106,22.60739 0.72263,1.2464 28.86374,0 0.72512,-1.2289 13.215,-22.39119 0.74625,-1.265 -0.74,-1.2675 -13.21537,-22.6088 -0.72313,-1.2387" + inkscape:connector-curvature="0" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523" /> + <g + id="g3365-0-4-1-9-8" + transform="matrix(0.125,0,0,-0.125,124.46742,882.67914)" + style="fill:url(#linearGradient10691-2);fill-opacity:1" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <g + clip-path="url(#clipPath3369-1-5-6-1-49)" + id="g3367-2-4-2-8-6" + style="fill:url(#linearGradient10689-9);fill-opacity:1"> + <path + id="path3379-4-6-7-6-2" + style="fill:url(#linearGradient4498-3);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 1131.64,3128.5 -104.95,-181.12 116.38,-200.42 208.05,0.94 112.02,191.63 -112.08,188.97 -219.42,0" + inkscape:connector-curvature="0" /> + </g> + </g> + <path + id="path3381-6-8-0-0-8" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 254.24864,514.25665 12.3925,-21.3899 25.99625,0 13.27125,22.3762 -13.27125,22.7025 -24.56875,0.11 -13.82,-23.7988 z m 39.8125,-23.8899 -28.86125,0 -0.7225,1.2462 -12.3925,21.39 -0.72625,1.255 0.7275,1.2537 13.82,23.7988 0.7275,1.2513 1.44625,-0.01 24.56875,-0.11 1.4275,-0.01 0.72,-1.2325 13.27125,-22.7025 0.7425,-1.27 -0.75125,-1.2663 -13.27125,-22.3762 -0.72625,-1.225" + inkscape:connector-curvature="0" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523" /> + <g + id="g3383-5-5-2-2-0" + transform="matrix(0.125,0,0,-0.125,124.46742,882.67914)" + style="fill:url(#linearGradient10687-9);fill-opacity:1" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <g + clip-path="url(#clipPath3387-3-6-4-2-3)" + id="g3385-0-6-4-8-9" + style="fill:url(#linearGradient10685-44);fill-opacity:1"> + <path + id="path3397-9-6-1-6-8" + style="fill:url(#linearGradient4492-0);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 862.109,3289.75 -109.086,-190.45 69.122,-124.42 164.511,-0.47 c 0,0 111.044,188.28 116.564,197.63 7.66,0 43.03,0 43.03,0 l -67.03,117.71 -217.111,0" + inkscape:connector-curvature="0" /> + </g> + </g> + <path + id="path3399-6-7-3-2-04" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 220.0304,495.27665 12.92424,-22.5662 25.68775,0 6.95625,12.2138 -3.94375,0 -14.56837,24.7025 -19.11525,-0.055 -7.94087,-14.295 z m 40.06574,-25.0662 -28.59012,0 -0.71975,1.2575 -12.92537,22.5663 -0.70112,1.2237 0.68512,1.2325 7.94137,14.295 0.71087,1.2825 1.46638,0 19.11525,0.055 1.43212,0 0.729,-1.2338 13.84375,-23.4724 6.81625,0 -2.12875,-3.7375 -6.95625,-12.2138 -0.71875,-1.2625" + inkscape:connector-curvature="0" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523" /> + <g + transform="matrix(1.25,0,0,-1.25,117.405,895.69964)" + id="g3465-0-9" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <text + id="text3467-9-6" + transform="matrix(1,0,-0.17627963,-1,0,0)" + x="116.98372" + y="-267.77499" + style="font-size:11.81779194px"> + <tspan + id="tspan3469-0-8" + sodipodi:role="line" + style="font-size:46.39999771px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark" + x="116.98372" + y="-267.77499">ATOMIC</tspan> + </text> + <text + id="text3471-0-2" + transform="matrix(0.99235617,0,-0.17763746,-1.0077027,0,0)" + style="font-size:38.40000153px" + x="112.74373" + y="-306.75479"> + <tspan + id="tspan3473-6-8" + sodipodi:role="line" + style="font-size:38.40000153px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark" + x="112.74373" + y="-306.75479">boost</tspan> + </text> + </g> + <path + sodipodi:type="arc" + style="fill:#0000a7;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path4821-47" + sodipodi:cx="160.35715" + sodipodi:cy="240.93361" + sodipodi:rx="10.114144" + sodipodi:ry="10.114144" + d="m 170.47129,240.93361 a 10.114144,10.114144 0 1 1 -20.22829,0 10.114144,10.114144 0 1 1 20.22829,0 z" + transform="translate(73.021973,299.26676)" /> + <path + transform="matrix(0.74292732,0,0,0.74292732,160.9833,334.95876)" + sodipodi:type="arc" + style="fill:#00b000;fill-opacity:1;stroke:#ffffff;stroke-width:2.69205332;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path4821-4-9" + sodipodi:cx="160.35715" + sodipodi:cy="240.93361" + sodipodi:rx="10.114144" + sodipodi:ry="10.114144" + d="m 170.47129,240.93361 a 10.114144,10.114144 0 1 1 -20.22829,0 10.114144,10.114144 0 1 1 20.22829,0 z" /> + <path + transform="matrix(0.51798873,0,0,0.51798873,159.28596,366.74327)" + sodipodi:type="arc" + style="fill:#cb0000;fill-opacity:1;stroke:#ffffff;stroke-width:3.8610878;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path4821-4-8-4" + sodipodi:cx="160.35715" + sodipodi:cy="240.93361" + sodipodi:rx="10.114144" + sodipodi:ry="10.114144" + d="m 170.47129,240.93361 a 10.114144,10.114144 0 1 1 -20.22829,0 10.114144,10.114144 0 1 1 20.22829,0 z" /> + <path + style="fill:none;stroke:#808080;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 250.05288,487.74985 c 12.11436,-0.8226 21.99257,5.106 28.337,15.9431" + id="path16018" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 279.75705,526.03685 c -5.64547,24.9935 -31.79301,20.1257 -32.06907,20.0828" + id="path16020" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 233.21476,494.63695 c -16.70632,11.7511 -8.41283,33.4381 -8.77494,33.2356" + id="path16022" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <g + id="g3319-1-2-5-1-8-7" + transform="matrix(0.10419818,0,0,-0.10419818,147.29097,965.23744)" + style="fill:url(#radialGradient10699-4-4);fill-opacity:1" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <g + clip-path="url(#clipPath3323-7-2-4-5-2-6)" + id="g3321-9-2-7-4-14-6" + style="fill:url(#radialGradient3192);fill-opacity:1"> + <path + id="path3335-8-7-3-8-7-1" + style="fill:url(#radialGradient4516-6-5);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 997.469,2312.51 c -322.379,0 -583.739,261.36 -583.739,583.74 0,322.38 261.36,583.74 583.739,583.74 322.381,0 583.741,-261.36 583.741,-583.74 0,-322.38 -261.36,-583.74 -583.741,-583.74" + inkscape:connector-curvature="0" /> + </g> + </g> + <g + id="g3347-6-8-3-7-64-8" + transform="matrix(0.125,0,0,-0.125,122.26447,1028.0561)" + style="fill:url(#linearGradient10695-5-7);fill-opacity:1" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <g + clip-path="url(#clipPath3351-4-7-3-5-57-7)" + id="g3349-5-5-4-7-98-9" + style="fill:url(#linearGradient10693-2-2);fill-opacity:1"> + <path + id="path3361-0-8-2-9-7-2" + style="fill:url(#linearGradient4510-4-1);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 757.242,2926.25 -110.687,-189.11 110.656,-190.89 219.437,0 111.622,189.1 -111.59,190.9 -219.438,0" + inkscape:connector-curvature="0" /> + </g> + </g> + <path + id="path3363-6-9-0-1-3-7" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 204.52958,685.91745 13.106,-22.3925 25.99649,0 13.21487,22.6087 -13.21487,22.39129 -25.99649,0 -13.106,-22.60749 z m 40.53761,-24.8925 -28.86524,0 -0.72412,1.2375 -13.106,22.3925 -0.73575,1.2563 0.73087,1.26 13.106,22.60739 0.72263,1.2464 28.86374,0 0.72512,-1.2289 13.215,-22.39119 0.74625,-1.265 -0.74,-1.2675 -13.21537,-22.6088 -0.72313,-1.2387" + inkscape:connector-curvature="0" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523" /> + <g + id="g3365-0-4-1-9-8-9" + transform="matrix(0.125,0,0,-0.125,122.26447,1028.0561)" + style="fill:url(#linearGradient10691-2-2);fill-opacity:1" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <g + clip-path="url(#clipPath3369-1-5-6-1-49-5)" + id="g3367-2-4-2-8-6-5" + style="fill:url(#linearGradient10689-9-4);fill-opacity:1"> + <path + id="path3379-4-6-7-6-2-4" + style="fill:url(#linearGradient4498-3-1);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 1131.64,3128.5 -104.95,-181.12 116.38,-200.42 208.05,0.94 112.02,191.63 -112.08,188.97 -219.42,0" + inkscape:connector-curvature="0" /> + </g> + </g> + <path + id="path3381-6-8-0-0-8-3" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 252.04569,659.63365 12.3925,-21.3899 25.99625,0 13.27125,22.3762 -13.27125,22.7025 -24.56875,0.11 -13.82,-23.7988 z m 39.8125,-23.8899 -28.86125,0 -0.7225,1.2462 -12.3925,21.39 -0.72625,1.255 0.7275,1.2537 13.82,23.7988 0.7275,1.2513 1.44625,-0.01 24.56875,-0.11 1.4275,-0.01 0.72,-1.2325 13.27125,-22.7025 0.7425,-1.27 -0.75125,-1.2663 -13.27125,-22.3762 -0.72625,-1.225" + inkscape:connector-curvature="0" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523" /> + <g + id="g3383-5-5-2-2-0-1" + transform="matrix(0.125,0,0,-0.125,122.26447,1028.0561)" + style="fill:url(#linearGradient10687-9-1);fill-opacity:1" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <g + clip-path="url(#clipPath3387-3-6-4-2-3-4)" + id="g3385-0-6-4-8-9-2" + style="fill:url(#linearGradient10685-44-9);fill-opacity:1"> + <path + id="path3397-9-6-1-6-8-3" + style="fill:url(#linearGradient4492-0-8);fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 862.109,3289.75 -109.086,-190.45 69.122,-124.42 164.511,-0.47 c 0,0 111.044,188.28 116.564,197.63 7.66,0 43.03,0 43.03,0 l -67.03,117.71 -217.111,0" + inkscape:connector-curvature="0" /> + </g> + </g> + <path + id="path3399-6-7-3-2-04-3" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m 217.82745,640.65365 12.92424,-22.5662 25.68775,0 6.95625,12.2138 -3.94375,0 -14.56837,24.7025 -19.11525,-0.055 -7.94087,-14.295 z m 40.06574,-25.0662 -28.59012,0 -0.71975,1.2575 -12.92537,22.5663 -0.70112,1.2237 0.68512,1.2325 7.94137,14.295 0.71087,1.2825 1.46638,0 19.11525,0.055 1.43212,0 0.729,-1.2338 13.84375,-23.4724 6.81625,0 -2.12875,-3.7375 -6.95625,-12.2138 -0.71875,-1.2625" + inkscape:connector-curvature="0" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523" /> + <g + transform="matrix(1.25,0,0,-1.25,115.20205,1041.0766)" + id="g3465-0-9-4" + inkscape:export-filename="C:\Users\Adam\Desktop\bg_logo1.png" + inkscape:export-xdpi="63.625523" + inkscape:export-ydpi="63.625523"> + <text + id="text3467-9-6-1" + transform="matrix(1,0,-0.17627963,-1,0,0)" + x="116.98372" + y="-267.77499" + style="font-size:11.81779194px"> + <tspan + id="tspan3469-0-8-1" + sodipodi:role="line" + style="font-size:46.39999771px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark" + x="116.98372" + y="-267.77499">Atomic</tspan> + </text> + <text + id="text3471-0-2-3" + transform="matrix(0.99235617,0,-0.17763746,-1.0077027,0,0)" + style="font-size:38.40000153px" + x="112.74373" + y="-306.75479"> + <tspan + id="tspan3473-6-8-8" + sodipodi:role="line" + style="font-size:38.40000153px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#49608a;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:Denmark;-inkscape-font-specification:Denmark" + x="112.74373" + y="-306.75479">Boost</tspan> + </text> + </g> + <path + sodipodi:type="arc" + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path4821-47-7" + sodipodi:cx="160.35715" + sodipodi:cy="240.93361" + sodipodi:rx="10.114144" + sodipodi:ry="10.114144" + d="m 170.47129,240.93361 a 10.114144,10.114144 0 1 1 -20.22829,0 10.114144,10.114144 0 1 1 20.22829,0 z" + transform="matrix(0.53649776,0,0,0.53649776,136.31572,567.15057)" /> + <path + transform="matrix(0.45553914,0,0,0.45553914,171.71781,574.06648)" + sodipodi:type="arc" + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.69205331999999990;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path4821-4-9-4" + sodipodi:cx="160.35715" + sodipodi:cy="240.93361" + sodipodi:rx="10.114144" + sodipodi:ry="10.114144" + d="m 170.47129,240.93361 a 10.114144,10.114144 0 1 1 -20.22829,0 10.114144,10.114144 0 1 1 20.22829,0 z" /> + <path + transform="matrix(0.33234221,0,0,0.33234221,173.35638,592.9985)" + sodipodi:type="arc" + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:3.86108780000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path4821-4-8-4-2" + sodipodi:cx="160.35715" + sodipodi:cy="240.93361" + sodipodi:rx="10.114144" + sodipodi:ry="10.114144" + d="m 170.47129,240.93361 a 10.114144,10.114144 0 1 1 -20.22829,0 10.114144,10.114144 0 1 1 20.22829,0 z" /> + <path + style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 231.48167,671.25081 c 5.6438,-0.15431 8.79799,1.45226 12.0778,6.25882" + id="path16018-7" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 244.5941,690.50066 c -4.06373,10.90468 -15.39442,8.6554 -15.38328,8.74968" + id="path16020-7" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 221.63678,674.9333 c -7.09591,5.63691 -3.2412,15.66119 -3.57792,15.56405" + id="path16022-9" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + </g> +</svg> diff --git a/3rdParty/Boost/src/libs/atomic/doc/platform.qbk b/3rdParty/Boost/src/libs/atomic/doc/platform.qbk new file mode 100644 index 0000000..6b9a9ec --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/doc/platform.qbk @@ -0,0 +1,312 @@ +[/ + / Copyright (c) 2009 Helge Bahmann + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:template_organization Organization of class template layers] + +The implementation uses multiple layers of template classes that +inherit from the next lower level each and refine or adapt the respective +underlying class: + +* [^boost::atomic<T>] is the topmost-level, providing + the external interface. Implementation-wise, it does not add anything + (except for hiding copy constructor and assignment operator). + +* [^boost::detail::atomic::internal_atomic&<T,S=sizeof(T),I=is_integral_type<T> >]: + This layer is mainly responsible for providing the overloaded operators + mapping to API member functions (e.g. [^+=] to [^fetch_add]). + The defaulted template parameter [^I] allows + to expose the correct API functions (via partial template + specialization): For non-integral types, it only + publishes the various [^exchange] functions + as well as load and store, for integral types it + additionally exports arithmetic and logic operations. + [br] + Depending on whether the given type is integral, it + inherits from either [^boost::detail::atomic::platform_atomic<T,S=sizeof(T)>] + or [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>]. + There is however some special-casing: for non-integral types + of size 1, 2, 4 or 8, it will coerce the datatype into an integer representation + and delegate to [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>] + -- the rationale is that platform implementors only need to provide + integer-type operations. + +* [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>] + must provide the full set of operations for an integral type T + (i.e. [^load], [^store], [^exchange], + [^compare_exchange_weak], [^compare_exchange_strong], + [^fetch_add], [^fetch_sub], [^fetch_and], + [^fetch_or], [^fetch_xor], [^is_lock_free]). + The default implementation uses locking to emulate atomic operations, so + this is the level at which implementors should provide template specializations + to add support for platform-specific atomic operations. + [br] + The two separate template parameters allow separate specialization + on size and type (which, with fixed size, cannot + specify more than signedness/unsignedness). The rationale is that + most platform-specific atomic operations usually depend only on the + operand size, so that common implementations for signed/unsigned + types are possible. Signedness allows to properly to choose sign-extending + instructions for the [^load] operation, avoiding later + conversion. The expectation is that in most implementations this will + be a normal assignment in C, possibly accompanied by memory + fences, so that the compiler can automatically choose the correct + instruction. + +* At the lowest level, [^boost::detail::atomic::platform_atomic<T,S=sizeof(T)>] + provides the most basic atomic operations ([^load], [^store], + [^exchange], [^compare_exchange_weak], + [^compare_exchange_strong]) for arbitrarily generic data types. + The default implementation uses locking as a fallback mechanism. + Implementors generally do not have to specialize at this level + (since these will not be used for the common integral type sizes + of 1, 2, 4 and 8 bytes), but if s/he can if s/he so wishes to + provide truly atomic operations for "odd" data type sizes. + Some amount of care must be taken as the "raw" data type + passed in from the user through [^boost::atomic<T>] + is visible here -- it thus needs to be type-punned or otherwise + manipulated byte-by-byte to avoid using overloaded assignment, + comparison operators and copy constructors. + +[endsect] + + +[section:platform_atomic_implementation Implementing platform-specific atomic operations] + +In principle implementors are responsible for providing the +full range of named member functions of an atomic object +(i.e. [^load], [^store], [^exchange], +[^compare_exchange_weak], [^compare_exchange_strong], +[^fetch_add], [^fetch_sub], [^fetch_and], +[^fetch_or], [^fetch_xor], [^is_lock_free]). +These must be implemented as partial template specializations for +[^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>]: + +[c++] + + template<typename T> + class platform_atomic_integral<T, 4> + { + public: + explicit platform_atomic_integral(T v) : i(v) {} + platform_atomic_integral(void) {} + + T load(memory_order order=memory_order_seq_cst) const volatile + { + // platform-specific code + } + void store(T v, memory_order order=memory_order_seq_cst) volatile + { + // platform-specific code + } + + private: + volatile T i; + }; + +As noted above, it will usually suffice to specialize on the second +template argument, indicating the size of the data type in bytes. + +[section:automatic_buildup Templates for automatic build-up] + +Often only a portion of the required operations can be +usefully mapped to machine instructions. Several helper template +classes are provided that can automatically synthesize missing methods to +complete an implementation. + +At the minimum, an implementor must provide the +[^load], [^store], +[^compare_exchange_weak] and +[^is_lock_free] methods: + +[c++] + + template<typename T> + class my_atomic_32 { + public: + my_atomic_32() {} + my_atomic_32(T initial_value) : value(initial_value) {} + + T load(memory_order order=memory_order_seq_cst) volatile const + { + // platform-specific code + } + void store(T new_value, memory_order order=memory_order_seq_cst) volatile + { + // platform-specific code + } + bool compare_exchange_weak(T &expected, T desired, + memory_order success_order, + memory_order_failure_order) volatile + { + // platform-specific code + } + bool is_lock_free() const volatile {return true;} + protected: + // typedef is required for classes inheriting from this + typedef T integral_type; + private: + T value; + }; + +The template [^boost::detail::atomic::build_atomic_from_minimal] +can then take care of the rest: + +[c++] + + template<typename T> + class platform_atomic_integral<T, 4> + : public boost::detail::atomic::build_atomic_from_minimal<my_atomic_32<T> > + { + public: + typedef build_atomic_from_minimal<my_atomic_32<T> > super; + + explicit platform_atomic_integral(T v) : super(v) {} + platform_atomic_integral(void) {} + }; + +There are several helper classes to assist in building "complete" +atomic implementations from different starting points: + +* [^build_atomic_from_minimal] requires + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + +* [^build_atomic_from_exchange] requires + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + * [^compare_exchange_strong] (4-operand version) + * [^exchange] + +* [^build_atomic_from_add] requires + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + * [^compare_exchange_strong] (4-operand version) + * [^exchange] + * [^fetch_add] + +* [^build_atomic_from_typical] (<I>supported on gcc only</I>) requires + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + * [^compare_exchange_strong] (4-operand version) + * [^exchange] + * [^fetch_add_var] (protected method) + * [^fetch_inc] (protected method) + * [^fetch_dec] (protected method) + + This will generate a [^fetch_add] method + that calls [^fetch_inc]/[^fetch_dec] + when the given parameter is a compile-time constant + equal to +1 or -1 respectively, and [^fetch_add_var] + in all other cases. This provides a mechanism for + optimizing the extremely common case of an atomic + variable being used as a counter. + + The prototypes for these methods to be implemented is: + [c++] + + template<typename T> + class my_atomic { + public: + T fetch_inc(memory_order order) volatile; + T fetch_dec(memory_order order) volatile; + T fetch_add_var(T counter, memory_order order) volatile; + }; + +These helper templates are defined in [^boost/atomic/detail/builder.hpp]. + +[endsect] + +[section:automatic_buildup_small Build sub-word-sized atomic data types] + +There is one other helper template that can build sub-word-sized +atomic data types even though the underlying architecture allows +only word-sized atomic operations: + +[c++] + + template<typename T> + class platform_atomic_integral<T, 1> : + public build_atomic_from_larger_type<my_atomic_32<uint32_t>, T> + { + public: + typedef build_atomic_from_larger_type<my_atomic_32<uint32_t>, T> super; + + explicit platform_atomic_integral(T v) : super(v) {} + platform_atomic_integral(void) {} + }; + +The above would create an atomic data type of 1 byte size, and +use masking and shifts to map it to 32-bit atomic operations. +The base type must implement [^load], [^store] +and [^compare_exchange_weak] for this to work. + +[endsect] + +[section:other_sizes Atomic data types for unusual object sizes] + +In unusual circumstances, an implementor may also opt to specialize +[^public boost::detail::atomic::platform_atomic<T,S=sizeof(T)>] +to provide support for atomic objects not fitting an integral size. +If you do that, keep the following things in mind: + +* There is no reason to ever do this for object sizes + of 1, 2, 4 and 8 +* Only the following methods need to be implemented: + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + * [^compare_exchange_strong] (4-operand version) + * [^exchange] + +The type of the data to be stored in the atomic +variable (template parameter [^T]) +is exposed to this class, and the type may have +overloaded assignment and comparison operators -- +using these overloaded operators however will result +in an error. The implementor is responsible for +accessing the objects in a way that does not +invoke either of these operators (using e.g. +[^memcpy] or type-casts). + +[endsect] + +[endsect] + +[section:platform_atomic_fences Fences] + +Platform implementors need to provide a function performing +the action required for [funcref boost::atomic_thread_fence atomic_thread_fence] +(the fallback implementation will just perform an atomic operation +on an integer object). This is achieved by specializing the +[^boost::detail::atomic::platform_atomic_thread_fence] template +function in the following way: + +[c++] + + template<> + void platform_atomic_thread_fence(memory_order order) + { + // platform-specific code here + } + +[endsect] + +[section:platform_atomic_puttogether Putting it altogether] + +The template specializations should be put into a header file +in the [^boost/atomic/detail] directory, preferably +specifying supported compiler and architecture in its name. + +The file [^boost/atomic/detail/platform.hpp] must +subsequently be modified to conditionally include the new +header. + +[endsect] diff --git a/3rdParty/Boost/src/libs/atomic/index.html b/3rdParty/Boost/src/libs/atomic/index.html new file mode 100644 index 0000000..62a6c59 --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/index.html @@ -0,0 +1,13 @@ +<html> +<head> +<meta http-equiv="refresh" content="0; URL=../../doc/html/atomic.html"> +</head> +<body> +Automatic redirection failed, please go to +<a href="../../doc/html/atomic.html">../../doc/html/atomic.html</a> <hr> +<p>© Copyright Beman Dawes, 2001</p> +<p>Distributed under the Boost Software License, Version 1.0. (See accompanying +file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy +at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p> +</body> +</html> diff --git a/3rdParty/Boost/src/libs/atomic/src/lockpool.cpp b/3rdParty/Boost/src/libs/atomic/src/lockpool.cpp new file mode 100644 index 0000000..13269a1 --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/src/lockpool.cpp @@ -0,0 +1,144 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2011 Helge Bahmann + * Copyright (c) 2013-2014 Andrey Semashev + */ +/*! + * \file lockpool.cpp + * + * This file contains implementation of the lockpool used to emulate atomic ops. + */ + +#include <cstddef> +#include <boost/config.hpp> +#include <boost/assert.hpp> +#include <boost/memory_order.hpp> +#include <boost/atomic/capabilities.hpp> + +#if BOOST_ATOMIC_FLAG_LOCK_FREE == 2 +#include <boost/atomic/detail/operations_lockfree.hpp> +#elif !defined(BOOST_HAS_PTHREADS) +#error Boost.Atomic: Unsupported target platform, POSIX threads are required when native atomic operations are not available +#else +#include <pthread.h> +#define BOOST_ATOMIC_USE_PTHREAD +#endif + +#include <boost/atomic/detail/lockpool.hpp> +#include <boost/atomic/detail/pause.hpp> + +namespace boost { +namespace atomics { +namespace detail { + +namespace { + +// This seems to be the maximum across all modern CPUs +// NOTE: This constant is made as a macro because some compilers (gcc 4.4 for one) don't allow enums or namespace scope constants in alignment attributes +#define BOOST_ATOMIC_CACHE_LINE_SIZE 64 + +template< unsigned int N > +struct padding +{ + char data[N]; +}; +template< > +struct padding< 0 > +{ +}; + +struct BOOST_ALIGNMENT(BOOST_ATOMIC_CACHE_LINE_SIZE) padded_lock +{ +#if defined(BOOST_ATOMIC_USE_PTHREAD) + typedef pthread_mutex_t lock_type; +#else + typedef atomics::detail::operations< 1u, false > operations; + typedef operations::storage_type lock_type; +#endif + + lock_type lock; + // The additional padding is needed to avoid false sharing between locks + enum { padding_size = (sizeof(lock_type) <= BOOST_ATOMIC_CACHE_LINE_SIZE ? + (BOOST_ATOMIC_CACHE_LINE_SIZE - sizeof(lock_type)) : + (BOOST_ATOMIC_CACHE_LINE_SIZE - sizeof(lock_type) % BOOST_ATOMIC_CACHE_LINE_SIZE)) }; + padding< padding_size > pad; +}; + +static padded_lock g_lock_pool[41] +#if defined(BOOST_ATOMIC_USE_PTHREAD) += +{ + PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER +} +#endif +; + +} // namespace + + +#if !defined(BOOST_ATOMIC_USE_PTHREAD) + +// NOTE: This function must NOT be inline. Otherwise MSVC 9 will sometimes generate broken code for modulus operation which result in crashes. +BOOST_ATOMIC_DECL lockpool::scoped_lock::scoped_lock(const volatile void* addr) BOOST_NOEXCEPT : + m_lock(&g_lock_pool[reinterpret_cast< std::size_t >(addr) % (sizeof(g_lock_pool) / sizeof(*g_lock_pool))].lock) +{ + while (padded_lock::operations::test_and_set(*static_cast< padded_lock::lock_type* >(m_lock), memory_order_acquire)) + { + atomics::detail::pause(); + } +} + +BOOST_ATOMIC_DECL lockpool::scoped_lock::~scoped_lock() BOOST_NOEXCEPT +{ + padded_lock::operations::clear(*static_cast< padded_lock::lock_type* >(m_lock), memory_order_release); +} + +BOOST_ATOMIC_DECL void signal_fence() BOOST_NOEXCEPT; + +#else // !defined(BOOST_ATOMIC_USE_PTHREAD) + +BOOST_ATOMIC_DECL lockpool::scoped_lock::scoped_lock(const volatile void* addr) BOOST_NOEXCEPT : + m_lock(&g_lock_pool[reinterpret_cast< std::size_t >(addr) % (sizeof(g_lock_pool) / sizeof(*g_lock_pool))].lock) +{ + BOOST_VERIFY(pthread_mutex_lock(static_cast< pthread_mutex_t* >(m_lock)) == 0); +} + +BOOST_ATOMIC_DECL lockpool::scoped_lock::~scoped_lock() BOOST_NOEXCEPT +{ + BOOST_VERIFY(pthread_mutex_unlock(static_cast< pthread_mutex_t* >(m_lock)) == 0); +} + +#endif // !defined(BOOST_ATOMIC_USE_PTHREAD) + +BOOST_ATOMIC_DECL void lockpool::thread_fence() BOOST_NOEXCEPT +{ +#if BOOST_ATOMIC_THREAD_FENCE > 0 + atomics::detail::thread_fence(memory_order_seq_cst); +#else + // Emulate full fence by locking/unlocking a mutex + scoped_lock lock(0); +#endif +} + +BOOST_ATOMIC_DECL void lockpool::signal_fence() BOOST_NOEXCEPT +{ + // This function is intentionally non-inline, even if empty. This forces the compiler to treat its call as a compiler barrier. +#if BOOST_ATOMIC_SIGNAL_FENCE > 0 + atomics::detail::signal_fence(memory_order_seq_cst); +#endif +} + +} // namespace detail +} // namespace atomics +} // namespace boost diff --git a/3rdParty/Boost/src/libs/date_time/src/gregorian/date_generators.cpp b/3rdParty/Boost/src/libs/date_time/src/gregorian/date_generators.cpp index 4669065..32a58c1 100644 --- a/3rdParty/Boost/src/libs/date_time/src/gregorian/date_generators.cpp +++ b/3rdParty/Boost/src/libs/date_time/src/gregorian/date_generators.cpp @@ -3,7 +3,7 @@ * Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) * Author: Jeff Garland, Bart Garst - * $Date: 2012-09-24 11:08:16 -0700 (Mon, 24 Sep 2012) $ + * $Date$ */ diff --git a/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_month.cpp b/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_month.cpp index cce04f0..8232378 100644 --- a/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_month.cpp +++ b/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_month.cpp @@ -3,7 +3,7 @@ * Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) * Author: Jeff Garland, Bart Garst - * $Date: 2012-09-30 16:25:22 -0700 (Sun, 30 Sep 2012) $ + * $Date$ */ diff --git a/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_names.hpp b/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_names.hpp index 44aa8b8..f20b320 100644 --- a/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_names.hpp +++ b/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_names.hpp @@ -3,7 +3,7 @@ * Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) * Author: Jeff Garland, Bart Garst - * $Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $ + * $Date$ */ diff --git a/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_weekday.cpp b/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_weekday.cpp index fe83c15..ffdc96f 100644 --- a/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_weekday.cpp +++ b/3rdParty/Boost/src/libs/date_time/src/gregorian/greg_weekday.cpp @@ -3,7 +3,7 @@ * Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) * Author: Jeff Garland, Bart Garst - * $Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $ + * $Date$ */ diff --git a/3rdParty/Boost/src/libs/date_time/src/gregorian/gregorian_types.cpp b/3rdParty/Boost/src/libs/date_time/src/gregorian/gregorian_types.cpp index 341731f..7dd7f22 100644 --- a/3rdParty/Boost/src/libs/date_time/src/gregorian/gregorian_types.cpp +++ b/3rdParty/Boost/src/libs/date_time/src/gregorian/gregorian_types.cpp @@ -3,7 +3,7 @@ * Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) * Author: Jeff Garland - * $Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $ + * $Date$ */ diff --git a/3rdParty/Boost/src/libs/date_time/src/posix_time/posix_time_types.cpp b/3rdParty/Boost/src/libs/date_time/src/posix_time/posix_time_types.cpp index 4916d36..4395301 100644 --- a/3rdParty/Boost/src/libs/date_time/src/posix_time/posix_time_types.cpp +++ b/3rdParty/Boost/src/libs/date_time/src/posix_time/posix_time_types.cpp @@ -4,7 +4,7 @@ * Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) * Author: Jeff Garland - * $Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $ + * $Date$ */ diff --git a/3rdParty/Boost/src/libs/filesystem/src/codecvt_error_category.cpp b/3rdParty/Boost/src/libs/filesystem/src/codecvt_error_category.cpp index 245c3f3..165c6ea 100644 --- a/3rdParty/Boost/src/libs/filesystem/src/codecvt_error_category.cpp +++ b/3rdParty/Boost/src/libs/filesystem/src/codecvt_error_category.cpp @@ -35,11 +35,11 @@ namespace { public: codecvt_error_cat(){} - const char* name() const; + const char* name() const BOOST_SYSTEM_NOEXCEPT; std::string message(int ev) const; }; - const char* codecvt_error_cat::name() const + const char* codecvt_error_cat::name() const BOOST_SYSTEM_NOEXCEPT { return "codecvt"; } diff --git a/3rdParty/Boost/src/libs/filesystem/src/operations.cpp b/3rdParty/Boost/src/libs/filesystem/src/operations.cpp index d066e40..09b8853 100644 --- a/3rdParty/Boost/src/libs/filesystem/src/operations.cpp +++ b/3rdParty/Boost/src/libs/filesystem/src/operations.cpp @@ -73,17 +73,15 @@ using std::wstring; const fs::path dot_dot_path(".."); # include <sys/types.h> # include <sys/stat.h> -# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(ANDROID) +# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) # include <sys/statvfs.h> # define BOOST_STATVFS statvfs # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize -# elif defined (ANDROID) -# include <sys/vfs.h> -# define BOOST_STATVFS statfs -# define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>(vfs.f_bsize) # else # ifdef __OpenBSD__ # include <sys/param.h> +# elif defined(__ANDROID__) +# include <sys/vfs.h> # endif # include <sys/mount.h> # define BOOST_STATVFS statfs @@ -777,6 +775,7 @@ namespace detail path canonical(const path& p, const path& base, system::error_code* ec) { path source (p.is_absolute() ? p : absolute(p, base)); + path root(source.root_path()); path result; system::error_code local_ec; @@ -811,7 +810,8 @@ namespace detail continue; if (*itr == dot_dot_path) { - result.remove_filename(); + if (result != root) + result.remove_filename(); continue; } @@ -931,6 +931,7 @@ namespace detail } path parent = p.parent_path(); + BOOST_ASSERT_MSG(parent != p, "internal error: p == p.parent_path()"); if (!parent.empty()) { // determine if the parent exists @@ -1411,7 +1412,7 @@ namespace detail // - See the fchmodat() Linux man page: // "http://man7.org/linux/man-pages/man2/fchmodat.2.html" # if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW) \ - && !(defined(__SUNPRO_CC) || defined(sun)) \ + && !(defined(__SUNPRO_CC) || defined(__sun) || defined(sun)) \ && !(defined(linux) || defined(__linux) || defined(__linux__)) if (::fchmodat(AT_FDCWD, p.c_str(), mode_cast(prms), !(prms & symlink_perms) ? 0 : AT_SYMLINK_NOFOLLOW)) diff --git a/3rdParty/Boost/src/libs/filesystem/src/path.cpp b/3rdParty/Boost/src/libs/filesystem/src/path.cpp index c740dec..a3b3710 100644 --- a/3rdParty/Boost/src/libs/filesystem/src/path.cpp +++ b/3rdParty/Boost/src/libs/filesystem/src/path.cpp @@ -27,6 +27,10 @@ #include <boost/scoped_array.hpp> #include <boost/system/error_code.hpp> #include <boost/assert.hpp> +//#include <boost/detail/lightweight_mutex.hpp> +// fails on VC++ static builds because the runtime does not permit use of locks in +// staticly initialized code, and VC++ 2010 (and probably other versions) statically +// initializes some instances of class path. #include <algorithm> #include <cstddef> #include <cstring> @@ -35,7 +39,7 @@ #ifdef BOOST_WINDOWS_API # include "windows_file_codecvt.hpp" # include <windows.h> -#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__FreeBSD__) # include <boost/filesystem/detail/utf8_codecvt_facet.hpp> #endif @@ -98,7 +102,6 @@ namespace const char* const separators = "/"; const char* separator_string = "/"; const char* preferred_separator_string = "/"; - const char colon = ':'; const char dot = '.'; const fs::path dot_path("."); const fs::path dot_dot_path(".."); @@ -510,7 +513,7 @@ namespace size_type pos(str.find_last_of(separators, end_pos-1)); # ifdef BOOST_WINDOWS_API - if (pos == string_type::npos) + if (pos == string_type::npos && end_pos > 1) pos = str.find_last_of(colon, end_pos-2); # endif @@ -783,147 +786,103 @@ namespace filesystem } // namespace filesystem } // namespace boost -//--------------------------------------------------------------------------------------// -// // -// detail helpers // -// // -//--------------------------------------------------------------------------------------// - namespace { //------------------------------------------------------------------------------------// - // locale helpers // + // locale helpers // //------------------------------------------------------------------------------------// -#if defined(BOOST_WINDOWS_API) && defined(BOOST_FILESYSTEM_STATIC_LINK) + // Prior versions of these locale and codecvt implementations tried to take advantage + // of static initialization where possible, kept a local copy of the current codecvt + // facet (to avoid codecvt() having to call use_facet()), and was not multi-threading + // safe (again for efficiency). + // + // This was error prone, and required different implementation techniques depending + // on the compiler and also whether static or dynamic linking was used. Furthermore, + // users could not easily provide their multi-threading safe wrappers because the + // path interface requires the implementation itself to call codecvt() to obtain the + // default facet, and the initialization of the static within path_locale() could race. + // + // The code below is portable to all platforms, is much simpler, and hopefully will be + // much more robust. Timing tests (on Windows, using a Visual C++ release build) + // indicated the current code is roughly 9% slower than the previous code, and that + // seems a small price to pay for better code that is easier to use. + + //boost::detail::lightweight_mutex locale_mutex; inline std::locale default_locale() { +# if defined(BOOST_WINDOWS_API) std::locale global_loc = std::locale(); - std::locale loc(global_loc, new windows_file_codecvt); - return loc; + return std::locale(global_loc, new windows_file_codecvt); +# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__FreeBSD__) + // "All BSD system functions expect their string parameters to be in UTF-8 encoding + // and nothing else." See + // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html + // + // "The kernel will reject any filename that is not a valid UTF-8 string, and it will + // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS. + // The right way to deal with it would be to always convert the filename to UTF-8 + // before trying to open/create a file." See + // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html + // + // "How a file name looks at the API level depends on the API. Current Carbon APIs + // handle file names as an array of UTF-16 characters; POSIX ones handle them as an + // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk + // depends on the disk format; HFS+ uses UTF-16, but that's not important in most + // cases." See + // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html + // + // Many thanks to Peter Dimov for digging out the above references! + + std::locale global_loc = std::locale(); + return std::locale(global_loc, new boost::filesystem::detail::utf8_codecvt_facet); +# else // Other POSIX + // ISO C calls std::locale("") "the locale-specific native environment", and this + // locale is the default for many POSIX-based operating systems such as Linux. + return std::locale(""); +# endif } inline std::locale& path_locale() + // std::locale("") construction, needed on non-Apple POSIX systems, can throw + // (if environmental variables LC_MESSAGES or LANG are wrong, for example), so + // path_locale() provides lazy initialization via a local static to ensure that any + // exceptions occur after main() starts and so can be caught. Furthermore, + // path_locale() is only called if path::codecvt() or path::imbue() are themselves + // actually called, ensuring that an exception will only be thrown if std::locale("") + // is really needed. { static std::locale loc(default_locale()); return loc; } - - inline const path::codecvt_type*& codecvt_facet_ptr() - { - static const std::codecvt<wchar_t, char, std::mbstate_t>* - facet( - &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> > - (path_locale())); - return facet; - } - -#elif defined(BOOST_WINDOWS_API) && !defined(BOOST_FILESYSTEM_STATIC_LINK) - - std::locale path_locale(std::locale(), new windows_file_codecvt); - - const std::codecvt<wchar_t, char, std::mbstate_t>* - codecvt_facet_ptr(&std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> > - (path_locale)); - -#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) - - // "All BSD system functions expect their string parameters to be in UTF-8 encoding - // and nothing else." See - // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html - // - // "The kernel will reject any filename that is not a valid UTF-8 string, and it will - // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS. - // The right way to deal with it would be to always convert the filename to UTF-8 - // before trying to open/create a file." See - // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html - // - // "How a file name looks at the API level depends on the API. Current Carbon APIs - // handle file names as an array of UTF-16 characters; POSIX ones handle them as an - // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk - // depends on the disk format; HFS+ uses UTF-16, but that's not important in most - // cases." See - // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html - // - // Many thanks to Peter Dimov for digging out the above references! - - std::locale path_locale(std::locale(), - new boost::filesystem::detail::utf8_codecvt_facet); - - const std::codecvt<wchar_t, char, std::mbstate_t>* - codecvt_facet_ptr(&std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> > - (path_locale)); - -#else // Other POSIX - - // ISO C calls std::locale("") "the locale-specific native environment", and this - // locale is the default for many POSIX-based operating systems such as Linux. - - // std::locale("") construction can throw (if environmental variables LC_MESSAGES or - // or LANG are wrong, for example), so lazy initialization is used to ensure - // that exceptions occur after main() starts and so can be caught. - - std::locale path_locale; // initialized by path::codecvt() below - const std::codecvt<wchar_t, char, std::mbstate_t>* codecvt_facet_ptr; // ditto - -# endif - } // unnamed namespace //--------------------------------------------------------------------------------------// -// path::imbue implementation // +// path::codecvt() and path::imbue() implementation // //--------------------------------------------------------------------------------------// namespace boost { namespace filesystem { - -#if defined(BOOST_WINDOWS_API) && defined(BOOST_FILESYSTEM_STATIC_LINK) + // See comments above const path::codecvt_type& path::codecvt() { - BOOST_ASSERT_MSG(codecvt_facet_ptr(), "codecvt_facet_ptr() facet hasn't been properly initialized"); - return *codecvt_facet_ptr(); + BOOST_ASSERT_MSG(&path_locale(), "boost::filesystem::path locale initialization error"); +// boost::detail::lightweight_mutex::scoped_lock lock(locale_mutex); + return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale()); } - std::locale path::imbue(const std::locale & loc) + std::locale path::imbue(const std::locale& loc) { +// boost::detail::lightweight_mutex::scoped_lock lock(locale_mutex); std::locale temp(path_locale()); path_locale() = loc; - codecvt_facet_ptr() = - &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale()); - return temp; - } - -#else - - const path::codecvt_type& path::codecvt() - { -# if defined(BOOST_POSIX_API) && \ - !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) - // A local static initialized by calling path::imbue ensures that std::locale(""), - // which may throw, is called only if path_locale and condecvt_facet will actually - // be used. Thus misconfigured environmental variables will only cause an - // exception if a valid std::locale("") is actually needed. - static std::locale posix_lazy_initialization(path::imbue(std::locale(""))); -# endif - return *codecvt_facet_ptr; - } - - std::locale path::imbue(const std::locale& loc) - { - std::locale temp(path_locale); - path_locale = loc; - codecvt_facet_ptr = - &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale); return temp; } - -#endif - } // namespace filesystem } // namespace boost diff --git a/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp index cd9a5fe..d7910c2 100644 --- a/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp @@ -455,7 +455,7 @@ namespace boost { namespace program_options { namespace detail { // if they look like options if (opt.value.size() <= min_tokens) { - min_tokens -= static_cast<unsigned>(opt.value.size()); + min_tokens -= static_cast<unsigned>(opt.value.size()); } else { diff --git a/3rdParty/Boost/src/libs/program_options/src/options_description.cpp b/3rdParty/Boost/src/libs/program_options/src/options_description.cpp index 343bd30..9d51ce9 100644 --- a/3rdParty/Boost/src/libs/program_options/src/options_description.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/options_description.cpp @@ -604,12 +604,9 @@ namespace boost { namespace program_options { } } - void - options_description::print(std::ostream& os) const + unsigned + options_description::get_option_column_width() const { - if (!m_caption.empty()) - os << m_caption << ":\n"; - /* Find the maximum width of the option column */ unsigned width(23); unsigned i; // vc6 has broken for loop scoping @@ -620,6 +617,11 @@ namespace boost { namespace program_options { ss << " " << opt.format_name() << ' ' << opt.format_parameter(); width = (max)(width, static_cast<unsigned>(ss.str().size())); } + + /* Get width of groups as well*/ + for (unsigned j = 0; j < groups.size(); ++j) + width = max(width, groups[j]->get_option_column_width()); + /* this is the column were description should start, if first column is longer, we go to a new line */ const unsigned start_of_description_column = m_line_length - m_min_description_length; @@ -628,9 +630,20 @@ namespace boost { namespace program_options { /* add an additional space to improve readability */ ++width; - + return width; + } + + void + options_description::print(std::ostream& os, unsigned width) const + { + if (!m_caption.empty()) + os << m_caption << ":\n"; + + if (!width) + width = get_option_column_width(); + /* The options formatting style is stolen from Subversion. */ - for (i = 0; i < m_options.size(); ++i) + for (unsigned i = 0; i < m_options.size(); ++i) { if (belong_to_group[i]) continue; @@ -643,7 +656,8 @@ namespace boost { namespace program_options { } for (unsigned j = 0; j < groups.size(); ++j) { - os << "\n" << *groups[j]; + os << "\n"; + groups[j]->print(os, width); } } diff --git a/3rdParty/Boost/src/libs/regex/src/c_regex_traits.cpp b/3rdParty/Boost/src/libs/regex/src/c_regex_traits.cpp index 6701020..23ec324 100644 --- a/3rdParty/Boost/src/libs/regex/src/c_regex_traits.cpp +++ b/3rdParty/Boost/src/libs/regex/src/c_regex_traits.cpp @@ -54,6 +54,19 @@ c_regex_traits<char>::string_type BOOST_REGEX_CALL c_regex_traits<char>::transfo std::string src(p1, p2); while(s < (r = std::strxfrm(&*result.begin(), src.c_str(), s))) { +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::strxfrm, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if(r == INT_MAX) + { + result.erase(); + result.insert(result.begin(), static_cast<char>(0)); + return result; + } +#endif result.append(r - s + 3, ' '); s = result.size(); } diff --git a/3rdParty/Boost/src/libs/regex/src/posix_api.cpp b/3rdParty/Boost/src/libs/regex/src/posix_api.cpp index e59c19e..8a803b3 100644 --- a/3rdParty/Boost/src/libs/regex/src/posix_api.cpp +++ b/3rdParty/Boost/src/libs/regex/src/posix_api.cpp @@ -125,7 +125,7 @@ BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA* expression, const char #endif expression->re_magic = magic_value; static_cast<c_regex_type*>(expression->guts)->set_expression(ptr, p2, flags); - expression->re_nsub = static_cast<c_regex_type*>(expression->guts)->mark_count() - 1; + expression->re_nsub = static_cast<c_regex_type*>(expression->guts)->mark_count(); result = static_cast<c_regex_type*>(expression->guts)->error_code(); #ifndef BOOST_NO_EXCEPTIONS } diff --git a/3rdParty/Boost/src/libs/regex/src/static_mutex.cpp b/3rdParty/Boost/src/libs/regex/src/static_mutex.cpp index d14feb1..d02b01f 100644 --- a/3rdParty/Boost/src/libs/regex/src/static_mutex.cpp +++ b/3rdParty/Boost/src/libs/regex/src/static_mutex.cpp @@ -18,6 +18,7 @@ #define BOOST_REGEX_SOURCE #include <boost/config.hpp> +#include <boost/assert.hpp> #ifdef BOOST_HAS_THREADS @@ -54,8 +55,8 @@ void scoped_static_mutex_lock::lock() { if(0 == m_have_lock) { - pthread_mutex_lock(&(m_mutex.m_mutex)); - m_have_lock = true; + // Client code will throw if this fails: + m_have_lock = (pthread_mutex_lock(&(m_mutex.m_mutex)) == 0); } } @@ -63,7 +64,10 @@ void scoped_static_mutex_lock::unlock() { if(m_have_lock) { - pthread_mutex_unlock(&(m_mutex.m_mutex)); + // If this fails there's nothing we can do except assert, + // exceptions are out of the question as this code is called + // from the lock's destructor: + BOOST_VERIFY(pthread_mutex_unlock(&(m_mutex.m_mutex)) == 0); m_have_lock = false; } } @@ -157,7 +161,7 @@ void scoped_static_mutex_lock::lock() { boost::call_once(static_mutex::m_once,&static_mutex::init); if(0 == m_plock) - m_plock = new boost::recursive_mutex::scoped_lock(*static_mutex::m_pmutex, boost::defer_lock); + m_plock = new boost::unique_lock<boost::recursive_mutex>(*static_mutex::m_pmutex, boost::defer_lock); m_plock->lock(); m_have_lock = true; } diff --git a/3rdParty/Boost/src/libs/regex/src/w32_regex_traits.cpp b/3rdParty/Boost/src/libs/regex/src/w32_regex_traits.cpp index 8c22214..cf4dc10 100644 --- a/3rdParty/Boost/src/libs/regex/src/w32_regex_traits.cpp +++ b/3rdParty/Boost/src/libs/regex/src/w32_regex_traits.cpp @@ -283,9 +283,11 @@ BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, l if (r == 0) return def; - LPSTR buf = (LPSTR)_alloca( (r + 1) * 2 ); - if (::WideCharToMultiByte(CP_ACP, 0, wbuf, r, buf, (r + 1) * 2, NULL, NULL) == 0) - return def; + + int buf_size = 1 + ::WideCharToMultiByte(CP_ACP, 0, wbuf, r, NULL, 0, NULL, NULL); + LPSTR buf = (LPSTR)_alloca(buf_size); + if (::WideCharToMultiByte(CP_ACP, 0, wbuf, r, buf, buf_size, NULL, NULL) == 0) + return def; // failed conversion. #endif return std::string(buf); } @@ -485,7 +487,7 @@ BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type idx) return c; if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0) - return c; + return c; // No single byte lower case equivalent available #endif return result[0]; } @@ -556,7 +558,7 @@ BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type idx) return c; if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0) - return c; + return c; // No single byte upper case equivalent available. #endif return result[0]; } diff --git a/3rdParty/Boost/src/libs/regex/src/wc_regex_traits.cpp b/3rdParty/Boost/src/libs/regex/src/wc_regex_traits.cpp index b3d2c5a..7815a09 100644 --- a/3rdParty/Boost/src/libs/regex/src/wc_regex_traits.cpp +++ b/3rdParty/Boost/src/libs/regex/src/wc_regex_traits.cpp @@ -94,6 +94,19 @@ c_regex_traits<wchar_t>::string_type BOOST_REGEX_CALL c_regex_traits<wchar_t>::t std::wstring result(s, L' '); while(s < (r = std::wcsxfrm(&*result.begin(), src.c_str(), s))) { +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::strxfrm, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if(r == INT_MAX) + { + result.erase(); + result.insert(result.begin(), static_cast<wchar_t>(0)); + return result; + } +#endif result.append(r - s + 3, L' '); s = result.size(); } diff --git a/3rdParty/Boost/src/libs/regex/src/wide_posix_api.cpp b/3rdParty/Boost/src/libs/regex/src/wide_posix_api.cpp index ff5c90d..41704cd 100644 --- a/3rdParty/Boost/src/libs/regex/src/wide_posix_api.cpp +++ b/3rdParty/Boost/src/libs/regex/src/wide_posix_api.cpp @@ -135,7 +135,7 @@ BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW* expression, const wcha #endif expression->re_magic = wmagic_value; static_cast<wc_regex_type*>(expression->guts)->set_expression(ptr, p2, flags); - expression->re_nsub = static_cast<wc_regex_type*>(expression->guts)->mark_count() - 1; + expression->re_nsub = static_cast<wc_regex_type*>(expression->guts)->mark_count(); result = static_cast<wc_regex_type*>(expression->guts)->error_code(); #ifndef BOOST_NO_EXCEPTIONS } diff --git a/3rdParty/Boost/src/libs/serialization/src/archive_exception.cpp b/3rdParty/Boost/src/libs/serialization/src/archive_exception.cpp index 50d326a..d06303f 100644 --- a/3rdParty/Boost/src/libs/serialization/src/archive_exception.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/archive_exception.cpp @@ -13,7 +13,7 @@ #endif #include <exception> -#include <boost/assert.hpp> +//#include <boost/assert.hpp> #include <string> #define BOOST_ARCHIVE_SOURCE @@ -22,6 +22,18 @@ namespace boost { namespace archive { +unsigned int +archive_exception::append(unsigned int l, const char * a){ + while(l < (sizeof(m_buffer) - 1)){ + char c = *a++; + if('\0' == c) + break; + m_buffer[l++] = c; + } + m_buffer[l] = '\0'; + return l; +} + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_exception::archive_exception( exception_code c, @@ -30,80 +42,81 @@ archive_exception::archive_exception( ) : code(c) { - m_msg = "programming error"; + unsigned int length = 0; switch(code){ case no_exception: - m_msg = "uninitialized exception"; + length = append(length, "uninitialized exception"); break; case unregistered_class: - m_msg = "unregistered class"; + length = append(length, "unregistered class"); if(NULL != e1){ - m_msg += " - "; - m_msg += e1; + length = append(length, " - "); + length = append(length, e1); } break; case invalid_signature: - m_msg = "invalid signature"; + length = append(length, "invalid signature"); break; case unsupported_version: - m_msg = "unsupported version"; + length = append(length, "unsupported version"); break; case pointer_conflict: - m_msg = "pointer conflict"; + length = append(length, "pointer conflict"); break; case incompatible_native_format: - m_msg = "incompatible native format"; + length = append(length, "incompatible native format"); if(NULL != e1){ - m_msg += " - "; - m_msg += e1; + length = append(length, " - "); + length = append(length, e1); } break; case array_size_too_short: - m_msg = "array size too short"; + length = append(length, "array size too short"); break; case input_stream_error: - m_msg = "input stream error"; + length = append(length, "input stream error"); break; case invalid_class_name: - m_msg = "class name too long"; + length = append(length, "class name too long"); break; case unregistered_cast: - m_msg = "unregistered void cast "; - m_msg += (NULL != e1) ? e1 : "?"; - m_msg += "<-"; - m_msg += (NULL != e2) ? e2 : "?"; + length = append(length, "unregistered void cast "); + length = append(length, (NULL != e1) ? e1 : "?"); + length = append(length, "<-"); + length = append(length, (NULL != e2) ? e2 : "?"); break; case unsupported_class_version: - m_msg = "class version "; - m_msg += (NULL != e1) ? e1 : "<unknown class>"; + length = append(length, "class version "); + length = append(length, (NULL != e1) ? e1 : "<unknown class>"); break; case other_exception: // if get here - it indicates a derived exception // was sliced by passing by value in catch - m_msg = "unknown derived exception"; + length = append(length, "unknown derived exception"); break; case multiple_code_instantiation: - m_msg = "code instantiated in more than one module"; + length = append(length, "code instantiated in more than one module"); if(NULL != e1){ - m_msg += " - "; - m_msg += e1; + length = append(length, " - "); + length = append(length, e1); } break; case output_stream_error: - m_msg = "output stream error"; + length = append(length, "output stream error"); break; default: BOOST_ASSERT(false); + length = append(length, "programming error"); break; } } BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) -archive_exception::~archive_exception() throw () {} +archive_exception::~archive_exception() throw() {} BOOST_ARCHIVE_DECL(const char *) archive_exception::what( ) const throw() { - return m_msg.c_str(); + return m_buffer; } BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_exception::archive_exception() : diff --git a/3rdParty/Boost/src/libs/serialization/src/basic_archive.cpp b/3rdParty/Boost/src/libs/serialization/src/basic_archive.cpp index 23e5702..8baf178 100644 --- a/3rdParty/Boost/src/libs/serialization/src/basic_archive.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/basic_archive.cpp @@ -70,10 +70,11 @@ BOOST_ARCHIVE_SIGNATURE(){ // 8 - Boost 1.44 // separated version_type into library_version_type and class_version_type // changed version_type to be stored as 8 bits. +// 10- fixed base64 output/input. BOOST_ARCHIVE_DECL(library_version_type) BOOST_ARCHIVE_VERSION(){ - return library_version_type(9); + return library_version_type(11); } } // namespace archive diff --git a/3rdParty/Boost/src/libs/serialization/src/basic_iarchive.cpp b/3rdParty/Boost/src/libs/serialization/src/basic_iarchive.cpp index e9baddd..3a24690 100644 --- a/3rdParty/Boost/src/libs/serialization/src/basic_iarchive.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/basic_iarchive.cpp @@ -81,9 +81,18 @@ class basic_iarchive_impl { ////////////////////////////////////////////////////////////////////// // used to implement the reset_object_address operation. - object_id_type moveable_objects_start; - object_id_type moveable_objects_end; - object_id_type moveable_objects_recent; + struct moveable_objects { + object_id_type start; + object_id_type end; + object_id_type recent; + bool is_pointer; + moveable_objects() : + start(0), + end(0), + recent(0), + is_pointer(false) + {} + } m_moveable_objects; void reset_object_address( const void * new_address, @@ -159,19 +168,20 @@ class basic_iarchive_impl { ////////////////////////////////////////////////////////////////////// // address of the most recent object serialized as a poiner // whose data itself is now pending serialization - void * pending_object; - const basic_iserializer * pending_bis; - version_type pending_version; + struct pending { + void * object; + const basic_iserializer * bis; + version_type version; + pending() : + object(NULL), + bis(NULL), + version(0) + {} + } m_pending; basic_iarchive_impl(unsigned int flags) : m_archive_library_version(BOOST_ARCHIVE_VERSION()), - m_flags(flags), - moveable_objects_start(0), - moveable_objects_end(0), - moveable_objects_recent(0), - pending_object(NULL), - pending_bis(NULL), - pending_version(0) + m_flags(flags) {} ~basic_iarchive_impl(){} void set_library_version(library_version_type archive_library_version){ @@ -200,7 +210,7 @@ class basic_iarchive_impl { //public: void next_object_pointer(void * t){ - pending_object = t; + m_pending.object = t; } void delete_created_pointers(); class_id_type register_type( @@ -224,9 +234,12 @@ class basic_iarchive_impl { inline void basic_iarchive_impl::reset_object_address( - const void * new_address, - const void *old_address + void const * const new_address, + void const * const old_address ){ + if(m_moveable_objects.is_pointer) + return; + // this code handles a couple of situations. // a) where reset_object_address is applied to an untracked object. // In such a case the call is really superfluous and its really an @@ -240,18 +253,18 @@ basic_iarchive_impl::reset_object_address( // of the programmer but we can't detect it - as above. So maybe we // can save a few more people from themselves as above. object_id_type i; - for(i = moveable_objects_recent; i < moveable_objects_end; ++i){ + for(i = m_moveable_objects.recent; i < m_moveable_objects.end; ++i){ if(old_address == object_id_vector[i].address) break; } - for(; i < moveable_objects_end; ++i){ - + for(; i < m_moveable_objects.end; ++i){ + void const * const this_address = object_id_vector[i].address; // calculate displacement from this level // warning - pointer arithmetic on void * is in herently non-portable // but expected to work on all platforms in current usage - if(object_id_vector[i].address > old_address){ + if(this_address > old_address){ std::size_t member_displacement - = reinterpret_cast<std::size_t>(object_id_vector[i].address) + = reinterpret_cast<std::size_t>(this_address) - reinterpret_cast<std::size_t>(old_address); object_id_vector[i].address = reinterpret_cast<void *>( reinterpret_cast<std::size_t>(new_address) + member_displacement @@ -260,7 +273,7 @@ basic_iarchive_impl::reset_object_address( else{ std::size_t member_displacement = reinterpret_cast<std::size_t>(old_address) - - reinterpret_cast<std::size_t>(object_id_vector[i].address); + - reinterpret_cast<std::size_t>(this_address); object_id_vector[i].address = reinterpret_cast<void *>( reinterpret_cast<std::size_t>(new_address) - member_displacement ); @@ -356,10 +369,12 @@ basic_iarchive_impl::load_object( void * t, const basic_iserializer & bis ){ + m_moveable_objects.is_pointer = false; + serialization::state_saver<bool> ss_is_pointer(m_moveable_objects.is_pointer); // if its been serialized through a pointer and the preamble's been done - if(t == pending_object && & bis == pending_bis){ + if(t == m_pending.object && & bis == m_pending.bis){ // read data - (bis.load_object_data)(ar, t, pending_version); + (bis.load_object_data)(ar, t, m_pending.version); return; } @@ -370,13 +385,13 @@ basic_iarchive_impl::load_object( load_preamble(ar, co); // save the current move stack position in case we want to truncate it - boost::serialization::state_saver<object_id_type> w(moveable_objects_start); + boost::serialization::state_saver<object_id_type> ss_start(m_moveable_objects.start); // note: extra line used to evade borland issue const bool tracking = co.tracking_level; object_id_type this_id; - moveable_objects_start = + m_moveable_objects.start = this_id = object_id_type(object_id_vector.size()); // if we tracked this object when the archive was saved @@ -388,11 +403,11 @@ basic_iarchive_impl::load_object( // add a new enty into the tracking list object_id_vector.push_back(aobject(t, cid)); // and add an entry for this object - moveable_objects_end = object_id_type(object_id_vector.size()); + m_moveable_objects.end = object_id_type(object_id_vector.size()); } // read data (bis.load_object_data)(ar, t, co.file_version); - moveable_objects_recent = this_id; + m_moveable_objects.recent = this_id; } inline const basic_pointer_iserializer * @@ -403,8 +418,10 @@ basic_iarchive_impl::load_pointer( const basic_pointer_iserializer * (*finder)( const boost::serialization::extended_type_info & type_ ) - ){ + m_moveable_objects.is_pointer = true; + serialization::state_saver<bool> w(m_moveable_objects.is_pointer); + class_id_type cid; load(ar, cid); @@ -434,10 +451,10 @@ basic_iarchive_impl::load_pointer( bpis_ptr = (*finder)(*eti); } BOOST_ASSERT(NULL != bpis_ptr); - class_id_type new_cid = register_type(bpis_ptr->get_basic_serializer()); + // class_id_type new_cid = register_type(bpis_ptr->get_basic_serializer()); + BOOST_VERIFY(register_type(bpis_ptr->get_basic_serializer()) == cid); int i = cid; cobject_id_vector[i].bpis_ptr = bpis_ptr; - BOOST_ASSERT(new_cid == cid); } int i = cid; cobject_id & co = cobject_id_vector[i]; @@ -453,38 +470,41 @@ basic_iarchive_impl::load_pointer( return bpis_ptr; // save state - serialization::state_saver<object_id_type> w_start(moveable_objects_start); + serialization::state_saver<object_id_type> w_start(m_moveable_objects.start); + + // allocate space on the heap for the object - to be constructed later + t = bpis_ptr->heap_allocation(); + BOOST_ASSERT(NULL != t); if(! tracking){ bpis_ptr->load_object_ptr(ar, t, co.file_version); } else{ - serialization::state_saver<void *> x(pending_object); - serialization::state_saver<const basic_iserializer *> y(pending_bis); - serialization::state_saver<version_type> z(pending_version); + serialization::state_saver<void *> x(m_pending.object); + serialization::state_saver<const basic_iserializer *> y(m_pending.bis); + serialization::state_saver<version_type> z(m_pending.version); - pending_bis = & bpis_ptr->get_basic_serializer(); - pending_version = co.file_version; + m_pending.bis = & bpis_ptr->get_basic_serializer(); + m_pending.version = co.file_version; // predict next object id to be created const unsigned int ui = object_id_vector.size(); - serialization::state_saver<object_id_type> w_end(moveable_objects_end); + serialization::state_saver<object_id_type> w_end(m_moveable_objects.end); - // because the following operation could move the items - // don't use co after this + // add to list of serialized objects so that we can properly handle // cyclic strucures object_id_vector.push_back(aobject(t, cid)); + // remember that that the address of these elements could change + // when we make another call so don't use the address bpis_ptr->load_object_ptr( - ar, - object_id_vector[ui].address, - co.file_version + ar, + t, + m_pending.version ); - t = object_id_vector[ui].address; object_id_vector[ui].loaded_as_pointer = true; - BOOST_ASSERT(NULL != t); } return bpis_ptr; diff --git a/3rdParty/Boost/src/libs/serialization/src/basic_oarchive.cpp b/3rdParty/Boost/src/libs/serialization/src/basic_oarchive.cpp index 33f33f8..840955b 100644 --- a/3rdParty/Boost/src/libs/serialization/src/basic_oarchive.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/basic_oarchive.cpp @@ -331,6 +331,12 @@ basic_oarchive_impl::save_pointer( // makes a copy when passing a non-const to a const. This // is permitted by the standard but rarely seen in practice const class_name_type cn(key); + if(cn.size() > (BOOST_SERIALIZATION_MAX_KEY_SIZE - 1)) + boost::serialization::throw_exception( + boost::archive::archive_exception( + boost::archive::archive_exception:: + invalid_class_name) + ); // write out the external class identifier ar.vsave(cn); } diff --git a/3rdParty/Boost/src/libs/serialization/src/basic_serializer_map.cpp b/3rdParty/Boost/src/libs/serialization/src/basic_serializer_map.cpp index 80e805f..7df0b3d 100644 --- a/3rdParty/Boost/src/libs/serialization/src/basic_serializer_map.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/basic_serializer_map.cpp @@ -43,11 +43,12 @@ basic_serializer_map::type_info_pointer_compare::operator()( BOOST_ARCHIVE_DECL(bool) basic_serializer_map::insert(const basic_serializer * bs){ // attempt to insert serializer into it's map - const std::pair<map_type::iterator, bool> result = - m_map.insert(bs); // the following is commented out - rather than being just // deleted as a reminder not to try this. + // const std::pair<map_type::iterator, bool> result = + m_map.insert(bs); + // At first it seemed like a good idea. It enforced the // idea that a type be exported from at most one code module // (DLL or mainline). This would enforce a "one definition rule" diff --git a/3rdParty/Boost/src/libs/serialization/src/binary_iarchive.cpp b/3rdParty/Boost/src/libs/serialization/src/binary_iarchive.cpp index 7bb0435..c1117e9 100644 --- a/3rdParty/Boost/src/libs/serialization/src/binary_iarchive.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/binary_iarchive.cpp @@ -22,20 +22,6 @@ namespace boost { namespace archive { // explicitly instantiate for this type of stream -template class detail::archive_serializer_map<naked_binary_iarchive>; -template class basic_binary_iprimitive< - naked_binary_iarchive, - std::istream::char_type, - std::istream::traits_type ->; -template class basic_binary_iarchive<naked_binary_iarchive> ; -template class binary_iarchive_impl< - naked_binary_iarchive, - std::istream::char_type, - std::istream::traits_type ->; - -// explicitly instantiate for this type of stream template class detail::archive_serializer_map<binary_iarchive>; template class basic_binary_iprimitive< binary_iarchive, diff --git a/3rdParty/Boost/src/libs/serialization/src/binary_wiarchive.cpp b/3rdParty/Boost/src/libs/serialization/src/binary_wiarchive.cpp index a6135c8..720d469 100644 --- a/3rdParty/Boost/src/libs/serialization/src/binary_wiarchive.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/binary_wiarchive.cpp @@ -26,19 +26,6 @@ namespace boost { namespace archive { -template class detail::archive_serializer_map<naked_binary_wiarchive>; -template class basic_binary_iprimitive< - naked_binary_wiarchive, - wchar_t, - std::char_traits<wchar_t> ->; -template class basic_binary_iarchive<naked_binary_wiarchive> ; -template class binary_iarchive_impl< - naked_binary_wiarchive, - wchar_t, - std::char_traits<wchar_t> ->; - // explicitly instantiate for this type of text stream template class detail::archive_serializer_map<binary_wiarchive>; template class basic_binary_iprimitive< diff --git a/3rdParty/Boost/src/libs/serialization/src/shared_ptr_helper.cpp b/3rdParty/Boost/src/libs/serialization/src/shared_ptr_helper.cpp index b155cd9..15102e2 100644 --- a/3rdParty/Boost/src/libs/serialization/src/shared_ptr_helper.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/shared_ptr_helper.cpp @@ -1,8 +1,3 @@ -// MS compatible compilers support #pragma once -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 // shared_ptr_helper.hpp: serialization for boost shared pointern @@ -17,6 +12,7 @@ #include <list> #include <utility> #include <cstddef> // NULL +#include <cassert> #define BOOST_ARCHIVE_SOURCE // include this to prevent linker errors when the @@ -26,113 +22,42 @@ #include <boost/serialization/throw_exception.hpp> #include <boost/serialization/void_cast.hpp> #include <boost/serialization/extended_type_info.hpp> -#include <boost/archive/shared_ptr_helper.hpp> +#include <boost/serialization/shared_ptr_helper.hpp> #include <boost/archive/archive_exception.hpp> namespace boost { -namespace archive{ -namespace detail { +namespace serialization { /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 // a common class for holding various types of shared pointers -// returns pointer to object and an indicator whether this is a -// new entry (true) or a previous one (false) -BOOST_ARCHIVE_DECL(shared_ptr<void>) -shared_ptr_helper::get_od( - const void * t, - const boost::serialization::extended_type_info * true_type, - const boost::serialization::extended_type_info * this_type -){ - // get void pointer to the most derived type - // this uniquely identifies the object referred to - const void * od = void_downcast( - *true_type, - *this_type, - t - ); - if(NULL == od) - boost::serialization::throw_exception( - archive_exception( - archive_exception::unregistered_cast, - true_type->get_debug_info(), - this_type->get_debug_info() - ) - ); - - // make tracking array if necessary - if(NULL == m_pointers) - m_pointers = new collection_type; - - //shared_ptr<const void> sp(od, null_deleter()); - shared_ptr<const void> sp(od, null_deleter()); - collection_type::iterator i = m_pointers->find(sp); - - if(i == m_pointers->end()){ - shared_ptr<void> np; - return np; - } - od = void_upcast( - *true_type, - *this_type, - i->get() - ); - if(NULL == od) - boost::serialization::throw_exception( - archive_exception( - archive_exception::unregistered_cast, - true_type->get_debug_info(), - this_type->get_debug_info() - ) - ); - - return shared_ptr<void>( - const_pointer_cast<void>(*i), - const_cast<void *>(od) - ); -} - -BOOST_ARCHIVE_DECL(void) -shared_ptr_helper::append(const boost::shared_ptr<const void> &sp){ - // make tracking array if necessary - if(NULL == m_pointers) - m_pointers = new collection_type; - - collection_type::iterator i = m_pointers->find(sp); - - if(i == m_pointers->end()){ - std::pair<collection_type::iterator, bool> result; - result = m_pointers->insert(sp); - BOOST_ASSERT(result.second); - } -} - // #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP BOOST_ARCHIVE_DECL(void) -shared_ptr_helper::append(const boost_132::shared_ptr<const void> & t){ +shared_ptr_helper_base::append(const boost_132::shared_ptr<const void> & t){ if(NULL == m_pointers_132) m_pointers_132 = new std::list<boost_132::shared_ptr<const void> >; m_pointers_132->push_back(t); } // #endif + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) -shared_ptr_helper::shared_ptr_helper() : - m_pointers(NULL) +shared_ptr_helper_base::shared_ptr_helper_base() : + m_o_sp(NULL) #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP , m_pointers_132(NULL) #endif {} + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) -shared_ptr_helper::~shared_ptr_helper(){ - if(NULL != m_pointers) - delete m_pointers; +shared_ptr_helper_base::~shared_ptr_helper_base(){ + if(NULL != m_o_sp) + delete m_o_sp; #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP if(NULL != m_pointers_132) delete m_pointers_132; #endif } -} // namespace detail } // namespace serialization } // namespace boost diff --git a/3rdParty/Boost/src/libs/serialization/src/text_iarchive.cpp b/3rdParty/Boost/src/libs/serialization/src/text_iarchive.cpp index cb9017f..9520ca2 100644 --- a/3rdParty/Boost/src/libs/serialization/src/text_iarchive.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/text_iarchive.cpp @@ -24,10 +24,6 @@ namespace boost { namespace archive { -template class detail::archive_serializer_map<naked_text_iarchive>; -template class basic_text_iarchive<naked_text_iarchive> ; -template class text_iarchive_impl<naked_text_iarchive> ; - template class detail::archive_serializer_map<text_iarchive>; template class basic_text_iarchive<text_iarchive> ; template class text_iarchive_impl<text_iarchive> ; diff --git a/3rdParty/Boost/src/libs/serialization/src/text_wiarchive.cpp b/3rdParty/Boost/src/libs/serialization/src/text_wiarchive.cpp index a6630c0..a0c68a8 100644 --- a/3rdParty/Boost/src/libs/serialization/src/text_wiarchive.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/text_wiarchive.cpp @@ -26,10 +26,6 @@ namespace boost { namespace archive { -template class detail::archive_serializer_map<naked_text_wiarchive>; -template class basic_text_iarchive<naked_text_wiarchive> ; -template class text_wiarchive_impl<naked_text_wiarchive> ; - template class detail::archive_serializer_map<text_wiarchive>; template class basic_text_iarchive<text_wiarchive> ; template class text_wiarchive_impl<text_wiarchive> ; diff --git a/3rdParty/Boost/src/libs/serialization/src/utf8_codecvt_facet.cpp b/3rdParty/Boost/src/libs/serialization/src/utf8_codecvt_facet.cpp index d064c63..07deada 100644 --- a/3rdParty/Boost/src/libs/serialization/src/utf8_codecvt_facet.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/utf8_codecvt_facet.cpp @@ -7,15 +7,14 @@ #ifdef BOOST_NO_STD_WSTREAMBUF #error "wide char i/o not supported on this platform" #else - -#define BOOST_UTF8_BEGIN_NAMESPACE \ - namespace boost { namespace archive { namespace detail { -#define BOOST_UTF8_DECL -#define BOOST_UTF8_END_NAMESPACE }}} -#include <boost/detail/utf8_codecvt_facet.ipp> -#undef BOOST_UTF8_END_NAMESPACE -#undef BOOST_UTF8_DECL -#undef BOOST_UTF8_BEGIN_NAMESPACE - + #ifdef BOOST_NO_CXX11_HDR_CODECVT + #define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { namespace archive { namespace detail { + #define BOOST_UTF8_DECL + #define BOOST_UTF8_END_NAMESPACE }}} + #include <boost/detail/utf8_codecvt_facet.ipp> + #undef BOOST_UTF8_END_NAMESPACE + #undef BOOST_UTF8_DECL + #undef BOOST_UTF8_BEGIN_NAMESPACE + #endif // BOOST_NO_CXX11_HDR_CODECVT #endif // BOOST_NO_STD_WSTREAMBUF - diff --git a/3rdParty/Boost/src/libs/serialization/src/xml_archive_exception.cpp b/3rdParty/Boost/src/libs/serialization/src/xml_archive_exception.cpp index ea78916..41d33fd 100644 --- a/3rdParty/Boost/src/libs/serialization/src/xml_archive_exception.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/xml_archive_exception.cpp @@ -31,23 +31,23 @@ xml_archive_exception::xml_archive_exception( ) : archive_exception(other_exception, e1, e2) { - m_msg = "programming error"; switch(c){ case xml_archive_parsing_error: - m_msg = "unrecognized XML syntax"; + archive_exception::append(0, "unrecognized XML syntax"); break; case xml_archive_tag_mismatch: - m_msg = "XML start/end tag mismatch"; + archive_exception::append(0, "XML start/end tag mismatch"); if(NULL != e1){ - m_msg += " - "; - m_msg += e1; + archive_exception::append(0, " - "); + archive_exception::append(0, e1); } break; case xml_archive_tag_name_error: - m_msg = "Invalid XML tag name"; + archive_exception::append(0, "Invalid XML tag name"); break; default: BOOST_ASSERT(false); + archive_exception::append(0, "programming error"); break; } } diff --git a/3rdParty/Boost/src/libs/serialization/src/xml_iarchive.cpp b/3rdParty/Boost/src/libs/serialization/src/xml_iarchive.cpp index 6d0de77..4311893 100644 --- a/3rdParty/Boost/src/libs/serialization/src/xml_iarchive.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/xml_iarchive.cpp @@ -34,10 +34,6 @@ namespace boost { namespace archive { -template class detail::archive_serializer_map<naked_xml_iarchive>; -template class basic_xml_iarchive<naked_xml_iarchive> ; -template class xml_iarchive_impl<naked_xml_iarchive> ; - template class detail::archive_serializer_map<xml_iarchive>; template class basic_xml_iarchive<xml_iarchive> ; template class xml_iarchive_impl<xml_iarchive> ; diff --git a/3rdParty/Boost/src/libs/serialization/src/xml_wiarchive.cpp b/3rdParty/Boost/src/libs/serialization/src/xml_wiarchive.cpp index 2e10947..0266548 100644 --- a/3rdParty/Boost/src/libs/serialization/src/xml_wiarchive.cpp +++ b/3rdParty/Boost/src/libs/serialization/src/xml_wiarchive.cpp @@ -39,10 +39,6 @@ namespace boost { namespace archive { -template class detail::archive_serializer_map<naked_xml_wiarchive>; -template class basic_xml_iarchive<naked_xml_wiarchive> ; -template class xml_wiarchive_impl<naked_xml_wiarchive> ; - template class detail::archive_serializer_map<xml_wiarchive>; template class basic_xml_iarchive<xml_wiarchive> ; template class xml_wiarchive_impl<xml_wiarchive> ; diff --git a/3rdParty/Boost/src/libs/signals/src/connection.cpp b/3rdParty/Boost/src/libs/signals/src/connection.cpp deleted file mode 100644 index b4ed8b4..0000000 --- a/3rdParty/Boost/src/libs/signals/src/connection.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// Boost.Signals library - -// Copyright Douglas Gregor 2001-2004. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org - -#define BOOST_SIGNALS_SOURCE - -#include <boost/signals/connection.hpp> -#include <cassert> - -namespace boost { - namespace BOOST_SIGNALS_NAMESPACE { - - connection::connection(const connection& other) : - con(other.con), controlling_connection(other.controlling_connection) - { - } - - connection::~connection() - { - if (controlling_connection) { - disconnect(); - } - } - - void - connection::reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection* new_con) - { - con.reset(new_con); - } - - bool connection::operator==(const connection& other) const - { - return con.get() == other.con.get(); - } - - bool connection::operator<(const connection& other) const - { - return con.get() < other.con.get(); - } - - connection& connection::operator=(const connection& other) - { - connection(other).swap(*this); - return *this; - } - - void connection::swap(connection& other) - { - this->con.swap(other.con); - std::swap(this->controlling_connection, other.controlling_connection); - } - - void swap(connection& c1, connection& c2) - { - c1.swap(c2); - } - - scoped_connection::scoped_connection(const connection& other) : - connection(other), - released(false) - { - } - - scoped_connection::scoped_connection(const scoped_connection& other) : - connection(other), - released(other.released) - { - } - - scoped_connection::~scoped_connection() - { - if (!released) { - this->disconnect(); - } - } - - connection scoped_connection::release() - { - released = true; - return *this; - } - - void scoped_connection::swap(scoped_connection& other) - { - this->connection::swap(other); - bool other_released = other.released; - other.released = this->released; - this->released = other_released; - } - - void swap(scoped_connection& c1, scoped_connection& c2) - { - c1.swap(c2); - } - - scoped_connection& - scoped_connection::operator=(const connection& other) - { - scoped_connection(other).swap(*this); - return *this; - } - - scoped_connection& - scoped_connection::operator=(const scoped_connection& other) - { - scoped_connection(other).swap(*this); - return *this; - } - - void - connection::add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b) - { - assert(con.get() != 0); - con->bound_objects.push_back(b); - } - - - void connection::disconnect() const - { - if (this->connected()) { - // Make sure we have a reference to the basic_connection object, - // because 'this' may disappear - shared_ptr<detail::basic_connection> local_con = con; - - void (*signal_disconnect)(void*, void*) = local_con->signal_disconnect; - - // Note that this connection no longer exists - // Order is important here: we could get into an infinite loop if this - // isn't cleared before we try the disconnect. - local_con->signal_disconnect = 0; - - // Disconnect signal - signal_disconnect(local_con->signal, local_con->signal_data); - - // Disconnect all bound objects - typedef std::list<BOOST_SIGNALS_NAMESPACE::detail::bound_object>::iterator iterator; - for (iterator i = local_con->bound_objects.begin(); - i != local_con->bound_objects.end(); ++i) { - assert(i->disconnect != 0); - i->disconnect(i->obj, i->data); - } - } - } - } // end namespace boost -} // end namespace boost - -#ifndef BOOST_MSVC -// Explicit instantiations to keep everything in the library -template class std::list<boost::BOOST_SIGNALS_NAMESPACE::detail::bound_object>; -#endif diff --git a/3rdParty/Boost/src/libs/signals/src/named_slot_map.cpp b/3rdParty/Boost/src/libs/signals/src/named_slot_map.cpp deleted file mode 100644 index ac9a292..0000000 --- a/3rdParty/Boost/src/libs/signals/src/named_slot_map.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// Boost.Signals library - -// Copyright Douglas Gregor 2001-2004. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org - -#define BOOST_SIGNALS_SOURCE - -#include <boost/signals/detail/named_slot_map.hpp> -#include <cassert> -#include <map> -#include <list> -#include <typeinfo> - -namespace boost { namespace BOOST_SIGNALS_NAMESPACE { namespace detail { - -typedef std::list<connection_slot_pair> group_list; -typedef group_list::iterator slot_pair_iterator; -typedef std::map<stored_group, group_list, compare_type> slot_container_type; -typedef slot_container_type::iterator group_iterator; -typedef slot_container_type::const_iterator const_group_iterator; - - -#if BOOST_WORKAROUND(_MSC_VER, <= 1700) -void named_slot_map_iterator::decrement() { assert(false); } -void named_slot_map_iterator::advance(difference_type) { assert(false); } -#endif - -named_slot_map::named_slot_map(const compare_type& compare) : groups(compare) -{ - clear(); -} - -void named_slot_map::clear() -{ - groups.clear(); - groups[stored_group(stored_group::sk_front)]; - groups[stored_group(stored_group::sk_back)]; - back = groups.end(); - --back; -} - -named_slot_map::iterator named_slot_map::begin() -{ - return named_slot_map::iterator(groups.begin(), groups.end()); -} - -named_slot_map::iterator named_slot_map::end() -{ - return named_slot_map::iterator(groups.end(), groups.end()); -} - -named_slot_map::iterator -named_slot_map::insert(const stored_group& name, const connection& con, - const any& slot, connect_position at) -{ - group_iterator group; - if (name.empty()) { - switch (at) { - case at_front: group = groups.begin(); break; - case at_back: group = back; break; - } - } else { - group = groups.find(name); - if (group == groups.end()) { - slot_container_type::value_type v(name, group_list()); - group = groups.insert(v).first; - } - } - iterator it; - it.group = group; - it.last_group = groups.end(); - - switch (at) { - case at_back: - group->second.push_back(connection_slot_pair(con, slot)); - it.slot_ = group->second.end(); - it.slot_assigned = true; - --(it.slot_); - break; - - case at_front: - group->second.push_front(connection_slot_pair(con, slot)); - it.slot_ = group->second.begin(); - it.slot_assigned = true; - break; - } - return it; -} - -void named_slot_map::disconnect(const stored_group& name) -{ - group_iterator group = groups.find(name); - if (group != groups.end()) { - slot_pair_iterator i = group->second.begin(); - while (i != group->second.end()) { - slot_pair_iterator next = i; - ++next; - i->first.disconnect(); - i = next; - } - groups.erase((const_group_iterator) group); - } -} - -void named_slot_map::erase(iterator pos) -{ - // Erase the slot - pos.slot_->first.disconnect(); - pos.group->second.erase(pos.slot_); -} - -void named_slot_map::remove_disconnected_slots() -{ - // Remove any disconnected slots - group_iterator g = groups.begin(); - while (g != groups.end()) { - slot_pair_iterator s = g->second.begin(); - while (s != g->second.end()) { - if (s->first.connected()) ++s; - else g->second.erase(s++); - } - - // Clear out empty groups - if (empty(g)) groups.erase((const_group_iterator) g++); - else ++g; - } -} - - -} } } diff --git a/3rdParty/Boost/src/libs/signals/src/signal_base.cpp b/3rdParty/Boost/src/libs/signals/src/signal_base.cpp deleted file mode 100644 index 759672d..0000000 --- a/3rdParty/Boost/src/libs/signals/src/signal_base.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// Boost.Signals library - -// Copyright Douglas Gregor 2001-2004. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org - -#define BOOST_SIGNALS_SOURCE - -#include <boost/signals/detail/signal_base.hpp> -#include <cassert> - -namespace boost { - namespace BOOST_SIGNALS_NAMESPACE { - namespace detail { - signal_base_impl::signal_base_impl(const compare_type& comp, - const any& combiner) - : call_depth(0), - slots_(comp), - combiner_(combiner) - { - flags.delayed_disconnect = false; - flags.clearing = false; - } - - signal_base_impl::~signal_base_impl() - { - // Set the "clearing" flag to ignore extraneous disconnect requests, - // because all slots will be disconnected on destruction anyway. - flags.clearing = true; - } - - void signal_base_impl::disconnect_all_slots() - { - // Do nothing if we're already clearing the slot list - if (flags.clearing) - return; - - if (call_depth == 0) { - // Clearing the slot list will disconnect all slots automatically - temporarily_set_clearing set_clearing(this); - slots_.clear(); - } - else { - // We can't actually remove elements from the slot list because there - // are still iterators into the slot list that must not be - // invalidated by this operation. So just disconnect each slot - // without removing it from the slot list. When the call depth does - // reach zero, the call list will be cleared. - flags.delayed_disconnect = true; - temporarily_set_clearing set_clearing(this); - for (iterator i = slots_.begin(); i != slots_.end(); ++i) { - i->first.disconnect(); - } - } - } - - connection - signal_base_impl:: - connect_slot(const any& slot_, - const stored_group& name, - shared_ptr<slot_base::data_t> data, - connect_position at) - { - // Transfer the burden of ownership to a local, scoped - // connection. - data->watch_bound_objects.set_controlling(false); - scoped_connection safe_connection(data->watch_bound_objects); - - // Allocate storage for an iterator that will hold the point of - // insertion of the slot into the list. This is used to later remove - // the slot when it is disconnected. - std::auto_ptr<iterator> saved_iter(new iterator); - - // Add the slot to the list. - iterator pos = - slots_.insert(name, data->watch_bound_objects, slot_, at); - - // The assignment operation here absolutely must not throw, which - // intuitively makes sense (because any container's insert method - // becomes impossible to use in an exception-safe manner without this - // assumption), but doesn't appear to be mentioned in the standard. - *saved_iter = pos; - - // Fill out the connection object appropriately. None of these - // operations can throw - data->watch_bound_objects.get_connection()->signal = this; - data->watch_bound_objects.get_connection()->signal_data = - saved_iter.release(); - data->watch_bound_objects.get_connection()->signal_disconnect = - &signal_base_impl::slot_disconnected; - - // Make the copy of the connection in the list disconnect when it is - // destroyed. The local, scoped connection is then released - // because ownership has been transferred. - pos->first.set_controlling(); - return safe_connection.release(); - } - - bool signal_base_impl::empty() const - { - // Disconnected slots may still be in the list of slots if - // a) this is called while slots are being invoked (call_depth > 0) - // b) an exception was thrown in remove_disconnected_slots - for (iterator i = slots_.begin(); i != slots_.end(); ++i) { - if (i->first.connected()) - return false; - } - - return true; - } - - std::size_t signal_base_impl::num_slots() const - { - // Disconnected slots may still be in the list of slots if - // a) this is called while slots are being invoked (call_depth > 0) - // b) an exception was thrown in remove_disconnected_slots - std::size_t count = 0; - for (iterator i = slots_.begin(); i != slots_.end(); ++i) { - if (i->first.connected()) - ++count; - } - return count; - } - - void signal_base_impl::disconnect(const stored_group& group) - { slots_.disconnect(group); } - - void signal_base_impl::slot_disconnected(void* obj, void* data) - { - signal_base_impl* self = reinterpret_cast<signal_base_impl*>(obj); - - // We won't need the slot iterator after this - std::auto_ptr<iterator> slot(reinterpret_cast<iterator*>(data)); - - // If we're flags.clearing, we don't bother updating the list of slots - if (!self->flags.clearing) { - // If we're in a call, note the fact that a slot has been deleted so - // we can come back later to remove the iterator - if (self->call_depth > 0) { - self->flags.delayed_disconnect = true; - } - else { - // Just remove the slot now, it's safe - self->slots_.erase(*slot); - } - } - } - - void signal_base_impl::remove_disconnected_slots() const - { slots_.remove_disconnected_slots(); } - - call_notification:: - call_notification(const shared_ptr<signal_base_impl>& b) : - impl(b) - { - // A call will be made, so increment the call depth as a notification - impl->call_depth++; - } - - call_notification::~call_notification() - { - impl->call_depth--; - - // If the call depth is zero and we have some slots that have been - // disconnected during the calls, remove those slots from the list - if (impl->call_depth == 0 && - impl->flags.delayed_disconnect) { - impl->remove_disconnected_slots(); - impl->flags.delayed_disconnect = false; - } - } - - signal_base::signal_base(const compare_type& comp, const any& combiner) - : impl() - { - impl.reset(new signal_base_impl(comp, combiner)); - } - - signal_base::~signal_base() - { - } - - } // namespace detail - } // namespace BOOST_SIGNALS_NAMESPACE -} // namespace boost - diff --git a/3rdParty/Boost/src/libs/signals/src/slot.cpp b/3rdParty/Boost/src/libs/signals/src/slot.cpp deleted file mode 100644 index 7c296d6..0000000 --- a/3rdParty/Boost/src/libs/signals/src/slot.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// Boost.Signals library - -// Copyright Douglas Gregor 2001-2004. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org - -#define BOOST_SIGNALS_SOURCE - -#include <boost/signals/slot.hpp> - -namespace boost { - namespace BOOST_SIGNALS_NAMESPACE { - namespace detail { - void slot_base::create_connection() - { - // Create a new connection object - basic_connection* con = new basic_connection(); - - /* nothrow */ { - // The signal portion isn't really necessary, except that we need a - // signal for the connection to be connected. - con->signal = static_cast<void*>(this); - con->signal_data = 0; - con->blocked_ = false ; - con->signal_disconnect = &bound_object_destructed; - } - - // This connection watches for destruction of bound objects. Note - // that the reset routine will delete con if an allocation throws - data->watch_bound_objects.reset(con); - - // We create a scoped connection, so that exceptions thrown while - // adding bound objects will cause a cleanup of the bound objects - // already connected. - scoped_connection safe_connection(data->watch_bound_objects); - - // Now notify each of the bound objects that they are connected to this - // slot. - for(std::vector<const trackable*>::iterator i = - data->bound_objects.begin(); - i != data->bound_objects.end(); ++i) { - // Notify the object that the slot is connecting to it - BOOST_SIGNALS_NAMESPACE::detail::bound_object binding; - (*i)->signal_connected(data->watch_bound_objects, binding); - - // This will notify the bound object that the connection just made - // should be disconnected if an exception is thrown before the - // end of this iteration - BOOST_SIGNALS_NAMESPACE::detail::auto_disconnect_bound_object - disconnector(binding); - - // Add the binding to the list of bindings for the connection - con->bound_objects.push_back(binding); - - // The connection object now knows about the bound object, so if an - // exception is thrown later the connection object will notify the - // bound object of the disconnection automatically - disconnector.release(); - } - - // No exceptions will be thrown past this point. - safe_connection.release(); - - data->watch_bound_objects.set_controlling(true); - } - } // end namespace detail - } // end namespace BOOST_SIGNALS_NAMESPACE -} // end namespace boost diff --git a/3rdParty/Boost/src/libs/signals/src/trackable.cpp b/3rdParty/Boost/src/libs/signals/src/trackable.cpp deleted file mode 100644 index 4f63586..0000000 --- a/3rdParty/Boost/src/libs/signals/src/trackable.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Boost.Signals library - -// Copyright Douglas Gregor 2001-2004. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org - -#define BOOST_SIGNALS_SOURCE - -#include <boost/signals/trackable.hpp> -#include <algorithm> - -namespace boost { - namespace BOOST_SIGNALS_NAMESPACE { - void trackable::signal_disconnected(void* obj, void* data) - { - trackable* self = reinterpret_cast<trackable*>(obj); - connection_iterator* signal = - reinterpret_cast<connection_iterator*>(data); - - // If we're dying, don't bother erasing the connection from the list; - // it'll be gone anyway - if (!self->dying) { - self->connected_signals.erase(*signal); - } - - // This iterator pointer won't ever be used again - delete signal; - } - - void - trackable::signal_connected(connection c, - BOOST_SIGNALS_NAMESPACE::detail::bound_object& binding) const - { - // Insert the connection - connection_iterator pos = - connected_signals.insert(connected_signals.end(), c); - - // Make this copy of the object disconnect when destroyed - pos->set_controlling(); - - binding.obj = const_cast<void*>(reinterpret_cast<const void*>(this)); - binding.data = reinterpret_cast<void*>(new connection_iterator(pos)); - binding.disconnect = &signal_disconnected; - } - - trackable::~trackable() - { - dying = true; - } - } // end namespace BOOST_SIGNALS_NAMESPACE -} - -#ifndef BOOST_MSVC -// Explicit instantiations to keep in the library -template class std::list<boost::BOOST_SIGNALS_NAMESPACE::connection>; -#endif diff --git a/3rdParty/Boost/src/libs/system/src/error_code.cpp b/3rdParty/Boost/src/libs/system/src/error_code.cpp index 6772d15..aa628ab 100644 --- a/3rdParty/Boost/src/libs/system/src/error_code.cpp +++ b/3rdParty/Boost/src/libs/system/src/error_code.cpp @@ -9,422 +9,12 @@ //----------------------------------------------------------------------------// -#include <boost/config/warning_disable.hpp> - // define BOOST_SYSTEM_SOURCE so that <boost/system/config.hpp> knows // the library is being built (possibly exporting rather than importing code) -#define BOOST_SYSTEM_SOURCE +#define BOOST_SYSTEM_SOURCE -#include <boost/system/config.hpp> #include <boost/system/error_code.hpp> -#include <boost/cerrno.hpp> -#include <vector> -#include <cstdlib> -#include <cassert> - -using namespace boost::system; -using namespace boost::system::errc; - -#include <cstring> // for strerror/strerror_r - -# if defined( BOOST_WINDOWS_API ) -# include <windows.h> -# include "local_free_on_destruction.hpp" -# ifndef ERROR_INCORRECT_SIZE -# define ERROR_INCORRECT_SIZE ERROR_BAD_ARGUMENTS -# endif -# endif -//----------------------------------------------------------------------------// - -namespace -{ -#if defined(__PGI) - using boost::system::errc::invalid_argument; +#ifndef BOOST_ERROR_CODE_HEADER_ONLY +#include <boost/system/detail/error_code.ipp> #endif - // standard error categories ---------------------------------------------// - - class generic_error_category : public error_category - { - public: - generic_error_category(){} - const char * name() const; - std::string message( int ev ) const; - }; - - class system_error_category : public error_category - { - public: - system_error_category(){} - const char * name() const; - std::string message( int ev ) const; - error_condition default_error_condition( int ev ) const; - }; - - // generic_error_category implementation ---------------------------------// - - const char * generic_error_category::name() const - { - return "generic"; - } - - std::string generic_error_category::message( int ev ) const - { - static std::string unknown_err( "Unknown error" ); - // strerror_r is preferred because it is always thread safe, - // however, we fallback to strerror in certain cases because: - // -- Windows doesn't provide strerror_r. - // -- HP and Sun do provide strerror_r on newer systems, but there is - // no way to tell if is available at runtime and in any case their - // versions of strerror are thread safe anyhow. - // -- Linux only sometimes provides strerror_r. - // -- Tru64 provides strerror_r only when compiled -pthread. - // -- VMS doesn't provide strerror_r, but on this platform, strerror is - // thread safe. - # if defined(BOOST_WINDOWS_API) || defined(__hpux) || defined(__sun)\ - || (defined(__linux) && (!defined(__USE_XOPEN2K) || defined(BOOST_SYSTEM_USE_STRERROR)))\ - || (defined(__osf__) && !defined(_REENTRANT))\ - || (defined(__INTEGRITY))\ - || (defined(__vms))\ - || (defined(__QNXNTO__)) - const char * c_str = std::strerror( ev ); - return c_str - ? std::string( c_str ) - : unknown_err; - # else // use strerror_r - char buf[64]; - char * bp = buf; - std::size_t sz = sizeof(buf); - # if defined(__CYGWIN__) || defined(__USE_GNU) - // Oddball version of strerror_r - const char * c_str = strerror_r( ev, bp, sz ); - return c_str - ? std::string( c_str ) - : unknown_err; - # else - // POSIX version of strerror_r - int result; - for (;;) - { - // strerror_r returns 0 on success, otherwise ERANGE if buffer too small, - // invalid_argument if ev not a valid error number - # if defined (__sgi) - const char * c_str = strerror( ev ); - result = 0; - return c_str - ? std::string( c_str ) - : unknown_err; - # else - result = strerror_r( ev, bp, sz ); - # endif - if (result == 0 ) - break; - else - { - # if defined(__linux) - // Linux strerror_r returns -1 on error, with error number in errno - result = errno; - # endif - if ( result != ERANGE ) break; - if ( sz > sizeof(buf) ) std::free( bp ); - sz *= 2; - if ( (bp = static_cast<char*>(std::malloc( sz ))) == 0 ) - return std::string( "ENOMEM" ); - } - } - std::string msg; - try - { - msg = ( ( result == invalid_argument ) ? "Unknown error" : bp ); - } - -# ifndef BOOST_NO_EXCEPTIONS - // See ticket #2098 - catch(...) - { - // just eat the exception - } -# endif - - if ( sz > sizeof(buf) ) std::free( bp ); - sz = 0; - return msg; - # endif // else POSIX version of strerror_r - # endif // else use strerror_r - } - // system_error_category implementation --------------------------------// - - const char * system_error_category::name() const - { - return "system"; - } - - error_condition system_error_category::default_error_condition( int ev ) const - { - switch ( ev ) - { - case 0: return make_error_condition( success ); -# if defined(BOOST_POSIX_API) - // POSIX-like O/S -> posix_errno decode table ---------------------------// - case E2BIG: return make_error_condition( argument_list_too_long ); - case EACCES: return make_error_condition( permission_denied ); - case EADDRINUSE: return make_error_condition( address_in_use ); - case EADDRNOTAVAIL: return make_error_condition( address_not_available ); - case EAFNOSUPPORT: return make_error_condition( address_family_not_supported ); - case EAGAIN: return make_error_condition( resource_unavailable_try_again ); -# if EALREADY != EBUSY // EALREADY and EBUSY are the same on QNX Neutrino - case EALREADY: return make_error_condition( connection_already_in_progress ); -# endif - case EBADF: return make_error_condition( bad_file_descriptor ); - case EBADMSG: return make_error_condition( bad_message ); - case EBUSY: return make_error_condition( device_or_resource_busy ); - case ECANCELED: return make_error_condition( operation_canceled ); - case ECHILD: return make_error_condition( no_child_process ); - case ECONNABORTED: return make_error_condition( connection_aborted ); - case ECONNREFUSED: return make_error_condition( connection_refused ); - case ECONNRESET: return make_error_condition( connection_reset ); - case EDEADLK: return make_error_condition( resource_deadlock_would_occur ); - case EDESTADDRREQ: return make_error_condition( destination_address_required ); - case EDOM: return make_error_condition( argument_out_of_domain ); - case EEXIST: return make_error_condition( file_exists ); - case EFAULT: return make_error_condition( bad_address ); - case EFBIG: return make_error_condition( file_too_large ); - case EHOSTUNREACH: return make_error_condition( host_unreachable ); - case EIDRM: return make_error_condition( identifier_removed ); - case EILSEQ: return make_error_condition( illegal_byte_sequence ); - case EINPROGRESS: return make_error_condition( operation_in_progress ); - case EINTR: return make_error_condition( interrupted ); - case EINVAL: return make_error_condition( invalid_argument ); - case EIO: return make_error_condition( io_error ); - case EISCONN: return make_error_condition( already_connected ); - case EISDIR: return make_error_condition( is_a_directory ); - case ELOOP: return make_error_condition( too_many_symbolic_link_levels ); - case EMFILE: return make_error_condition( too_many_files_open ); - case EMLINK: return make_error_condition( too_many_links ); - case EMSGSIZE: return make_error_condition( message_size ); - case ENAMETOOLONG: return make_error_condition( filename_too_long ); - case ENETDOWN: return make_error_condition( network_down ); - case ENETRESET: return make_error_condition( network_reset ); - case ENETUNREACH: return make_error_condition( network_unreachable ); - case ENFILE: return make_error_condition( too_many_files_open_in_system ); - case ENOBUFS: return make_error_condition( no_buffer_space ); - case ENODATA: return make_error_condition( no_message_available ); - case ENODEV: return make_error_condition( no_such_device ); - case ENOENT: return make_error_condition( no_such_file_or_directory ); - case ENOEXEC: return make_error_condition( executable_format_error ); - case ENOLCK: return make_error_condition( no_lock_available ); - case ENOLINK: return make_error_condition( no_link ); - case ENOMEM: return make_error_condition( not_enough_memory ); - case ENOMSG: return make_error_condition( no_message ); - case ENOPROTOOPT: return make_error_condition( no_protocol_option ); - case ENOSPC: return make_error_condition( no_space_on_device ); - case ENOSR: return make_error_condition( no_stream_resources ); - case ENOSTR: return make_error_condition( not_a_stream ); - case ENOSYS: return make_error_condition( function_not_supported ); - case ENOTCONN: return make_error_condition( not_connected ); - case ENOTDIR: return make_error_condition( not_a_directory ); - # if ENOTEMPTY != EEXIST // AIX treats ENOTEMPTY and EEXIST as the same value - case ENOTEMPTY: return make_error_condition( directory_not_empty ); - # endif // ENOTEMPTY != EEXIST - # if ENOTRECOVERABLE != ECONNRESET // the same on some Broadcom chips - case ENOTRECOVERABLE: return make_error_condition( state_not_recoverable ); - # endif // ENOTRECOVERABLE != ECONNRESET - case ENOTSOCK: return make_error_condition( not_a_socket ); - case ENOTSUP: return make_error_condition( not_supported ); - case ENOTTY: return make_error_condition( inappropriate_io_control_operation ); - case ENXIO: return make_error_condition( no_such_device_or_address ); - # if EOPNOTSUPP != ENOTSUP - case EOPNOTSUPP: return make_error_condition( operation_not_supported ); - # endif // EOPNOTSUPP != ENOTSUP - case EOVERFLOW: return make_error_condition( value_too_large ); - # if EOWNERDEAD != ECONNABORTED // the same on some Broadcom chips - case EOWNERDEAD: return make_error_condition( owner_dead ); - # endif // EOWNERDEAD != ECONNABORTED - case EPERM: return make_error_condition( operation_not_permitted ); - case EPIPE: return make_error_condition( broken_pipe ); - case EPROTO: return make_error_condition( protocol_error ); - case EPROTONOSUPPORT: return make_error_condition( protocol_not_supported ); - case EPROTOTYPE: return make_error_condition( wrong_protocol_type ); - case ERANGE: return make_error_condition( result_out_of_range ); - case EROFS: return make_error_condition( read_only_file_system ); - case ESPIPE: return make_error_condition( invalid_seek ); - case ESRCH: return make_error_condition( no_such_process ); - case ETIME: return make_error_condition( stream_timeout ); - case ETIMEDOUT: return make_error_condition( timed_out ); - case ETXTBSY: return make_error_condition( text_file_busy ); - # if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: return make_error_condition( operation_would_block ); - # endif // EAGAIN != EWOULDBLOCK - case EXDEV: return make_error_condition( cross_device_link ); - #else - // Windows system -> posix_errno decode table ---------------------------// - // see WinError.h comments for descriptions of errors - case ERROR_ACCESS_DENIED: return make_error_condition( permission_denied ); - case ERROR_ALREADY_EXISTS: return make_error_condition( file_exists ); - case ERROR_BAD_UNIT: return make_error_condition( no_such_device ); - case ERROR_BUFFER_OVERFLOW: return make_error_condition( filename_too_long ); - case ERROR_BUSY: return make_error_condition( device_or_resource_busy ); - case ERROR_BUSY_DRIVE: return make_error_condition( device_or_resource_busy ); - case ERROR_CANNOT_MAKE: return make_error_condition( permission_denied ); - case ERROR_CANTOPEN: return make_error_condition( io_error ); - case ERROR_CANTREAD: return make_error_condition( io_error ); - case ERROR_CANTWRITE: return make_error_condition( io_error ); - case ERROR_CURRENT_DIRECTORY: return make_error_condition( permission_denied ); - case ERROR_DEV_NOT_EXIST: return make_error_condition( no_such_device ); - case ERROR_DEVICE_IN_USE: return make_error_condition( device_or_resource_busy ); - case ERROR_DIR_NOT_EMPTY: return make_error_condition( directory_not_empty ); - case ERROR_DIRECTORY: return make_error_condition( invalid_argument ); // WinError.h: "The directory name is invalid" - case ERROR_DISK_FULL: return make_error_condition( no_space_on_device ); - case ERROR_FILE_EXISTS: return make_error_condition( file_exists ); - case ERROR_FILE_NOT_FOUND: return make_error_condition( no_such_file_or_directory ); - case ERROR_HANDLE_DISK_FULL: return make_error_condition( no_space_on_device ); - case ERROR_INVALID_ACCESS: return make_error_condition( permission_denied ); - case ERROR_INVALID_DRIVE: return make_error_condition( no_such_device ); - case ERROR_INVALID_FUNCTION: return make_error_condition( function_not_supported ); - case ERROR_INVALID_HANDLE: return make_error_condition( invalid_argument ); - case ERROR_INVALID_NAME: return make_error_condition( invalid_argument ); - case ERROR_LOCK_VIOLATION: return make_error_condition( no_lock_available ); - case ERROR_LOCKED: return make_error_condition( no_lock_available ); - case ERROR_NEGATIVE_SEEK: return make_error_condition( invalid_argument ); - case ERROR_NOACCESS: return make_error_condition( permission_denied ); - case ERROR_NOT_ENOUGH_MEMORY: return make_error_condition( not_enough_memory ); - case ERROR_NOT_READY: return make_error_condition( resource_unavailable_try_again ); - case ERROR_NOT_SAME_DEVICE: return make_error_condition( cross_device_link ); - case ERROR_OPEN_FAILED: return make_error_condition( io_error ); - case ERROR_OPEN_FILES: return make_error_condition( device_or_resource_busy ); - case ERROR_OPERATION_ABORTED: return make_error_condition( operation_canceled ); - case ERROR_OUTOFMEMORY: return make_error_condition( not_enough_memory ); - case ERROR_PATH_NOT_FOUND: return make_error_condition( no_such_file_or_directory ); - case ERROR_READ_FAULT: return make_error_condition( io_error ); - case ERROR_RETRY: return make_error_condition( resource_unavailable_try_again ); - case ERROR_SEEK: return make_error_condition( io_error ); - case ERROR_SHARING_VIOLATION: return make_error_condition( permission_denied ); - case ERROR_TOO_MANY_OPEN_FILES: return make_error_condition( too_many_files_open ); - case ERROR_WRITE_FAULT: return make_error_condition( io_error ); - case ERROR_WRITE_PROTECT: return make_error_condition( permission_denied ); - case WSAEACCES: return make_error_condition( permission_denied ); - case WSAEADDRINUSE: return make_error_condition( address_in_use ); - case WSAEADDRNOTAVAIL: return make_error_condition( address_not_available ); - case WSAEAFNOSUPPORT: return make_error_condition( address_family_not_supported ); - case WSAEALREADY: return make_error_condition( connection_already_in_progress ); - case WSAEBADF: return make_error_condition( bad_file_descriptor ); - case WSAECONNABORTED: return make_error_condition( connection_aborted ); - case WSAECONNREFUSED: return make_error_condition( connection_refused ); - case WSAECONNRESET: return make_error_condition( connection_reset ); - case WSAEDESTADDRREQ: return make_error_condition( destination_address_required ); - case WSAEFAULT: return make_error_condition( bad_address ); - case WSAEHOSTUNREACH: return make_error_condition( host_unreachable ); - case WSAEINPROGRESS: return make_error_condition( operation_in_progress ); - case WSAEINTR: return make_error_condition( interrupted ); - case WSAEINVAL: return make_error_condition( invalid_argument ); - case WSAEISCONN: return make_error_condition( already_connected ); - case WSAEMFILE: return make_error_condition( too_many_files_open ); - case WSAEMSGSIZE: return make_error_condition( message_size ); - case WSAENAMETOOLONG: return make_error_condition( filename_too_long ); - case WSAENETDOWN: return make_error_condition( network_down ); - case WSAENETRESET: return make_error_condition( network_reset ); - case WSAENETUNREACH: return make_error_condition( network_unreachable ); - case WSAENOBUFS: return make_error_condition( no_buffer_space ); - case WSAENOPROTOOPT: return make_error_condition( no_protocol_option ); - case WSAENOTCONN: return make_error_condition( not_connected ); - case WSAENOTSOCK: return make_error_condition( not_a_socket ); - case WSAEOPNOTSUPP: return make_error_condition( operation_not_supported ); - case WSAEPROTONOSUPPORT: return make_error_condition( protocol_not_supported ); - case WSAEPROTOTYPE: return make_error_condition( wrong_protocol_type ); - case WSAETIMEDOUT: return make_error_condition( timed_out ); - case WSAEWOULDBLOCK: return make_error_condition( operation_would_block ); - #endif - default: return error_condition( ev, system_category() ); - } - } - -# if !defined( BOOST_WINDOWS_API ) - - std::string system_error_category::message( int ev ) const - { - return generic_category().message( ev ); - } -# else - - std::string system_error_category::message( int ev ) const - { -# ifndef BOOST_NO_ANSI_APIS - LPVOID lpMsgBuf = 0; - DWORD retval = ::FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - ev, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPSTR) &lpMsgBuf, - 0, - NULL - ); - detail::local_free_on_destruction lfod(lpMsgBuf); - if (retval == 0) - return std::string("Unknown error"); - - std::string str( static_cast<LPCSTR>(lpMsgBuf) ); -# else // WinCE workaround - LPVOID lpMsgBuf = 0; - DWORD retval = ::FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - ev, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPWSTR) &lpMsgBuf, - 0, - NULL - ); - detail::local_free_on_destruction lfod(lpMsgBuf); - if (retval == 0) - return std::string("Unknown error"); - - int num_chars = (wcslen( static_cast<LPCWSTR>(lpMsgBuf) ) + 1) * 2; - LPSTR narrow_buffer = (LPSTR)_alloca( num_chars ); - if (::WideCharToMultiByte(CP_ACP, 0, static_cast<LPCWSTR>(lpMsgBuf), -1, narrow_buffer, num_chars, NULL, NULL) == 0) - return std::string("Unknown error"); - - std::string str( narrow_buffer ); -# endif - while ( str.size() - && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') ) - str.erase( str.size()-1 ); - if ( str.size() && str[str.size()-1] == '.' ) - { str.erase( str.size()-1 ); } - return str; - } -# endif - -} // unnamed namespace - -namespace boost -{ - namespace system - { - -# ifndef BOOST_SYSTEM_NO_DEPRECATED - BOOST_SYSTEM_DECL error_code throws; // "throw on error" special error_code; - // note that it doesn't matter if this - // isn't initialized before use since - // the only use is to take its - // address for comparison purposes -# endif - - BOOST_SYSTEM_DECL const error_category & system_category() - { - static const system_error_category system_category_const; - return system_category_const; - } - - BOOST_SYSTEM_DECL const error_category & generic_category() - { - static const generic_error_category generic_category_const; - return generic_category_const; - } - - } // namespace system -} // namespace boost diff --git a/3rdParty/Boost/src/libs/system/src/local_free_on_destruction.hpp b/3rdParty/Boost/src/libs/system/src/local_free_on_destruction.hpp deleted file mode 100644 index 110024f..0000000 --- a/3rdParty/Boost/src/libs/system/src/local_free_on_destruction.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// local_free_on_exit.hpp ------------------------------------------------------------// - -// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2010 Beman Dawes - -// Distributed under the Boost Software License, Version 1.0. -// See http://www.boost.org/LICENSE_1_0.txt - -// This is derived from boost/asio/detail/local_free_on_block_exit.hpp to avoid -// a dependency on asio. Thanks to Chris Kohlhoff for pointing it out. - -#ifndef BOOST_SYSTEM_LOCAL_FREE_ON_EXIT_HPP -#define BOOST_SYSTEM_LOCAL_FREE_ON_EXIT_HPP - -namespace boost { -namespace system { -namespace detail { - -class local_free_on_destruction -{ -public: - explicit local_free_on_destruction(void* p) - : p_(p) {} - - ~local_free_on_destruction() - { - ::LocalFree(p_); - } - -private: - void* p_; - local_free_on_destruction(const local_free_on_destruction&); // = deleted - local_free_on_destruction& operator=(const local_free_on_destruction&); // = deleted -}; - -} // namespace detail -} // namespace system -} // namespace boost - -#endif // BOOST_SYSTEM_LOCAL_FREE_ON_EXIT_HPP diff --git a/3rdParty/Boost/src/libs/thread/src/future.cpp b/3rdParty/Boost/src/libs/thread/src/future.cpp index 33980f5..0b990c1 100755..100644 --- a/3rdParty/Boost/src/libs/thread/src/future.cpp +++ b/3rdParty/Boost/src/libs/thread/src/future.cpp @@ -7,7 +7,8 @@ #ifndef BOOST_NO_EXCEPTIONS -#include <boost/thread/future.hpp> +#include <boost/thread/future_error_code.hpp> +#include <string> namespace boost { @@ -19,12 +20,12 @@ namespace boost public boost::system::error_category { public: - virtual const char* name() const; //BOOST_NOEXCEPT; + virtual const char* name() const BOOST_NOEXCEPT; virtual std::string message(int ev) const; }; const char* - future_error_category::name() const //BOOST_NOEXCEPT + future_error_category::name() const BOOST_NOEXCEPT { return "future"; } @@ -48,14 +49,16 @@ namespace boost } return std::string("unspecified future_errc value\n"); } + future_error_category future_error_category_var; } + BOOST_THREAD_DECL const system::error_category& future_category() BOOST_NOEXCEPT { - static thread_detail::future_error_category f; - return f; + return thread_detail::future_error_category_var; } } #endif + diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/once.cpp b/3rdParty/Boost/src/libs/thread/src/pthread/once.cpp index d5fd656..2cfe7cd 100644 --- a/3rdParty/Boost/src/libs/thread/src/pthread/once.cpp +++ b/3rdParty/Boost/src/libs/thread/src/pthread/once.cpp @@ -3,18 +3,24 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include <boost/thread/detail/config.hpp> +#ifdef BOOST_THREAD_ONCE_ATOMIC +#include "./once_atomic.cpp" +#else #define __STDC_CONSTANT_MACROS +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> #include <boost/thread/once.hpp> #include <boost/assert.hpp> +#include <boost/throw_exception.hpp> #include <pthread.h> #include <stdlib.h> #include <memory> namespace boost { - namespace detail + namespace thread_detail { - BOOST_THREAD_DECL thread_detail::uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; + BOOST_THREAD_DECL uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER; BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER; @@ -55,13 +61,14 @@ namespace boost #endif } - thread_detail::uintmax_atomic_t& get_once_per_thread_epoch() + uintmax_atomic_t& get_once_per_thread_epoch() { BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key)); void* data=pthread_getspecific(epoch_tss_key); if(!data) { data=malloc(sizeof(thread_detail::uintmax_atomic_t)); + if(!data) BOOST_THROW_EXCEPTION(std::bad_alloc()); BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data)); *static_cast<thread_detail::uintmax_atomic_t*>(data)=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; } @@ -70,3 +77,4 @@ namespace boost } } +#endif // diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/once_atomic.cpp b/3rdParty/Boost/src/libs/thread/src/pthread/once_atomic.cpp new file mode 100644 index 0000000..b7ee1dc --- /dev/null +++ b/3rdParty/Boost/src/libs/thread/src/pthread/once_atomic.cpp @@ -0,0 +1,90 @@ +// (C) Copyright 2013 Andrey Semashev +// (C) Copyright 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +//#define __STDC_CONSTANT_MACROS +#include <boost/thread/detail/config.hpp> +#include <boost/thread/once.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#include <boost/assert.hpp> +#include <boost/static_assert.hpp> +#include <boost/atomic.hpp> +#include <boost/memory_order.hpp> +#include <pthread.h> + +namespace boost +{ + namespace thread_detail + { + + enum flag_states + { + uninitialized, in_progress, initialized + }; + + +#ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11 + BOOST_STATIC_ASSERT_MSG(sizeof(atomic_int_type) == sizeof(atomic_type), "Boost.Thread: unsupported platform"); +#endif + + static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_cond_t once_cv = PTHREAD_COND_INITIALIZER; + + BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + if (f.load(memory_order_acquire) != initialized) + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + if (f.load(memory_order_acquire) != initialized) + { + while (true) + { + atomic_int_type expected = uninitialized; + if (f.compare_exchange_strong(expected, in_progress, memory_order_acq_rel, memory_order_acquire)) + { + // We have set the flag to in_progress + return true; + } + else if (expected == initialized) + { + // Another thread managed to complete the initialization + return false; + } + else + { + // Wait until the initialization is complete + //pthread::pthread_mutex_scoped_lock lk(&once_mutex); + BOOST_VERIFY(!pthread_cond_wait(&once_cv, &once_mutex)); + } + } + } + } + return false; + } + + BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + f.store(initialized, memory_order_release); + } + BOOST_VERIFY(!pthread_cond_broadcast(&once_cv)); + } + + BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + f.store(uninitialized, memory_order_release); + } + BOOST_VERIFY(!pthread_cond_broadcast(&once_cv)); + } + + } // namespace thread_detail + +} // namespace boost diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp index c83eac1..f218fa8 100644 --- a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp +++ b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp @@ -1,20 +1,22 @@ // Copyright (C) 2001-2003 // William E. Kempf // Copyright (C) 2007-8 Anthony Williams -// (C) Copyright 2011 Vicente J. Botet Escriba +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include <boost/thread/detail/config.hpp> -#include <boost/thread/thread.hpp> +#include <boost/thread/thread_only.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/thread/xtime.hpp> +#endif #include <boost/thread/condition_variable.hpp> #include <boost/thread/locks.hpp> #include <boost/thread/once.hpp> #include <boost/thread/tss.hpp> -#include <boost/throw_exception.hpp> +#include <boost/thread/future.hpp> #ifdef __GLIBC__ #include <sys/sysinfo.h> @@ -25,6 +27,15 @@ #include <unistd.h> #endif +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/trim.hpp> +#include <boost/lexical_cast.hpp> + +#include <fstream> +#include <string> +#include <set> +#include <vector> + #include "./timeconv.inl" #pragma GCC diagnostic ignored "-Wreturn-type" @@ -35,14 +46,17 @@ namespace boost { thread_data_base::~thread_data_base() { - { for (notify_list_t::iterator i = notify.begin(), e = notify.end(); i != e; ++i) { i->second->unlock(); i->first->notify_all(); } - } + for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end(); + i != e; ++i) + { + (*i)->make_ready(); + } } struct thread_exit_callback_node @@ -74,6 +88,7 @@ namespace boost { while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks) { + while(thread_info->thread_exit_callbacks) { detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks; @@ -99,7 +114,10 @@ namespace boost thread_info->tss_data.erase(current); } } - thread_info->self.reset(); + if (thread_info) // fixme: should we test this? + { + thread_info->self.reset(); + } } } } @@ -150,38 +168,54 @@ namespace boost boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self; thread_info->self.reset(); detail::set_current_thread_data(thread_info.get()); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS BOOST_TRY { +#endif thread_info->run(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } BOOST_CATCH (thread_interrupted const&) { } - BOOST_CATCH_END // Removed as it stops the debugger identifying the cause of the exception // Unhandled exceptions still cause the application to terminate // BOOST_CATCH(...) // { +// throw; +// // std::terminate(); // } - + BOOST_CATCH_END +#endif detail::tls_destructor(thread_info.get()); detail::set_current_thread_data(0); boost::lock_guard<boost::mutex> lock(thread_info->data_mutex); thread_info->done=true; thread_info->done_condition.notify_all(); + return 0; } } - + } + namespace detail + { struct externally_launched_thread: detail::thread_data_base { externally_launched_thread() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS interrupt_enabled=false; +#endif + } + ~externally_launched_thread() { + BOOST_ASSERT(notify.empty()); + notify.clear(); + BOOST_ASSERT(async_states_.empty()); + async_states_.clear(); } - void run() {} void notify_all_at_thread_exit(condition_variable*, mutex*) @@ -192,18 +226,18 @@ namespace boost void operator=(externally_launched_thread&); }; - detail::thread_data_base* make_external_thread_data() + thread_data_base* make_external_thread_data() { - detail::thread_data_base* const me(new externally_launched_thread()); + thread_data_base* const me(detail::heap_new<externally_launched_thread>()); me->self.reset(me); set_current_thread_data(me); return me; } - detail::thread_data_base* get_or_make_current_thread_data() + thread_data_base* get_or_make_current_thread_data() { - detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); + thread_data_base* current_thread_data(get_current_thread_data()); if(!current_thread_data) { current_thread_data=make_external_thread_data(); @@ -217,18 +251,20 @@ namespace boost thread::thread() BOOST_NOEXCEPT {} - void thread::start_thread() + bool thread::start_thread_noexcept() { thread_info->self=thread_info; int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get()); if (res != 0) { thread_info->self.reset(); - boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create")); + return false; +// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create")); } + return true; } - void thread::start_thread(const attributes& attr) + bool thread::start_thread_noexcept(const attributes& attr) { thread_info->self=thread_info; const attributes::native_handle_type* h = attr.native_handle(); @@ -236,14 +272,16 @@ namespace boost if (res != 0) { thread_info->self.reset(); - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create")); } int detached_state; res = pthread_attr_getdetachstate(h, &detached_state); if (res != 0) { thread_info->self.reset(); - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_attr_getdetachstate")); } if (PTHREAD_CREATE_DETACHED==detached_state) { @@ -261,6 +299,7 @@ namespace boost } } } + return true; } @@ -270,12 +309,8 @@ namespace boost return thread_info; } - void thread::join() + bool thread::join_noexcept() { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } detail::thread_data_ptr const local_thread_info=(get_thread_info)(); if(local_thread_info) { @@ -314,21 +349,16 @@ namespace boost { thread_info.reset(); } + return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } - bool thread::do_try_join_until(struct timespec const &timeout) + bool thread::do_try_join_until_noexcept(struct timespec const &timeout, bool& res) { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } detail::thread_data_ptr const local_thread_info=(get_thread_info)(); if(local_thread_info) { @@ -338,9 +368,10 @@ namespace boost unique_lock<mutex> lock(local_thread_info->data_mutex); while(!local_thread_info->done) { - if(!local_thread_info->done_condition.do_timed_wait(lock,timeout)) + if(!local_thread_info->done_condition.do_wait_until(lock,timeout)) { - return false; + res=false; + return true; } } do_join=!local_thread_info->join_started; @@ -370,19 +401,18 @@ namespace boost { thread_info.reset(); } + res=true; return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } bool thread::joinable() const BOOST_NOEXCEPT { - return (get_thread_info)(); + return (get_thread_info)()?true:false; } @@ -405,61 +435,121 @@ namespace boost namespace this_thread { + namespace no_interruption_point + { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts) + { -#ifdef __DECXXX - /// Workaround of DECCXX issue of incorrect template substitution - template<> -#endif - void sleep(const system_time& st) + if (boost::detail::timespec_ge(ts, boost::detail::timespec_zero())) + { + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + # if defined(__IBMCPP__) || defined(_AIX) + BOOST_VERIFY(!pthread_delay_np(const_cast<timespec*>(&ts))); + # else + BOOST_VERIFY(!pthread_delay_np(&ts)); + # endif + # elif defined(BOOST_HAS_NANOSLEEP) + // nanosleep takes a timespec that is an offset, not + // an absolute time. + nanosleep(&ts, 0); + # else + mutex mx; + unique_lock<mutex> lock(mx); + condition_variable cond; + cond.do_wait_for(lock, ts); + # endif + } + } + + void BOOST_THREAD_DECL sleep_until(const timespec& ts) + { + timespec now = boost::detail::timespec_now(); + if (boost::detail::timespec_gt(ts, now)) + { + for (int foo=0; foo < 5; ++foo) + { + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + timespec d = boost::detail::timespec_minus(ts, now); + BOOST_VERIFY(!pthread_delay_np(&d)); + # elif defined(BOOST_HAS_NANOSLEEP) + // nanosleep takes a timespec that is an offset, not + // an absolute time. + timespec d = boost::detail::timespec_minus(ts, now); + nanosleep(&d, 0); + # else + mutex mx; + unique_lock<mutex> lock(mx); + condition_variable cond; + cond.do_wait_until(lock, ts); + # endif + timespec now2 = boost::detail::timespec_now(); + if (boost::detail::timespec_ge(now2, ts)) + { + return; + } + } + } + } + + } + } + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts) { - detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); if(thread_info) { - unique_lock<mutex> lk(thread_info->sleep_mutex); - while(thread_info->sleep_condition.timed_wait(lk,st)) {} + unique_lock<mutex> lk(thread_info->sleep_mutex); + while( thread_info->sleep_condition.do_wait_for(lk,ts)) {} } else { - xtime const xt=get_xtime(st); + boost::this_thread::no_interruption_point::hiden::sleep_for(ts); + } + } - for (int foo=0; foo < 5; ++foo) - { -# if defined(BOOST_HAS_PTHREAD_DELAY_NP) - timespec ts; - to_timespec_duration(xt, ts); - BOOST_VERIFY(!pthread_delay_np(&ts)); -# elif defined(BOOST_HAS_NANOSLEEP) - timespec ts; - to_timespec_duration(xt, ts); + void BOOST_THREAD_DECL sleep_until(const timespec& ts) + { + boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); - // nanosleep takes a timespec that is an offset, not - // an absolute time. - nanosleep(&ts, 0); -# else - mutex mx; - mutex::scoped_lock lock(mx); - condition cond; - cond.timed_wait(lock, xt); -# endif - xtime cur; - xtime_get(&cur, TIME_UTC_); - if (xtime_cmp(xt, cur) <= 0) - return; - } + if(thread_info) + { + unique_lock<mutex> lk(thread_info->sleep_mutex); + while(thread_info->sleep_condition.do_wait_until(lk,ts)) {} + } + else + { + boost::this_thread::no_interruption_point::hiden::sleep_until(ts); } } + } // hiden + } // this_thread + namespace this_thread + { void yield() BOOST_NOEXCEPT { # if defined(BOOST_HAS_SCHED_YIELD) BOOST_VERIFY(!sched_yield()); # elif defined(BOOST_HAS_PTHREAD_YIELD) BOOST_VERIFY(!pthread_yield()); +//# elif defined BOOST_THREAD_USES_DATETIME +// xtime xt; +// xtime_get(&xt, TIME_UTC_); +// sleep(xt); +// sleep_for(chrono::milliseconds(0)); # else - xtime xt; - xtime_get(&xt, TIME_UTC_); - sleep(xt); +#error + timespec ts; + ts.tv_sec= 0; + ts.tv_nsec= 0; + hiden::sleep_for(ts); # endif } } @@ -481,24 +571,65 @@ namespace boost #endif } - thread::id thread::get_id() const BOOST_NOEXCEPT + unsigned thread::physical_concurrency() BOOST_NOEXCEPT { - #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID - //return local_thread_info->thread_handle; - return const_cast<thread*>(this)->native_handle(); - #else - detail::thread_data_ptr const local_thread_info=(get_thread_info)(); - if(local_thread_info) - { - return id(local_thread_info); - } - else - { - return id(); +#ifdef __linux__ + try { + using namespace std; + + ifstream proc_cpuinfo ("/proc/cpuinfo"); + + const string physical_id("physical id"), core_id("core id"); + + typedef std::pair<unsigned, unsigned> core_entry; // [physical ID, core id] + + std::set<core_entry> cores; + + core_entry current_core_entry; + + string line; + while ( getline(proc_cpuinfo, line) ) { + if (line.empty()) + continue; + + vector<string> key_val(2); + boost::split(key_val, line, boost::is_any_of(":")); + + if (key_val.size() != 2) + return hardware_concurrency(); + + string key = key_val[0]; + string value = key_val[1]; + boost::trim(key); + boost::trim(value); + + if (key == physical_id) { + current_core_entry.first = boost::lexical_cast<unsigned>(value); + continue; + } + + if (key == core_id) { + current_core_entry.second = boost::lexical_cast<unsigned>(value); + cores.insert(current_core_entry); + continue; + } + } + // Fall back to hardware_concurrency() in case + // /proc/cpuinfo is formatted differently than we expect. + return cores.size() != 0 ? cores.size() : hardware_concurrency(); + } catch(...) { + return hardware_concurrency(); } - #endif +#elif defined(__APPLE__) + int count; + size_t size=sizeof(count); + return sysctlbyname("hw.physicalcpu",&count,&size,NULL,0)?0:count; +#else + return hardware_concurrency(); +#endif } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void thread::interrupt() { detail::thread_data_ptr const local_thread_info=(get_thread_info)(); @@ -527,6 +658,7 @@ namespace boost return false; } } +#endif thread::native_handle_type thread::native_handle() { @@ -544,18 +676,9 @@ namespace boost +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS namespace this_thread { - thread::id get_id() BOOST_NOEXCEPT - { - #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID - return pthread_self(); - #else - boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data(); - return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr()); - #endif - } - void interruption_point() { #ifndef BOOST_NO_EXCEPTIONS @@ -625,6 +748,7 @@ namespace boost } } } +#endif namespace detail { @@ -632,7 +756,7 @@ namespace boost { detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); thread_exit_callback_node* const new_node= - new thread_exit_callback_node(func,current_thread_data->thread_exit_callbacks); + heap_new<thread_exit_callback_node>(func,current_thread_data->thread_exit_callbacks); current_thread_data->thread_exit_callbacks=new_node; } @@ -670,8 +794,11 @@ namespace boost void erase_tss_node(void const* key) { - detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); - current_thread_data->tss_data.erase(key); + detail::thread_data_base* const current_thread_data(get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->tss_data.erase(key); + } } void set_tss_data(void const* key, @@ -700,6 +827,7 @@ namespace boost } } } + BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) { detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); @@ -708,6 +836,17 @@ namespace boost current_thread_data->notify_all_at_thread_exit(&cond, lk.release()); } } +namespace detail { + + void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as) + { + detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->make_ready_at_thread_exit(as); + } + } +} diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl b/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl index cab7c55..d81f31b 100644 --- a/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl +++ b/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl @@ -17,6 +17,7 @@ const int NANOSECONDS_PER_MILLISECOND = 1000000; const int MICROSECONDS_PER_SECOND = 1000000; const int NANOSECONDS_PER_MICROSECOND = 1000; +#if defined BOOST_THREAD_USES_DATETIME inline void to_time(int milliseconds, boost::xtime& xt) { int res = 0; @@ -33,7 +34,9 @@ inline void to_time(int milliseconds, boost::xtime& xt) xt.nsec -= NANOSECONDS_PER_SECOND; } } +#endif #if defined(BOOST_HAS_PTHREADS) +#if defined BOOST_THREAD_USES_DATETIME inline void to_timespec(const boost::xtime& xt, timespec& ts) { ts.tv_sec = static_cast<int>(xt.sec); @@ -44,14 +47,27 @@ inline void to_timespec(const boost::xtime& xt, timespec& ts) ts.tv_nsec %= NANOSECONDS_PER_SECOND; } } - +#endif inline void to_time(int milliseconds, timespec& ts) { +#if defined BOOST_THREAD_USES_DATETIME boost::xtime xt; to_time(milliseconds, xt); to_timespec(xt, ts); +#else + ts.tv_sec += (milliseconds / MILLISECONDS_PER_SECOND); + ts.tv_nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * + NANOSECONDS_PER_MILLISECOND); + + if (ts.tv_nsec >= NANOSECONDS_PER_SECOND) + { + ++ts.tv_sec; + ts.tv_nsec -= NANOSECONDS_PER_SECOND; + } +#endif } +#if defined BOOST_THREAD_USES_DATETIME inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) { boost::xtime cur; @@ -82,7 +98,9 @@ inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) } } #endif +#endif +#if defined BOOST_THREAD_USES_DATETIME inline void to_duration(boost::xtime xt, int& milliseconds) { boost::xtime cur; @@ -126,6 +144,7 @@ inline void to_microduration(boost::xtime xt, int& microseconds) NANOSECONDS_PER_MICROSECOND); } } +#endif } // Change Log: diff --git a/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp b/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp index 5a26f5e..54ebbf3 100644 --- a/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp +++ b/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp @@ -3,6 +3,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007 Anthony Williams // (C) Copyright 2007 David Deakins +// (C) Copyright 2011-2013 Vicente J. Botet Escriba #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x400 @@ -11,17 +12,20 @@ #ifndef WINVER #define WINVER 0x400 #endif +//#define BOOST_THREAD_VERSION 3 -#include <boost/thread/thread.hpp> +#include <boost/thread/thread_only.hpp> #include <boost/thread/once.hpp> #include <boost/thread/tss.hpp> #include <boost/thread/condition_variable.hpp> #include <boost/thread/detail/tss_hooks.hpp> +#include <boost/thread/future.hpp> #include <boost/assert.hpp> -#include <boost/throw_exception.hpp> +#include <boost/cstdint.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/date_time/posix_time/conversion.hpp> - +#endif #include <memory> #include <algorithm> #ifndef UNDER_CE @@ -36,16 +40,20 @@ namespace boost { thread_data_base::~thread_data_base() { - { for (notify_list_t::iterator i = notify.begin(), e = notify.end(); i != e; ++i) { i->second->unlock(); i->first->notify_all(); } - } + for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end(); + i != e; ++i) + { + (*i)->make_ready(); + } } } + namespace { #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 @@ -75,24 +83,34 @@ namespace boost } } - detail::thread_data_base* get_current_thread_data() - { - if(current_thread_tls_key==TLS_OUT_OF_INDEXES) - { - return 0; - } - return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key); - } - void set_current_thread_data(detail::thread_data_base* new_data) { boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); - if(current_thread_tls_key!=TLS_OUT_OF_INDEXES) + if (current_thread_tls_key!=TLS_OUT_OF_INDEXES) + { BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data)); + } else - boost::throw_exception(thread_resource_error()); + { + BOOST_VERIFY(false); + //boost::throw_exception(thread_resource_error()); + } } + } + namespace detail + { + thread_data_base* get_current_thread_data() + { + if(current_thread_tls_key==TLS_OUT_OF_INDEXES) + { + return 0; + } + return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key); + } + } + namespace + { #ifndef BOOST_HAS_THREADEX // Windows CE doesn't define _beginthreadex @@ -111,7 +129,7 @@ namespace boost return ret; } - typedef void* uintptr_t; + //typedef void* uintptr_t; inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*), void* arglist, unsigned initflag, unsigned* thrdaddr) @@ -151,7 +169,7 @@ namespace boost { void run_thread_exit_callbacks() { - detail::thread_data_ptr current_thread_data(get_current_thread_data(),false); + detail::thread_data_ptr current_thread_data(detail::get_current_thread_data(),false); if(current_thread_data) { while(! current_thread_data->tss_data.empty() || current_thread_data->thread_exit_callbacks) @@ -190,23 +208,24 @@ namespace boost { detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param)); set_current_thread_data(thread_info); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + BOOST_TRY { +#endif thread_info->run(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS } -#ifndef BOOST_NO_EXCEPTIONS - catch(thread_interrupted const&) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(thread_interrupted const&) { } -#endif // Removed as it stops the debugger identifying the cause of the exception // Unhandled exceptions still cause the application to terminate -// catch(...) // BOOST_NO_EXCEPTIONS protected +// BOOST_CATCH(...) // { // std::terminate(); // } + BOOST_CATCH_END +#endif run_thread_exit_callbacks(); return 0; } @@ -215,29 +234,33 @@ namespace boost thread::thread() BOOST_NOEXCEPT {} - void thread::start_thread() + bool thread::start_thread_noexcept() { uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); if(!new_thread) { - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error()); } intrusive_ptr_add_ref(thread_info.get()); thread_info->thread_handle=(detail::win32::handle)(new_thread); ResumeThread(thread_info->thread_handle); + return true; } - void thread::start_thread(const attributes& attr) + bool thread::start_thread_noexcept(const attributes& attr) { //uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); uintptr_t const new_thread=_beginthreadex(0,static_cast<unsigned int>(attr.get_stack_size()),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); if(!new_thread) { - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error()); } intrusive_ptr_add_ref(thread_info.get()); thread_info->thread_handle=(detail::win32::handle)(new_thread); ResumeThread(thread_info->thread_handle); + return true; } thread::thread(detail::thread_data_ptr data): @@ -252,7 +275,15 @@ namespace boost externally_launched_thread() { ++count; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS interruption_enabled=false; +#endif + } + ~externally_launched_thread() { + BOOST_ASSERT(notify.empty()); + notify.clear(); + BOOST_ASSERT(async_states_.empty()); + async_states_.clear(); } void run() @@ -268,28 +299,25 @@ namespace boost void make_external_thread_data() { externally_launched_thread* me=detail::heap_new<externally_launched_thread>(); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { set_current_thread_data(me); } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { detail::heap_delete(me); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } detail::thread_data_base* get_or_make_current_thread_data() { - detail::thread_data_base* current_thread_data(get_current_thread_data()); + detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); if(!current_thread_data) { make_external_thread_data(); - current_thread_data=get_current_thread_data(); + current_thread_data=detail::get_current_thread_data(); } return current_thread_data; } @@ -309,54 +337,47 @@ namespace boost bool thread::joinable() const BOOST_NOEXCEPT { - return (get_thread_info)(); + return (get_thread_info)() ? true : false; } - void thread::join() + bool thread::join_noexcept() { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } + detail::thread_data_ptr local_thread_info=(get_thread_info)(); if(local_thread_info) { this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel()); release_handle(); + return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } +#if defined BOOST_THREAD_USES_DATETIME bool thread::timed_join(boost::system_time const& wait_until) { return do_try_join_until(get_milliseconds_until(wait_until)); } - - bool thread::do_try_join_until(uintmax_t milli) +#endif + bool thread::do_try_join_until_noexcept(uintmax_t milli, bool& res) { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } detail::thread_data_ptr local_thread_info=(get_thread_info)(); if(local_thread_info) { if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli)) { - return false; + res=false; + return true; } release_handle(); + res=true; return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } @@ -370,6 +391,7 @@ namespace boost thread_info=0; } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void thread::interrupt() { detail::thread_data_ptr local_thread_info=(get_thread_info)(); @@ -385,13 +407,40 @@ namespace boost return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0); } +#endif + unsigned thread::hardware_concurrency() BOOST_NOEXCEPT { - SYSTEM_INFO info={{0}}; + //SYSTEM_INFO info={{0}}; + SYSTEM_INFO info; GetSystemInfo(&info); return info.dwNumberOfProcessors; } + unsigned thread::physical_concurrency() BOOST_NOEXCEPT + { + unsigned cores = 0; +#if !(defined(__MINGW32__) || defined (__MINGW64__)) + DWORD size = 0; + + GetLogicalProcessorInformation(NULL, &size); + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) + return 0; + + std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(size); + if (GetLogicalProcessorInformation(&buffer.front(), &size) == FALSE) + return 0; + + const size_t Elements = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); + + for (size_t i = 0; i < Elements; ++i) { + if (buffer[i].Relationship == RelationProcessorCore) + ++cores; + } +#endif + return cores; + } + thread::native_handle_type thread::native_handle() { detail::thread_data_ptr local_thread_info=(get_thread_info)(); @@ -409,10 +458,10 @@ namespace boost { LARGE_INTEGER get_due_time(detail::timeout const& target_time) { - LARGE_INTEGER due_time={{0}}; + LARGE_INTEGER due_time={{0,0}}; if(target_time.relative) { - unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start; + detail::win32::ticks_type const elapsed_milliseconds=detail::win32::GetTickCount64()()-target_time.start; LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds); LONGLONG const hundred_nanoseconds_in_one_millisecond=10000; @@ -423,7 +472,7 @@ namespace boost } else { - SYSTEMTIME target_system_time={0}; + SYSTEMTIME target_system_time={0,0,0,0,0,0,0,0}; target_system_time.wYear=target_time.abs_time.date().year(); target_system_time.wMonth=target_time.abs_time.date().month(); target_system_time.wDay=target_time.abs_time.date().day(); @@ -467,19 +516,22 @@ namespace boost detail::win32::handle handles[3]={0}; unsigned handle_count=0; unsigned wait_handle_index=~0U; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS unsigned interruption_index=~0U; +#endif unsigned timeout_index=~0U; if(handle_to_wait_for!=detail::win32::invalid_handle_value) { wait_handle_index=handle_count; handles[handle_count++]=handle_to_wait_for; } - if(get_current_thread_data() && get_current_thread_data()->interruption_enabled) +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + if(detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled) { interruption_index=handle_count; - handles[handle_count++]=get_current_thread_data()->interruption_handle; + handles[handle_count++]=detail::get_current_thread_data()->interruption_handle; } - +#endif detail::win32::handle_manager timer_handle; #ifndef UNDER_CE @@ -531,11 +583,13 @@ namespace boost { return true; } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS else if(notified_index==interruption_index) { - detail::win32::ResetEvent(get_current_thread_data()->interruption_handle); + detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle); throw thread_interrupted(); } +#endif else if(notified_index==timeout_index) { return false; @@ -555,54 +609,140 @@ namespace boost return false; } + namespace no_interruption_point + { + bool non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time) + { + detail::win32::handle handles[3]={0}; + unsigned handle_count=0; + unsigned wait_handle_index=~0U; + unsigned timeout_index=~0U; + if(handle_to_wait_for!=detail::win32::invalid_handle_value) + { + wait_handle_index=handle_count; + handles[handle_count++]=handle_to_wait_for; + } + detail::win32::handle_manager timer_handle; + +#ifndef UNDER_CE + unsigned const min_timer_wait_period=20; + + if(!target_time.is_sentinel()) + { + detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); + if(time_left.milliseconds > min_timer_wait_period) + { + // for a long-enough timeout, use a waitable timer (which tracks clock changes) + timer_handle=CreateWaitableTimer(NULL,false,NULL); + if(timer_handle!=0) + { + LARGE_INTEGER due_time=get_due_time(target_time); + + bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0; + if(set_time_succeeded) + { + timeout_index=handle_count; + handles[handle_count++]=timer_handle; + } + } + } + else if(!target_time.relative) + { + // convert short absolute-time timeouts into relative ones, so we don't race against clock changes + target_time=detail::timeout(time_left.milliseconds); + } + } +#endif + + bool const using_timer=timeout_index!=~0u; + detail::timeout::remaining_time time_left(0); + + do + { + if(!using_timer) + { + time_left=target_time.remaining_milliseconds(); + } + + if(handle_count) + { + unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds); + if(notified_index<handle_count) + { + if(notified_index==wait_handle_index) + { + return true; + } + else if(notified_index==timeout_index) + { + return false; + } + } + } + else + { + detail::win32::Sleep(time_left.milliseconds); + } + if(target_time.relative) + { + target_time.milliseconds-=detail::timeout::max_non_infinite_wait; + } + } + while(time_left.more); + return false; + } + } + thread::id get_id() BOOST_NOEXCEPT { #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID - //return detail::win32::GetCurrentThread(); return detail::win32::GetCurrentThreadId(); #else return thread::id(get_or_make_current_thread_data()); #endif } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void interruption_point() { if(interruption_enabled() && interruption_requested()) { - detail::win32::ResetEvent(get_current_thread_data()->interruption_handle); + detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle); throw thread_interrupted(); } } bool interruption_enabled() BOOST_NOEXCEPT { - return get_current_thread_data() && get_current_thread_data()->interruption_enabled; + return detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled; } bool interruption_requested() BOOST_NOEXCEPT { - return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0); + return detail::get_current_thread_data() && (detail::win32::WaitForSingleObject(detail::get_current_thread_data()->interruption_handle,0)==0); } +#endif void yield() BOOST_NOEXCEPT { detail::win32::Sleep(0); } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS disable_interruption::disable_interruption() BOOST_NOEXCEPT: interruption_was_enabled(interruption_enabled()) { if(interruption_was_enabled) { - get_current_thread_data()->interruption_enabled=false; + detail::get_current_thread_data()->interruption_enabled=false; } } disable_interruption::~disable_interruption() BOOST_NOEXCEPT { - if(get_current_thread_data()) + if(detail::get_current_thread_data()) { - get_current_thread_data()->interruption_enabled=interruption_was_enabled; + detail::get_current_thread_data()->interruption_enabled=interruption_was_enabled; } } @@ -610,17 +750,18 @@ namespace boost { if(d.interruption_was_enabled) { - get_current_thread_data()->interruption_enabled=true; + detail::get_current_thread_data()->interruption_enabled=true; } } restore_interruption::~restore_interruption() BOOST_NOEXCEPT { - if(get_current_thread_data()) + if(detail::get_current_thread_data()) { - get_current_thread_data()->interruption_enabled=false; + detail::get_current_thread_data()->interruption_enabled=false; } } +#endif } namespace detail @@ -716,12 +857,22 @@ namespace boost BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) { - detail::thread_data_base* const current_thread_data(get_current_thread_data()); + detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); if(current_thread_data) { current_thread_data->notify_all_at_thread_exit(&cond, lk.release()); } } +//namespace detail { +// +// void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as) +// { +// detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); +// if(current_thread_data) +// { +// current_thread_data->make_ready_at_thread_exit(as); +// } +// } +//} } - diff --git a/3rdParty/Boost/src/libs/thread/src/win32/tss_pe.cpp b/3rdParty/Boost/src/libs/thread/src/win32/tss_pe.cpp index 1654b19..5fd53b6 100644 --- a/3rdParty/Boost/src/libs/thread/src/win32/tss_pe.cpp +++ b/3rdParty/Boost/src/libs/thread/src/win32/tss_pe.cpp @@ -1,4 +1,4 @@ -// $Id: tss_pe.cpp 79373 2012-07-09 05:55:01Z viboes $ +// $Id$ // (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004. // (C) Copyright 2007 Roland Schwarz // (C) Copyright 2007 Anthony Williams @@ -80,6 +80,36 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata #define WIN32_LEAN_AND_MEAN #include <windows.h> + +// _pRawDllMainOrig can be defined by including boost/thread/win32/mfc_thread_init.hpp +// into your dll; it ensures that MFC-Dll-initialization will be done properly +// The following code is adapted from the MFC-Dll-init code +/* + * _pRawDllMainOrig MUST be an extern const variable, which will be aliased to + * _pDefaultRawDllMainOrig if no real user definition is present, thanks to the + * alternatename directive. + */ + +// work at least with _MSC_VER 1500 (MSVC++ 9.0, VS 2008) +#if (_MSC_VER >= 1500) + +extern "C" { +extern BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID); +extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NULL; +#if defined (_M_IX86) +#pragma comment(linker, "/alternatename:__pRawDllMainOrig=__pDefaultRawDllMainOrig") +#elif defined (_M_X64) || defined (_M_ARM) +#pragma comment(linker, "/alternatename:_pRawDllMainOrig=_pDefaultRawDllMainOrig") +#else /* defined (_M_X64) || defined (_M_ARM) */ +#error Unsupported platform +#endif /* defined (_M_X64) || defined (_M_ARM) */ +} + +#endif + + + + //Definitions required by implementation #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 @@ -240,7 +270,11 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata } } +#if (_MSC_VER >= 1500) + BOOL WINAPI dll_callback(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved) +#else BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID) +#endif { switch (dwReason) { @@ -251,6 +285,13 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata boost::on_process_exit(); break; } + +#if (_MSC_VER >= 1500) + if( _pRawDllMainOrig ) + { + return _pRawDllMainOrig(hInstance, dwReason, lpReserved); + } +#endif return true; } } //namespace |