diff --git a/asl-uninitialized-move.patch b/asl-uninitialized-move.patch index 2cce2e7..4afe0cb 100644 --- a/asl-uninitialized-move.patch +++ b/asl-uninitialized-move.patch @@ -1,22 +1,81 @@ -diff --git a/adobe/move.hpp b/adobe/move.hpp -index 350000d..6c302a2 100644 ---- a/adobe/move.hpp -+++ b/adobe/move.hpp -@@ -440,8 +440,8 @@ with move semantics, for movable types, otherwise with copy semantics. - */ +diff --git a/asl-uninitialized-move.patch b/asl-uninitialized-move.patch +index 2cce2e7..e69de29 100644 +--- a/asl-uninitialized-move.patch ++++ b/asl-uninitialized-move.patch +@@ -1,56 +0,0 @@ +-diff --git a/adobe/move.hpp b/adobe/move.hpp +-index 350000d..6c302a2 100644 +---- a/adobe/move.hpp +-+++ b/adobe/move.hpp +-@@ -440,8 +440,8 @@ with move semantics, for movable types, otherwise with copy semantics. +- */ +- template // O models BidirectionalIterator +--inline O move_backward(I& in, O out) +--{ return move_backward(boost::begin(in), boost::end(in), out); } +-+inline O adobe::move_backward(I& in, O out) +-+{ return adobe::move_backward(boost::begin(in), boost::end(in), out); } +- +- /*************************************************************************************************/ +- +-diff --git a/adobe/once.hpp b/adobe/once.hpp +-index 5f005a4..e349b92 100644 +---- a/adobe/once.hpp +-+++ b/adobe/once.hpp +-@@ -11,12 +11,12 @@ +- +- /*************************************************************************************************/ +- +--#include +-- +- #if defined(BOOST_HAS_THREADS) +- #include +- #endif +- +-+#include +-+ +- /*************************************************************************************************/ +- +- namespace adobe { +-diff --git a/adobe/vector.hpp b/adobe/vector.hpp +-index 2d23e59..8968b59 100644 +---- a/adobe/vector.hpp +-+++ b/adobe/vector.hpp +-@@ -319,7 +319,7 @@ void vector::append_move(I f, I l, std::forward_iterator_tag) +- size_type n(std::distance(f, l)); +- +- if (remaining() < n) reserve((adobe::max)(size() + n, 2 * size())); +-- set_finish(uninitialized_move(f, l, end())); +-+ set_finish(adobe::uninitialized_move(f, l, end())); +- } +- +- template +-@@ -406,7 +406,7 @@ void vector::reserve(size_type n) +- if (capacity() < n) { +- vector tmp; +- tmp.header_m = allocate(get_allocator(), n); +-- tmp.header_m->finish() = uninitialized_move(begin(), end(), tmp.end()); +-+ tmp.header_m->finish() = adobe::uninitialized_move(begin(), end(), tmp.end()); +- swap(tmp); +- } +- } +diff --git a/tmp/source_release/adobe/move.hpp b/tmp/source_release/adobe/move.hpp +index 350000d..5fe6db5 100644 +--- a/tmp/source_release/adobe/move.hpp ++++ b/tmp/source_release/adobe/move.hpp +@@ -441,7 +441,7 @@ with move semantics, for movable types, otherwise with copy semantics. template // O models BidirectionalIterator --inline O move_backward(I& in, O out) + inline O move_backward(I& in, O out) -{ return move_backward(boost::begin(in), boost::end(in), out); } -+inline O adobe::move_backward(I& in, O out) +{ return adobe::move_backward(boost::begin(in), boost::end(in), out); } /*************************************************************************************************/ -diff --git a/adobe/once.hpp b/adobe/once.hpp +diff --git a/tmp/source_release/adobe/once.hpp b/tmp/source_release/adobe/once.hpp index 5f005a4..e349b92 100644 ---- a/adobe/once.hpp -+++ b/adobe/once.hpp +--- a/tmp/source_release/adobe/once.hpp ++++ b/tmp/source_release/adobe/once.hpp @@ -11,12 +11,12 @@ /*************************************************************************************************/ @@ -32,10 +91,10 @@ index 5f005a4..e349b92 100644 /*************************************************************************************************/ namespace adobe { -diff --git a/adobe/vector.hpp b/adobe/vector.hpp -index 2d23e59..8968b59 100644 ---- a/adobe/vector.hpp -+++ b/adobe/vector.hpp +diff --git a/tmp/source_release/adobe/vector.hpp b/tmp/source_release/adobe/vector.hpp +index 926cfa9..8968b59 100644 +--- a/tmp/source_release/adobe/vector.hpp ++++ b/tmp/source_release/adobe/vector.hpp @@ -319,7 +319,7 @@ void vector::append_move(I f, I l, std::forward_iterator_tag) size_type n(std::distance(f, l)); @@ -45,6 +104,24 @@ index 2d23e59..8968b59 100644 } template +@@ -354,7 +354,7 @@ typename vector::iterator vector::insert(iterator p, I f, I l, std:: + + if (n < after) { + append_move(last - n, last); +- move_backward(p, last - n, last); ++ adobe::move_backward(p, last - n, last); + std::copy(f, l, p); + } else { + I m = f; +@@ -387,7 +387,7 @@ typename vector::iterator vector::insert_move(iterator p, I f, I l) + + if (n < after) { + append_move(last - n, last); +- move_backward(p, last - n, last); ++ adobe::move_backward(p, last - n, last); + adobe::move(f, l, p); + } else { + I m = f; @@ -406,7 +406,7 @@ void vector::reserve(size_type n) if (capacity() < n) { vector tmp; @@ -54,3 +131,12 @@ index 2d23e59..8968b59 100644 swap(tmp); } } +@@ -430,7 +430,7 @@ typename vector::iterator vector::insert(iterator p, size_type n, co + + if (n < after) { + append_move(last - n, last); +- move_backward(p, last - n, last); ++ adobe::move_backward(p, last - n, last); + std::fill_n(p, n, x); + } else { + std::uninitialized_fill_n(last, n - after, x); diff --git a/tmp/source_release/adobe/array.hpp b/tmp/source_release/adobe/array.hpp new file mode 100644 index 0000000..76e4205 --- /dev/null +++ b/tmp/source_release/adobe/array.hpp @@ -0,0 +1,48 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt + or a copy at http://stlab.adobe.com/licenses.html) +*/ + +/**************************************************************************************************/ + +#ifndef ADOBE_ARRAY_HPP +#define ADOBE_ARRAY_HPP + +#include + +#include + +#include +#include +#include + +/**************************************************************************************************/ + +namespace adobe { +namespace version_1 { + +/**************************************************************************************************/ + +template // T models Regular +inline void push_back(array_t& v, T x) +{ v.push_back(any_regular_t(adobe::move(x))); } + +inline void push_back(array_t& v, any_regular_t x) +{ v.push_back(adobe::move(x)); } + +/**************************************************************************************************/ + +} // namespace version_1 + +using version_1::push_back; + +} // namespace adobe + +/**************************************************************************************************/ + +ADOBE_SHORT_NAME_TYPE('a','r','r','y', adobe::array_t) + +/**************************************************************************************************/ + +#endif diff --git a/tmp/source_release/adobe/move.hpp b/tmp/source_release/adobe/move.hpp new file mode 100644 index 0000000..5fe6db5 --- /dev/null +++ b/tmp/source_release/adobe/move.hpp @@ -0,0 +1,491 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt + or a copy at http://stlab.adobe.com/licenses.html) +*/ + +/*************************************************************************************************/ + +#ifndef ADOBE_MOVE_HPP +#define ADOBE_MOVE_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*! +\defgroup move_related Move Library +\ingroup utility +\brief +The move library is a collection of utilities for creating and using types that leverage +return value optimization (RVO) to avoid unnecessary copies. + +\section move_tutorial Tutorial +User defined types often have remote parts either because they are implemented using a +pointer-to-implementation or are variable sized. Such objects can be expensive to copy +and are often copied unnecessarily when they are returned from functions or stored in other +objects or containers. The \ref move_related is a collection of utilities to implement types which +can be moved to elide copying in such situations as well as utilities to assist in moving value. + +\par Implementing a Movable Type + +A movable type models \ref concept_movable. There are three components of a movable type: + - Satisfy the requirements of concept \ref concept_regular_type. + - Implement a move-ctor using move_from<>. + - Modify the assignment operator to take the operand by value and consume it. + +A typical implementation of the move-ctor will simply extract the remote part, leaving the +source in a destructible state. + +The assignment operator takes the operand parameter by value. Typically the simplest way +to destory the local remote part and consume the remote part of the operand is to swap +contents with the operand. This is similar to the copy-ctor and swap idiom for implementing +assignment. + +Listing 1 shows an example movable class that implements a typical pointer-to-implementation +(PiPl) idiom and shows that it can be used as any regular type. + +\code +#include +#include + +#include + +#include + +using std::swap; + +struct implementation : boost::equality_comparable +{ + explicit implementation(int x = 0) : member(x) { } + + implementation(const implementation& x) : member(x.member) + { std::cout << "copy remote part: " << member << std::endl; } + + implementation& operator=(const implementation& x) + { + member = x.member; + std::cout << "assign remote part: " << member << std::endl; + return *this; + } + + friend bool operator==(const implementation& x, const implementation& y) + { return x.member == y.member; } + + int member; +}; + +class movable : public boost::equality_comparable +{ + public: +// model concept Regular + + explicit movable(int x = 0) : member(new implementation(x)) { } + ~movable() { delete member; } + movable(const movable& x) : member(new implementation(*x.member)) { } + // operator=() implemented below + + friend bool operator==(const movable& x, const movable &y) + { return *x.member == *y.member; } + + friend void swap(movable& x, movable& y) + { swap(x.member, y.member); } + +// model concept Movable + + // move-ctor assumes ownership of remote part + movable(adobe::move_from x) : member(x.source.member) + { x.source.member = 0; } + + // operator=() on a movable type takes parameter by value and consumes it + movable& operator=(movable x) + { swap(*this, x); return *this; } + + private: + implementation* member; +}; + +int main() +{ + movable x(10); + movable y = x; + + return 0; +} +\endcode +
Listing 1
+ +\verbatim +copy remote part: 10 +\endverbatim +
Output of Listing 1
+ +\par Returning a Movable Type + +We can return a movable type from a function by value and unnessary copies will be avoided as +Listing 2 illustrates: + +\code +//... +movable f(int x, int y) +{ return movable(x * y); } + +int main() +{ + movable x = f(10, 5); + movable y; + y = f(4, 3); + + return 0; +} +\endcode +
Listing 2
+ +\verbatim + +\endverbatim +
Ouput of Listing 2
+ +In this example it is not necessary to make any copies. The result of f() is constructed directly +in place for x through a compiler optimization known as return value optimization or RVO. In the +case of assigning to y, the same optimization allows the compiler to construct the operand for +assignment as the result of f() which is them moved into y. + +\par Implementing a Sink Function + +A sink is any function that copies it's argument, usually for the purpose of storing it. +A sink is often a constructor or an insert function on a container. The \c operator=() on a movable +type is a form of a sink function. To implement a sink function pass the argument by value and then +use \c adobe::move() to move the argument into place. Note that this technique cannot be used to +implement \c operator=() on because it relies on assignment. Listing 3 implements an example sink +function. + +\code +//... + +struct sink +{ + explicit sink(movable x) : member(adobe::move(x)) { } + + movable member; +}; + +int main() +{ + movable x = f(10, 5); + sink y(x); // must copy. + sink z(f(20, 2)); // no copy. + + return 0; +} +\endcode +
Listing 3
+ +\verbatim +copy remote part: 50 +\endverbatim +
Output of Listing 3
+ +Here again unnessary copies are eliminated. Although adobe::move() can be used anytime to force the +move of an object, it should only be used as part of an explicit sink function otherwise it hinders +the understanding of code. + +\par Utilities + +There are many utilities as part of the move library which can be used to move elements instead of +copying them. These are useful when building containers or dealing with sink operations which must +manage a collection of movable objects. Generally these operations parallel the associated copying +algorithms from STL. Examples: + + + + + + + + + +
MoveCopyComment
adobe::move()std::copyNot to be confused with the single argument adobe::move()
adobe::move_backward()std::copy_backward
adobe::back_move_iterator()std::back_insert_iterator
adobe::back_mover()std::back_inserter
adobe::move_construct()std::construct
adobe::uninitialized_move()std::uninitialized_copy
+ +\par Advanced Topics + +The \c adobe::move() function is a NOP if the argument is not movable, however, when a non-movable +item is passed to a sink this may still result in an unnecessary copy - one to the sink and one to +copy the argument of the sink into place. To avoid the additional copy, two forms of a sink function +can be provided, one for movable types and one for copyable types. The \c adobe::move_sink<> and +\c adobe::copy_sink<> tags can be used to select between the two functions. See the +implementation of \c adobe::move_construct() as an example. + +If a sink function is a member of a template class, the same issue with regard to unnecessary copies +can occur. In this case, it is desirable to distinguish between the a copy and move sink as above +but also to allow implicit conversions to the type stored in the container. To allow this use the +two argument form of \c adobe::move_sink<> and \c adobe::copy_sink<>. See the implementation of +\c adobe::vector::push_back() as an example. + +\par Theory of Operation + +to be written + +\par Acknowledgments: +The move library was inspired by the move library written by Dave Abrahams and the work on move +done by Dave Abrahams and Howard Hinnant. +*/ + +/*************************************************************************************************/ + +namespace adobe { + +/*************************************************************************************************/ + +namespace implementation { + +/*************************************************************************************************/ + +template +struct class_has_move_assign { + class type { + typedef T& (T::*E)(T t); + typedef char (&no_type)[1]; + typedef char (&yes_type)[2]; + template struct sfinae { typedef yes_type type; }; + template + static typename sfinae<&U::operator=>::type test(int); + template + static no_type test(...); + public: + enum {value = sizeof(test(1)) == sizeof(yes_type)}; + }; + }; + +/*************************************************************************************************/ + +template +struct has_move_assign : boost::mpl::and_, class_has_move_assign > {}; + +/*************************************************************************************************/ + +class test_can_convert_anything { }; + +/*************************************************************************************************/ + +} //namespace implementation + + +/*************************************************************************************************/ + +/* + REVISIT (sparent@adobe.com): This is a work around for Boost 1.34.1 and VC++ 2008 where + boost::is_convertible fails to compile. +*/ + +template +struct is_convertible : boost::mpl::or_< + boost::is_same, + boost::is_convertible +> { }; + +/*! +\ingroup move_related +\brief move_from is used for move_ctors. +*/ + +template +struct move_from +{ + explicit move_from(T& x) : source(x) { } + T& source; +}; + +/*! +\ingroup move_related +\brief The is_movable trait can be used to identify movable types. +*/ +template +struct is_movable : boost::mpl::and_< + boost::is_convertible, T>, + implementation::has_move_assign, + boost::mpl::not_ > + > { }; + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief copy_sink and move_sink are used to select between overloaded operations according to + whether type T is movable and convertible to type U. +\sa move +*/ + +template +struct copy_sink : boost::enable_if< + boost::mpl::and_< + adobe::is_convertible, + boost::mpl::not_ > + >, + R + > +{ }; + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief move_sink and copy_sink are used to select between overloaded operations according to + whether type T is movable and convertible to type U. + \sa move +*/ + +template +struct move_sink : boost::enable_if< + boost::mpl::and_< + adobe::is_convertible, + is_movable + >, + R + > +{ }; + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief This version of move is selected when T is_movable . It in turn calls the move +constructor. This call, with the help of the return value optimization, will cause x to be moved +instead of copied to its destination. See adobe/test/move/main.cpp for examples. + +*/ +template +T move(T& x, typename move_sink::type = 0) { return T(move_from(x)); } + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief This version of move is selected when T is not movable . The net result will be that +x gets copied. +*/ +template +T& move(T& x, typename copy_sink::type = 0) { return x; } + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief Iterator pair version of move. Similar to std::copy but with move semantics, +for movable types, otherwise with copy semantics. +*/ +template // O models OutputIterator +O move(I f, I l, O result) +{ + while (f != l) { + *result = adobe::move(*f); + ++f; ++result; + } + return result; +} + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief \ref concept_convertible_to_range version of move. Similar to copy but with move semantics, +for movable types, otherwise with copy semantics. +*/ +template // O models OutputIterator +inline O move(I& in, O out) { return adobe::move(boost::begin(in), boost::end(in), out); } + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief Iterator pair version of move_backwards. Similar to std::copy_backwards but with move semantics, +for movable types, otherwise with copy semantics. +*/ +template // O models BidirectionalIterator +O move_backward(I f, I l, O result) +{ + while (f != l) { + --l; --result; + *result = adobe::move(*l); + } + return result; +} + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief \ref concept_convertible_to_range version of move_backwards. Similar to std::copy_backwards but +with move semantics, for movable types, otherwise with copy semantics. +*/ +template // O models BidirectionalIterator +inline O move_backward(I& in, O out) +{ return adobe::move_backward(boost::begin(in), boost::end(in), out); } + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief Similar to std::back_insert_iterator but +with move semantics, for movable types, otherwise with copy semantics. +*/ + +template // C models Container +class back_move_iterator : public std::iterator +{ + C* container_m; + + public: + typedef C container_type; + + explicit back_move_iterator(C& x) : container_m(&x) { } + + back_move_iterator& operator=(typename C::value_type x) + { container_m->push_back(adobe::move(x)); return *this; } + + back_move_iterator& operator*() { return *this; } + back_move_iterator& operator++() { return *this; } + back_move_iterator& operator++(int) { return *this; } +}; + +/*************************************************************************************************/ + +/*! +\ingroup move_related +\brief Similar to std::back_inserter but +with move semantics, for movable types, otherwise with copy semantics. +*/ + +template // C models Container +inline back_move_iterator back_mover(C& x) { return back_move_iterator(x); } + +/*************************************************************************************************/ + +} // namespace adobe + +/*************************************************************************************************/ + +#endif + +/*************************************************************************************************/ diff --git a/tmp/source_release/adobe/once.hpp b/tmp/source_release/adobe/once.hpp new file mode 100644 index 0000000..e349b92 --- /dev/null +++ b/tmp/source_release/adobe/once.hpp @@ -0,0 +1,176 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt + or a copy at http://stlab.adobe.com/licenses.html) +*/ + +/*************************************************************************************************/ + +#ifndef ADOBE_ONCE_HPP +#define ADOBE_ONCE_HPP + +/*************************************************************************************************/ + +#if defined(BOOST_HAS_THREADS) + #include +#endif + +#include + +/*************************************************************************************************/ + +namespace adobe { + +/*************************************************************************************************/ + +#if defined(BOOST_HAS_THREADS) + +/*************************************************************************************************/ + +typedef boost::once_flag once_flag; +#define ADOBE_ONCE_INIT BOOST_ONCE_INIT + +inline void call_once(void (*func)(), adobe::once_flag& flag) +{ + boost::call_once(func, flag); +} + +/*************************************************************************************************/ + +#else + +/*************************************************************************************************/ + +typedef bool once_flag; +#define ADOBE_ONCE_INIT false + +inline void call_once(void (*func)(), adobe::once_flag& flag) +{ + if (!flag) + { + (*func)(); + flag = true; + } +} + +/*************************************************************************************************/ + +#endif + +/*************************************************************************************************/ + +} // namespace adobe + +/*************************************************************************************************/ + +#define ADOBE_ONCE_DECLARATION(signature) \ + struct adobe_initialize_constants_##signature##_t \ + { \ + adobe_initialize_constants_##signature##_t(); \ + }; + +#define ADOBE_ONCE_DEFINITION(signature, func) \ + namespace { \ + adobe::once_flag adobe_once_flag_##signature##_s = ADOBE_ONCE_INIT; \ + } \ + adobe_initialize_constants_##signature##_t::adobe_initialize_constants_##signature##_t() \ + { \ + adobe::call_once(&func, adobe_once_flag_##signature##_s); \ + } + +#define ADOBE_ONCE_INSTANCE(signature) \ + adobe_initialize_constants_##signature##_t adobe_initialize_constants_##signature##_s + +#define ADOBE_ONCE_STATIC_INSTANCE(signature) \ + namespace { ADOBE_ONCE_INSTANCE(signature); } + +#if defined(BOOST_HAS_THREADS) + +#define ADOBE_GLOBAL_MUTEX_DEFINITION(signature) \ + namespace { \ + adobe::once_flag adobe_once_flag_##signature##_s = ADOBE_ONCE_INIT; \ + boost::mutex* adobe_mutex_ptr_##signature##_s = 0; \ + void adobe_init_once_##signature() \ + { \ + static boost::mutex mutex_s; \ + adobe_mutex_ptr_##signature##_s = &mutex_s; \ + } \ + } + +#define ADOBE_GLOBAL_MUTEX_INSTANCE(signature) \ + boost::call_once(&adobe_init_once_##signature, adobe_once_flag_##signature##_s); \ + boost::mutex::scoped_lock lock(*adobe_mutex_ptr_##signature##_s) + +#else + +#define ADOBE_GLOBAL_MUTEX_DEFINITION(signature) +#define ADOBE_GLOBAL_MUTEX_INSTANCE(signature) + +#endif + +/*************************************************************************************************/ + +#if defined(BOOST_HAS_THREADS) + +#define ADOBE_THREAD_LOCAL_STORAGE_1(type, signature, ctor_p1) \ + namespace { \ + typedef boost::thread_specific_ptr< type > adobe_thread_local_storage_##signature##_t; \ + adobe_thread_local_storage_##signature##_t* adobe_thread_local_storage_##signature##_g = 0;\ + type& adobe_thread_local_storage_##signature##_access(); \ + type& adobe_thread_local_storage_##signature##_access() \ + { \ + type* result = adobe_thread_local_storage_##signature##_g->get(); \ + if (result) return *result; \ + result = new type(ctor_p1); \ + adobe_thread_local_storage_##signature##_g->reset(result); \ + return *result; \ + } } + +#define ADOBE_THREAD_LOCAL_STORAGE(type, signature) \ + namespace { \ + typedef boost::thread_specific_ptr< type > adobe_thread_local_storage_##signature##_t; \ + adobe_thread_local_storage_##signature##_t* adobe_thread_local_storage_##signature##_g = 0;\ + type& adobe_thread_local_storage_##signature##_access(); \ + type& adobe_thread_local_storage_##signature##_access() \ + { \ + type* result = adobe_thread_local_storage_##signature##_g->get(); \ + if (result) return *result; \ + result = new type(); \ + adobe_thread_local_storage_##signature##_g->reset(result); \ + return *result; \ + } } + +#define ADOBE_THREAD_LOCAL_STORAGE_INITIALIZE(signature) \ + static adobe_thread_local_storage_##signature##_t adobe_thread_local_storage_##signature##_s; \ + adobe_thread_local_storage_##signature##_g = &adobe_thread_local_storage_##signature##_s + +#else + +#define ADOBE_THREAD_LOCAL_STORAGE_1(type, signature, ctor_p1) \ + type& adobe_thread_local_storage_##signature##_access(); \ + type& adobe_thread_local_storage_##signature##_access() \ + { \ + static type adobe_thread_local_storage_##signature##_s(ctor_p1); \ + return adobe_thread_local_storage_##signature##_s; \ + } + +#define ADOBE_THREAD_LOCAL_STORAGE(type, signature) \ + type& adobe_thread_local_storage_##signature##_access(); \ + type& adobe_thread_local_storage_##signature##_access() \ + { \ + static type adobe_thread_local_storage_##signature##_s; \ + return adobe_thread_local_storage_##signature##_s; \ + } + +#define ADOBE_THREAD_LOCAL_STORAGE_INITIALIZE(signature) + +#endif + +#define ADOBE_THREAD_LOCAL_STORAGE_ACCESS(signature) \ + adobe_thread_local_storage_##signature##_access() + +/*************************************************************************************************/ + +#endif // ADOBE_ONCE_HPP + +/*************************************************************************************************/ diff --git a/tmp/source_release/adobe/vector.hpp b/tmp/source_release/adobe/vector.hpp new file mode 100644 index 0000000..8968b59 --- /dev/null +++ b/tmp/source_release/adobe/vector.hpp @@ -0,0 +1,520 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt + or a copy at http://stlab.adobe.com/licenses.html) +*/ + +/*************************************************************************************************/ + +#ifndef ADOBE_VECTOR_HPP +#define ADOBE_VECTOR_HPP + +/*************************************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef ADOBE_STD_SERIALIZATION +#include +#endif + +/*************************************************************************************************/ + +namespace adobe { +namespace version_1 { + +/*! +\defgroup container Containers +\ingroup asl_libraries + */ + + +/*************************************************************************************************/ + +//!\ingroup abi_container +template // A models Allocator(T) +class vector : boost::totally_ordered, vector > +{ + public: + typedef T& reference; + typedef const T& const_reference; + typedef T* iterator; + typedef const T* const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef A allocator_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + private: + struct header_t + { + struct compact_header_t + { + boost::compressed_pair allocate_finish_m; + T* end_of_storage_m; + }; + aligned_storage header_m; + T storage_m[1]; + + allocator_type& allocator() { return header_m.get().allocate_finish_m.first(); } + const allocator_type& allocator() const { return header_m.get().allocate_finish_m.first(); } + + pointer& finish() { return header_m.get().allocate_finish_m.second(); } + const pointer& finish() const { return header_m.get().allocate_finish_m.second(); } + + pointer& end_of_storage() { return header_m.get().end_of_storage_m; } + const pointer& end_of_storage() const { return header_m.get().end_of_storage_m; } + }; + + header_t* header_m; + + void set_finish(T* x) + { + assert(header_m != 0 || x == 0); + if (header_m) header_m->finish() = x; + } + + const T* end_of_storage() const { return header_m ? header_m->end_of_storage() : 0; } + + static header_t* allocate(allocator_type, std::size_t); + + size_type remaining() const { return end_of_storage() - end(); } + + template // I models InputIterator + void append(I f, I l) { append(f, l, typename std::iterator_traits::iterator_category()); } + + template // I models InputIterator + void append(I f, I l, std::input_iterator_tag); + + template // I models ForwardIterator + void append(I f, I l, std::forward_iterator_tag); + + template // I models InputIterator + void append_move(I f, I l) + { append_move(f, l, typename std::iterator_traits::iterator_category()); } + + template // I models InputIterator + void append_move(I f, I l, std::input_iterator_tag); + + template // I models ForwardIterator + void append_move(I f, I l, std::forward_iterator_tag); + + template // I models InputIterator + iterator insert(iterator p, I f, I l, std::input_iterator_tag); + + template // I models ForwardIterator + iterator insert(iterator p, I f, I l, std::forward_iterator_tag); + + public: + // 23.2.4.1 construct/copy/destroy + + explicit vector(const allocator_type& a) : header_m(allocate(a, 0)) { } + vector() : header_m(0) { } + + explicit vector(size_type n) : header_m(allocate(allocator_type(), n)) + { + std::uninitialized_fill_n(end(), n, value_type()); + set_finish(end() + n); + } + + vector(size_type n, const value_type& x) : header_m(allocate(allocator_type(), n)) + { + std::uninitialized_fill_n(end(), n, x); + set_finish(end() + n); + } + + vector(size_type n, const value_type& x, const allocator_type& a) : header_m(allocate(a, n)) + { + std::uninitialized_fill_n(end(), n, x); + set_finish(end() + n); + } + + vector(const vector& x) : header_m(allocate(x.get_allocator(), x.size())) + { +#ifndef NDEBUG + /* REVISIT (sparent) : MS stupid "safety check" doesn't known about empty ranges. */ + set_finish(x.begin() == x.end() ? end() : std::uninitialized_copy(x.begin(), x.end(), end())); +#else + set_finish(std::uninitialized_copy(x.begin(), x.end(), end())); +#endif + } + + template // I models InputIterator + vector(I f, I l, typename boost::disable_if >::type* = 0) : header_m(0) + { append(f, l); } + + template // I models InputIterator + vector(I f, I l, const allocator_type& a, + typename boost::disable_if >::type* = 0) : header_m(allocate(a), 0) + { append(f, l); } + + ~vector() { + if (header_m) { + clear(); + + typename allocator_type::template rebind::other alloc(get_allocator()); + alloc.deallocate(reinterpret_cast(header_m), + (end_of_storage() - begin()) * sizeof(T) + (sizeof(header_t) - sizeof(T))); + } + } + + // adobe addition + + vector(move_from x) : header_m(x.source.header_m) { x.source.header_m = 0; } + + allocator_type get_allocator() const + { return header_m ? header_m->allocator() : allocator_type(); } + + iterator begin() { return header_m ? &header_m->storage_m[0] : 0; } + iterator end() { return header_m ? header_m->finish() : 0; } + + const_iterator begin() const { return header_m ? &header_m->storage_m[0] : 0; } + const_iterator end() const { return header_m ? header_m->finish() : 0; } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + size_type size() const { return size_type(end() - begin()); } + size_type max_size() const { return size_type(-1) / sizeof(value_type); } + + size_type capacity() const { return size_type(end_of_storage() - begin()); } + bool empty() const { return begin() == end(); } + + reference operator[](size_type n) { assert(n < size()); return *(begin() + n); } + const_reference operator[](size_type n) const { assert(n < size()); return *(begin() + n); } + + /* + REVISIT (sparent@adobe.com): at() explicitly omitted because it pulls in out_of_range + which inherits from logic_error and uses std::string. + */ + + vector& operator=(vector x) { swap(x); return *this; } + + void reserve(size_type n); + + reference front() { assert(!empty()); return *begin(); } + const_reference front() const { assert(!empty()); return *begin(); } + + reference back() { assert(!empty()); return *(end() - 1); } + const_reference back() const { assert(!empty()); return *(end() - 1); } + + void push_back(value_type x) + { append_move(&x, &x + 1); } + + void pop_back() { assert(!empty()); resize(size() - 1); } + + void swap(vector& x) { std::swap(header_m, x.header_m); } + + iterator insert(iterator p, value_type x) + { return insert_move(p, &x, &x + 1); } + + template // I models InputIterator + iterator insert(iterator p, I f, I l, typename boost::disable_if >::type* = 0) + { return insert(p, f, l, typename std::iterator_traits::iterator_category()); } + + template // I models ForwardIterator + iterator insert_move(iterator p, I f, I l); + + iterator insert(iterator p, size_type n, const T& x); + + iterator erase(iterator pos) { assert(pos != end()); return erase(pos, pos + 1); } + + iterator erase(iterator f, iterator l); + + void clear() { erase(begin(), end()); } + + void resize(size_type n); + + void resize(size_type n, const value_type& x); + + friend inline bool operator==(const vector& x, const vector& y) + { +#if defined(_MSC_VER) && _MSC_VER == 1600 && _ITERATOR_DEBUG_LEVEL != 0 + return (x.size() == y.size()) && std::_Equal1(x.begin(), x.end(), + y.begin(), std::tr1::false_type()); +#else + return (x.size() == y.size()) && std::equal(x.begin(), x.end(), y.begin()); +#endif + } + + friend inline bool operator<(const vector& x, const vector& y) + { + return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); + } + + friend inline void swap(vector& x, vector& y) { x.swap(y); } +}; + +template +typename vector::header_t* vector::allocate(allocator_type a, std::size_t n) +{ + if (n == 0) { + if (a == allocator_type()) return 0; + n = 1; + } + + typename allocator_type::template rebind::other alloc(a); + + header_t* result = reinterpret_cast(alloc.allocate(sizeof(header_t) - sizeof(T) + + n * sizeof(T))); + construct(&result->allocator(), a); + result->finish() = &result->storage_m[0]; + result->end_of_storage() = result->finish() + n; + + return result; +} + +template +template // I models InputIterator +void vector::append(I f, I l, std::input_iterator_tag) { while (f != l) { push_back(*f); ++f; } } + +template +template // I models InputIterator +void vector::append_move(I f, I l, std::input_iterator_tag) +{ while (f != l) { push_back(adobe::move(*f)); ++f; } } + +template +template // I models ForwardIterator +void vector::append(I f, I l, std::forward_iterator_tag) +{ + size_type n(std::distance(f, l)); + + if (remaining() < n) reserve((adobe::max)(size() + n, 2 * size())); + set_finish(std::uninitialized_copy(f, l, end())); +} + +template +template // I models ForwardIterator +void vector::append_move(I f, I l, std::forward_iterator_tag) +{ + size_type n(std::distance(f, l)); + + if (remaining() < n) reserve((adobe::max)(size() + n, 2 * size())); + set_finish(adobe::uninitialized_move(f, l, end())); +} + +template +template // I models InputIterator +typename vector::iterator vector::insert(iterator p, I f, I l, std::input_iterator_tag) +{ + size_type o(p - begin()); + size_type s = size(); + append(f, l); + // REVISIT (sparent) : This could be a move based rotate + std::rotate(begin() + o, begin() + s, end()); + return end() - s + o; +} + +template +template // I models ForwardIterator +typename vector::iterator vector::insert(iterator p, I f, I l, std::forward_iterator_tag) +{ + size_type n(std::distance(f, l)); + iterator last = end(); + size_type before = p - begin(); + + if (remaining() < n) { + vector tmp; + tmp.reserve((adobe::max)(size() + n, 2 * size())); + tmp.append_move(begin(), p); + tmp.append(f, l); + tmp.append_move(p, last); + swap(tmp); + } else { + size_type after(last - p); + + if (n < after) { + append_move(last - n, last); + adobe::move_backward(p, last - n, last); + std::copy(f, l, p); + } else { + I m = f; + std::advance(m, after); + append(m, l); + append_move(p, last); + std::copy(f, m, p); + } + } + return begin() + before + n; +} + +template +template // I models ForwardIterator +typename vector::iterator vector::insert_move(iterator p, I f, I l) +{ + size_type n(std::distance(f, l)); + iterator last = end(); + size_type before = p - begin(); + + if (remaining() < n) { + vector tmp; + tmp.reserve((adobe::max)(size() + n, 2 * size())); + tmp.append_move(begin(), p); + tmp.append_move(f, l); + tmp.append_move(p, last); + swap(tmp); + } else { + size_type after(last - p); + + if (n < after) { + append_move(last - n, last); + adobe::move_backward(p, last - n, last); + adobe::move(f, l, p); + } else { + I m = f; + std::advance(m, after); + append_move(m, l); + append_move(p, last); + adobe::move(f, m, p); + } + } + return begin() + before + n; +} + +template +void vector::reserve(size_type n) +{ + if (capacity() < n) { + vector tmp; + tmp.header_m = allocate(get_allocator(), n); + tmp.header_m->finish() = adobe::uninitialized_move(begin(), end(), tmp.end()); + swap(tmp); + } +} + +template +typename vector::iterator vector::insert(iterator p, size_type n, const T& x) +{ + iterator last = end(); + size_type before = p - begin(); + + if (remaining() < n) { + vector tmp; + tmp.reserve((adobe::max)(size() + n, 2 * size())); + tmp.append_move(begin(), p); + std::uninitialized_fill_n(tmp.end(), n, x); + tmp.set_finish(tmp.end() + n); + tmp.append_move(p, last); + swap(tmp); + } else { + size_type after(last - p); + + if (n < after) { + append_move(last - n, last); + adobe::move_backward(p, last - n, last); + std::fill_n(p, n, x); + } else { + std::uninitialized_fill_n(last, n - after, x); + set_finish(last + (n - after)); + append_move(p, last); + std::fill_n(p, after, x); + } + } + return begin() + before + n; +} + +template +typename vector::iterator vector::erase(iterator f, iterator l) +{ + iterator i = adobe::move(l, end(), f); + for (iterator b(i), e(end()); b != e; ++b) { + b->~value_type(); + } + set_finish(i); + return f; +} + +template +void vector::resize(size_type n) +{ + if (n < size()) erase(begin() + n, end()); + else insert(end(), n - size(), value_type()); +} + +template +void vector::resize(size_type n, const value_type& x) +{ + if (n < size()) erase(begin() + n, end()); + else insert(end(), n - size(), x); +} + +/*************************************************************************************************/ + +#ifdef ADOBE_STD_SERIALIZATION + +template +std::ostream& operator<<(std::ostream& out, const vector& x) +{ + out << begin_sequence; + + for (typename vector::const_iterator first(x.begin()), last(x.end()); first != last; ++first) + { + out << format(*first); + } + + out << end_sequence; + + return out; +} + +#endif + +/*************************************************************************************************/ + +BOOST_STATIC_ASSERT(sizeof(vector) == sizeof(void*)); + +/*************************************************************************************************/ + +} // namespace version_1 +} // namespace adobe + +/*************************************************************************************************/ + +ADOBE_NAME_TYPE_1("vector:version_1:adobe", adobe::version_1::vector >) +ADOBE_NAME_TYPE_2("vector:version_1:adobe", adobe::version_1::vector) + +/*************************************************************************************************/ + +namespace boost { + +template +struct has_nothrow_constructor > : boost::mpl::true_ { }; + +} // namespace boost + +/*! +@} +*/ +/*************************************************************************************************/ + +#endif