Thread: [Assorted-commits] SF.net SVN: assorted:[1082] cpp-commons/trunk
Brought to you by:
yangzhang
From: <yan...@us...> - 2008-12-02 05:34:29
|
Revision: 1082 http://assorted.svn.sourceforge.net/assorted/?rev=1082&view=rev Author: yangzhang Date: 2008-12-02 05:34:16 +0000 (Tue, 02 Dec 2008) Log Message: ----------- - migrated to boost 1.37 - fixed some check calls - added printf format attributes to check functions - fixed format specifiers/typing by using stringstream/lexical_cast - updated and published the README Modified Paths: -------------- cpp-commons/trunk/README cpp-commons/trunk/src/commons/boost/delegates.h cpp-commons/trunk/src/commons/check.h cpp-commons/trunk/src/commons/die.h cpp-commons/trunk/src/commons/sockets.h cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/README =================================================================== --- cpp-commons/trunk/README 2008-11-30 23:46:31 UTC (rev 1081) +++ cpp-commons/trunk/README 2008-12-02 05:34:16 UTC (rev 1082) @@ -6,33 +6,43 @@ -------- The C++ Commons is a general-purpose utility library for the C++ programming -language. The library is nascent, so it doesn't have enough to warrant a -release. This is a library of header files, in the same spirit as [boost]. +language. This is a library of header files, in the same spirit as [boost]. Here are some of the features present in the library: -- check macros (assertions that aren't meant to be removed in releases) +- C functions for string manipulation - RAII utilities, such as for closing file descriptors -- low-level system information from cpuid +- `array`: thin wrapper around arrays (`scoped_array` + size) +- `pool`: fixed-size object pools +- bit manipulation +- bundles of header includes +- C++ support for pthreads, but allowing the user to access the underlying + `pthread_t` (a major annoyance of using boost threads was its complete + encapsulation) +- C++ support for [State Threads] +- check macros (like assertions but never removed from compilation) +- `deque`: simpler deque implementation that uses coarse-grained allocation +- error handling, such as `die()`, which leverages `strerror` - file I/O utilities, such as reading complete files +- function delegates (for use with C functions that take `(void*)(void*)`) - hash functions +- low-level system information from `cpuid` +- `nullptr`: from C++0x - pseudo-random number generators -- error handling, such as `die()` -- function delegates (for use with C functions that take `(void*)(void*)`) -- region-based allocation -- bundles of header includes +- region-based memory management - socket utilities -- C functions for string manipulation -- bit manipulation -- C++ support for pthreads, but allowing the user to access the underlying - `pthread_t` (a major annoyance of using boost threads was its complete - encapsulation) - portable re-implementations of pthread primitives such as barriers -- C++ support for [State Threads] +- time utilities, including timers and simpler interfaces to system clocks +- utilities for streams - utilities for [tamer] +- x86 architecture-specific tools -[State Threads]: http://state-threads.sourceforge.net/ +Setup +----- +Like [boost], just include these header files in your next C++ project, and +you're ready to go! + Related Work ------------ Modified: cpp-commons/trunk/src/commons/boost/delegates.h =================================================================== --- cpp-commons/trunk/src/commons/boost/delegates.h 2008-11-30 23:46:31 UTC (rev 1081) +++ cpp-commons/trunk/src/commons/boost/delegates.h 2008-12-02 05:34:16 UTC (rev 1082) @@ -14,7 +14,7 @@ void swallow(const function0<void> f) { try { f(); } - catch (exception &ex) { cerr << ex.what() << endl; } + catch (std::exception &ex) { cerr << ex.what() << endl; } } /** @@ -45,7 +45,7 @@ // run_function0_ex(void* p) // { // try { run_function0(p); } -// catch (exception &ex) { return exception(ex); } +// catch (std::exception &ex) { return std::exception(ex); } // } } Modified: cpp-commons/trunk/src/commons/check.h =================================================================== --- cpp-commons/trunk/src/commons/check.h 2008-11-30 23:46:31 UTC (rev 1081) +++ cpp-commons/trunk/src/commons/check.h 2008-12-02 05:34:16 UTC (rev 1082) @@ -5,6 +5,7 @@ #include <sstream> #include <string> #include <commons/die.h> +#include <boost/lexical_cast.hpp> // TODO: rename: // - chk(x): verifies and return x; if not, throw strerror @@ -31,9 +32,10 @@ // TODO: provide strerror in other functions too // TODO: better way to deal with errno? (rather than resetting it) + using namespace boost; using namespace std; - class check_exception : public exception + class check_exception : public std::exception { public: check_exception(const string & name) : name(name) {} @@ -43,7 +45,7 @@ const string name; }; - inline void + __attribute__((format(printf, 4, 0))) inline void _vcheck(bool cond, const char *file, int line, const char *fmt, va_list ap) { if (!cond) { @@ -58,7 +60,7 @@ } } - inline void + __attribute__((format(printf, 4, 5))) inline void _check(bool cond, const char *file, int line, const char *fmt, ...) { va_list ap; @@ -104,7 +106,8 @@ if (!x) { int e = errno; errno = 0; - _check(x, file, line, "expecting !=0, got %d: %s", x, strerror(e)); + _check(x, file, line, "expecting !=0, got %s: %s", + lexical_cast<string>(x).c_str(), strerror(e)); } return x; } @@ -130,7 +133,7 @@ if (l != r) { stringstream ss; ss << "expecting " << l << " == " << r; - _check(false, file, line, ss.str().c_str()); + _check(false, file, line, "%s", ss.str().c_str()); } } @@ -140,8 +143,9 @@ if (l < 0) { int e = errno; errno = 0; - _check(l == r, file, line, - "expecting %d, got %d: %s", r, l, strerror(e)); + stringstream ss; + ss << "expecting " << r << ", got " << l << ": " << strerror(e); + _check(l == r, file, line, "%s", ss.str().c_str()); } else { _checkeq(l, r, file, line); } Modified: cpp-commons/trunk/src/commons/die.h =================================================================== --- cpp-commons/trunk/src/commons/die.h 2008-11-30 23:46:31 UTC (rev 1081) +++ cpp-commons/trunk/src/commons/die.h 2008-12-02 05:34:16 UTC (rev 1082) @@ -15,7 +15,7 @@ * * TODO: move into C Commons. */ - void + __attribute__((format(printf, 1, 2))) void die(const char *format, ...) { const char *errstr; Modified: cpp-commons/trunk/src/commons/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/sockets.h 2008-11-30 23:46:31 UTC (rev 1081) +++ cpp-commons/trunk/src/commons/sockets.h 2008-12-02 05:34:16 UTC (rev 1082) @@ -46,7 +46,7 @@ sa.sin_addr.s_addr = htonl(INADDR_ANY); // Bind the socket to the local socket address. - check0x(bind(fd, (sockaddr*) &sa, sizeof sa)); + check0x(::bind(fd, (sockaddr*) &sa, sizeof sa)); return fd; } catch (...) { Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2008-11-30 23:46:31 UTC (rev 1081) +++ cpp-commons/trunk/src/commons/st/st.h 2008-12-02 05:34:16 UTC (rev 1082) @@ -100,7 +100,7 @@ sa.sin_addr = host; // Create the socket. - int sfd = checknneg(socket(PF_INET, SOCK_STREAM, 0)); + int sfd = checknnegerr(socket(PF_INET, SOCK_STREAM, 0)); st_netfd_t nfd = st_netfd_open_socket(sfd); // Connect. @@ -108,7 +108,7 @@ check0x(st_connect(nfd, (sockaddr*) &sa, sizeof sa, timeout)); return nfd; } catch (...) { - st_netfd_close(nfd); + check0x(st_netfd_close(nfd)); throw; } } @@ -313,17 +313,17 @@ st_intr_hub &hub_; }; - class st_group_join_exception : public exception + class st_group_join_exception : public std::exception { public: - st_group_join_exception(const map<st_thread_t, exception> &th2ex) : + st_group_join_exception(const map<st_thread_t, std::exception> &th2ex) : th2ex_(th2ex) {} virtual ~st_group_join_exception() throw() {} virtual const char *what() const throw() { if (!th2ex_.empty() && s == "") { bool first = true; stringstream ss; - typedef pair<st_thread_t, exception> p; + typedef pair<st_thread_t, std::exception> p; foreach (p p, th2ex_) { ss << (first ? "" : ", ") << p.first << " -> " << p.second.what(); first = false; @@ -333,7 +333,7 @@ return s.c_str(); } private: - map<st_thread_t, exception> th2ex_; + map<st_thread_t, std::exception> th2ex_; string s; }; @@ -357,10 +357,10 @@ { public: ~st_thread_group() { - map<st_thread_t, exception> th2ex; + map<st_thread_t, std::exception> th2ex; foreach (st_thread_t t, ts) { try { st_join(t); } - catch (exception &ex) { th2ex[t] = ex; } + catch (std::exception &ex) { th2ex[t] = ex; } } if (!th2ex.empty()) throw st_group_join_exception(th2ex); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-06 00:40:04
|
Revision: 1168 http://assorted.svn.sourceforge.net/assorted/?rev=1168&view=rev Author: yangzhang Date: 2009-02-06 00:39:52 +0000 (Fri, 06 Feb 2009) Log Message: ----------- - use shared ptrs in st_multichannel - added overload randint(min,max) - tweaked README Modified Paths: -------------- cpp-commons/trunk/README cpp-commons/trunk/src/commons/rand.h cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/README =================================================================== --- cpp-commons/trunk/README 2009-02-06 00:36:31 UTC (rev 1167) +++ cpp-commons/trunk/README 2009-02-06 00:39:52 UTC (rev 1168) @@ -11,7 +11,7 @@ Here are some of the features present in the library: - C functions for string manipulation -- RAII utilities, such as for closing file descriptors +- RAII utilities, such as for closing file descriptors and `finally` objects - `array`: thin wrapper around arrays (`scoped_array` + size) - `pool`: fixed-size object pools - bit manipulation Modified: cpp-commons/trunk/src/commons/rand.h =================================================================== --- cpp-commons/trunk/src/commons/rand.h 2009-02-06 00:36:31 UTC (rev 1167) +++ cpp-commons/trunk/src/commons/rand.h 2009-02-06 00:39:52 UTC (rev 1168) @@ -24,7 +24,7 @@ }; /** - * Generate a random int up to but excluding max. + * Generate a random int from 0 up to but excluding max. * \param[in] max Must be greater than one. */ inline int @@ -98,10 +98,20 @@ // // OK, this path isn't taking us anywhere. Let's go back to the original // formula. Sure, it exceeds max. But what if we just wrap it back around - // when it does? We can do so using %max. Success! + // when it does? We can do so using % max. Success! return static_cast<int>( random() / ( RAND_MAX / max ) % max ); } + + /** + * Use randint() to return a number in [min, max) if max > min + 1 (i.e. if + * there is more than one choice), otherwise return min. + */ + inline int + randint(int min, int max) + { + return max > min + 1 ? min + randint(max - min) : min; + } } #endif Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-06 00:36:31 UTC (rev 1167) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-06 00:39:52 UTC (rev 1168) @@ -189,6 +189,8 @@ bool b; }; + void toggle(st_bool& b) { if (b) b.reset(); else b.set(); } + /** * Wraps st_mutex_* errno-functions with exceptions and cleans up on * destruction. @@ -223,8 +225,9 @@ empty_.signal(); } T take() { - while (q_.empty()) + while (q_.empty()) { empty_.wait(); + } T x = front(); q_.pop(); return x; @@ -241,24 +244,23 @@ /** * An unbounded FIFO multi-cast channel, i.e. publish-subscribe. - * \todo Use shared_ptr. */ template <typename T> class st_multichannel { public: void push(const T &x) { - foreach (st_channel<T> *q, qs) { + foreach (shared_ptr<st_channel<T> > q, qs) { q->push(x); } } st_channel<T> &subscribe() { - st_channel<T>* q = new st_channel<T>; + shared_ptr<st_channel<T> > q(new st_channel<T>); qs.push_back(q); return *q; } private: - vector<st_channel<T>*> qs; + vector<shared_ptr<st_channel<T> > > qs; }; /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-22 06:49:49
|
Revision: 1219 http://assorted.svn.sourceforge.net/assorted/?rev=1219&view=rev Author: yangzhang Date: 2009-02-22 06:49:47 +0000 (Sun, 22 Feb 2009) Log Message: ----------- - moved a bunch of files around to get rid of the separation between boost-dependent and non-boost-dependent parts of the library - declared the library to require boost - removed libtask - updated the feature list - removed method_thread and other unnecessary thread utilities Modified Paths: -------------- cpp-commons/trunk/README cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/st/st.h cpp-commons/trunk/src/commons/threads.h Added Paths: ----------- cpp-commons/trunk/src/commons/delegates.h cpp-commons/trunk/src/commons/unique_ptr.hpp Removed Paths: ------------- cpp-commons/trunk/src/commons/boost/ cpp-commons/trunk/src/commons/task/ Modified: cpp-commons/trunk/README =================================================================== --- cpp-commons/trunk/README 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/README 2009-02-22 06:49:47 UTC (rev 1219) @@ -8,11 +8,13 @@ The C++ Commons is a general-purpose utility library for the C++ programming language. This is a library of header files, in the same spirit as [boost]. -Here are some of the features present in the library: +Features: - C functions for string manipulation - RAII utilities, such as for closing file descriptors and `finally` objects -- `array`: thin wrapper around arrays (`scoped_array` + size) +- smart arrays: sized arrays, "managed" (moveable, conditionally + scope-destroyed) arrays +- Howard Hinnant's C++03-emulated TR1 `unique_ptr.hpp` - `pool`: fixed-size object pools - bit manipulation - bundles of header includes @@ -35,14 +37,25 @@ - time utilities, including timers and simpler interfaces to system clocks - utilities for streams - utilities for [tamer] +- micro-utilities: noncopyable, expander annotations - x86 architecture-specific tools Setup ----- +Requirements: + +- [boost] 1.38.0 +- [GCC] 4 + Like [boost], just include these header files in your next C++ project, and you're ready to go! +Certain parts of the library have extra dependencies. (In particular, these +tend to be designed as supplementing the required libraries.) + +- [State Threads] 1.8 + Related Work ------------ Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/src/commons/array.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -1,10 +1,9 @@ #ifndef COMMONS_ARRAY_H #define COMMONS_ARRAY_H -#include <boost/scoped_array.hpp> -#include <commons/boost/unique_ptr.hpp> #include <commons/check.h> #include <commons/nullptr.h> +#include <commons/unique_ptr.hpp> #include <commons/utility.h> namespace commons { Copied: cpp-commons/trunk/src/commons/delegates.h (from rev 1216, cpp-commons/trunk/src/commons/boost/delegates.h) =================================================================== --- cpp-commons/trunk/src/commons/delegates.h (rev 0) +++ cpp-commons/trunk/src/commons/delegates.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -0,0 +1,69 @@ +#ifndef COMMONS_BOOST_DELEGATES_H +#define COMMONS_BOOST_DELEGATES_H + +#include <boost/function.hpp> +#include <boost/scoped_ptr.hpp> +#include <iostream> // for cerr + +namespace commons +{ + + using namespace boost; + using namespace std; + + typedef std::function<void()> fn; + + void + swallow(const fn f) { + try { f(); } + catch (std::exception &ex) { cerr << ex.what() << endl; } + } + + /** + * Delegate for running a 0-ary void function. + */ + void + run_function0(const void *p) + { + scoped_ptr<const fn> pf(reinterpret_cast<const fn*>(p)); + (*pf)(); + } + + /** + * NULL void*-returning delegate for running a 0-ary void function. + */ + void* + run_function0_null(void* p) + { + run_function0(p); + return NULL; + } + + // TODO: is there a way to do this? +// /** +// * Exception-returning delegate for running a 0-ary void function. +// */ +// void* +// run_function0_ex(void* p) +// { +// try { run_function0(p); } +// catch (std::exception &ex) { return std::exception(ex); } +// } + + /** + * A class that takes a functor and calls it on destruction, effectively + * giving you a `finally` clause. Particularly useful with clamp. + */ + //template<typename T> + typedef function0<void> T; + class finally { + public: + finally(T f): f_(f) {} + ~finally() { f_(); } + private: + T f_; + }; + +} + +#endif Property changes on: cpp-commons/trunk/src/commons/delegates.h ___________________________________________________________________ Added: svn:mergeinfo + Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -10,10 +10,10 @@ #include <st.h> #include <stx.h> #include <commons/array.h> +#include <commons/delegates.h> #include <commons/nullptr.h> // delegates.h must be included after sockets.h due to bind() conflicts. #include <commons/sockets.h> -#include <commons/boost/delegates.h> #include <commons/utility.h> #include <boost/foreach.hpp> #include <boost/function.hpp> Modified: cpp-commons/trunk/src/commons/threads.h =================================================================== --- cpp-commons/trunk/src/commons/threads.h 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/src/commons/threads.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -6,11 +6,17 @@ #include <sys/types.h> #include <unistd.h> +#include <boost/function.hpp> + #include <commons/check.h> +#include <commons/delegates.h> +#include <commons/nullptr.h> namespace commons { + using namespace boost; + /** * Get the current thread ID. Glibc does not provide a wrapper for this * system call. @@ -41,171 +47,22 @@ waitall(pthread_t* ts, int n) { for (int i = 0; i < n; i++) { - check(pthread_join(ts[i], NULL) == 0); + check(pthread_join(ts[i], nullptr) == 0); } } /** - * Helper for launching new threads. - */ - void* - runner(void *p) - { - void (*f)() = (void(*)()) p; - (*f)(); - return NULL; - } - - /** * Run a function in pthread. * \return The new pthread_t on success, 0 on failure. * TODO: Is it safe to treat the pthread_t as an integral type? */ pthread_t - spawn(void (*f)()) + spawn(const boost::function<void()>& f) { pthread_t t; - return pthread_create(&t, NULL, &runner, (void*) f) == 0 ? t : 0; + return pthread_create(&t, NULL, &run_function0_null, (void*) new boost::function<void()>(f)) == 0 ? t : 0; } - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C> pthread_t - method_thread(C *o, void (C::*m)()) - { - class runnable { - public: - C *o; - void (C::*m)(); - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)() = r->m; - delete r; - (o->*m)(); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C, class A> pthread_t - method_thread(C *o, void (C::*m)(A), A a) - { - class runnable { - public: - C *o; - void (C::*m)(A a); - A a; - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)(A ) = r->m; - A a = r->a; - delete r; - (o->*m)(a); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - r->a = a; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C, class A1, class A2> pthread_t - method_thread(C *o, void (C::*m)(A1 , A2 ), A1 a1, A2 a2) - { - class runnable { - public: - C *o; - void (C::*m)(A1 a1, A2 a2); - A1 a1; - A2 a2; - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)(A1 , A2 ) = r->m; - A1 a1 = r->a1; - A2 a2 = r->a2; - delete r; - (o->*m)(a1, a2); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - r->a1 = a1; - r->a2 = a2; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C, class A1, class A2, class A3> pthread_t - method_thread(C *o, void (C::*m)(A1 , A2, A3), A1 a1, A2 a2, A3 a3) - { - class runnable { - public: - C *o; - void (C::*m)(A1 a1, A2 a2, A3 a3); - A1 a1; - A2 a2; - A3 a3; - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)(A1, A2, A3) = r->m; - A1 a1 = r->a1; - A2 a2 = r->a2; - A3 a3 = r->a3; - delete r; - (o->*m)(a1, a2, a3); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - r->a1 = a1; - r->a2 = a2; - r->a3 = a3; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - } #endif Copied: cpp-commons/trunk/src/commons/unique_ptr.hpp (from rev 1216, cpp-commons/trunk/src/commons/boost/unique_ptr.hpp) =================================================================== --- cpp-commons/trunk/src/commons/unique_ptr.hpp (rev 0) +++ cpp-commons/trunk/src/commons/unique_ptr.hpp 2009-02-22 06:49:47 UTC (rev 1219) @@ -0,0 +1,535 @@ +/////////////////////////////////////////////////////////////////////////////// +// unique_ptr.hpp header file +// +// Copyright 2009 Howard Hinnant, Ion Gaztañaga. +// 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) +// See http://www.boost.org/libs/foreach for documentation + +// This is a C++03 emulation of std::unique_ptr placed in namespace boost. +// Reference http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf +// for the latest unique_ptr specification, and +// reference http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html +// for any pending issues against this specification. + +#ifndef UNIQUE_PTR_HPP +#define UNIQUE_PTR_HPP + +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits.hpp> +#include <boost/static_assert.hpp> +#include <boost/mpl/if.hpp> + +namespace boost +{ + +namespace detail_unique_ptr +{ + +typedef char one; +struct two {one _[2];}; + +// An is_convertible<From, To> that considers From an rvalue (consistent with C++0X). +// This is a simplified version neglecting the types function, array, void and abstract types +// I had to make a special case out of is_convertible<T,T> to make move-only +// types happy. + +namespace is_conv_imp +{ +template <class T> one test1(const T&); +template <class T> two test1(...); +template <class T> one test2(T); +template <class T> two test2(...); +template <class T> T source(); +} + +template <class T1, class T2> +struct is_convertible +{ + static const bool value = sizeof(is_conv_imp::test1<T2>(is_conv_imp::source<T1>())) == 1; +}; + +template <class T> +struct is_convertible<T, T> +{ + static const bool value = sizeof(is_conv_imp::test2<T>(is_conv_imp::source<T>())) == 1; +}; + +template <class T> +class rv +{ + T& r_; + +public: + explicit rv(T& r) : r_(r) {} + T* operator->() {return &r_;} + T& operator*() {return r_;} +}; + +template <class T> +struct identity +{ + typedef T type; +}; + +} // detail_unique_ptr + +template <class T> +inline +typename enable_if_c +< + !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + T& +>::type +move(T& t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + const T& +>::type +move(const T& t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + T +>::type +move(T& t) +{ + return T(detail_unique_ptr::rv<T>(t)); +} + +template <class T> +inline +typename enable_if_c +< + is_reference<T>::value, + T +>::type +forward(typename detail_unique_ptr::identity<T>::type t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + !is_reference<T>::value, + T +>::type +forward(typename detail_unique_ptr::identity<T>::type& t) +{ + return move(t); +} + +template <class T> +inline +typename enable_if_c +< + !is_reference<T>::value, + T +>::type +forward(const typename detail_unique_ptr::identity<T>::type& t) +{ + return move(const_cast<T&>(t)); +} + +namespace detail_unique_ptr { + +// A move-aware but stripped-down compressed_pair which only optimizes storage for T2 +template <class T1, class T2, bool = is_empty<T2>::value> +class unique_ptr_storage +{ + T1 t1_; + T2 t2_; + + typedef typename add_reference<T2>::type T2_reference; + typedef typename add_reference<const T2>::type T2_const_reference; + + unique_ptr_storage(const unique_ptr_storage&); + unique_ptr_storage& operator=(const unique_ptr_storage&); +public: + operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} + + unique_ptr_storage() : t1_(), t2_() {} + + explicit unique_ptr_storage(T1 t1) + : t1_(move(t1)), t2_() {} + + unique_ptr_storage(T1 t1, T2 t2) + : t1_(move(t1)), t2_(forward<T2>(t2)) {} + + T1& first() {return t1_;} + const T1& first() const {return t1_;} + + T2_reference second() {return t2_;} + T2_const_reference second() const {return t2_;} +}; + +template <class T1, class T2> +class unique_ptr_storage<T1, T2, true> + : private T2 +{ + T1 t1_; + typedef T2 t2_; + + unique_ptr_storage(const unique_ptr_storage&); + unique_ptr_storage& operator=(const unique_ptr_storage&); +public: + operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} + + unique_ptr_storage() : t1_() {} + + explicit unique_ptr_storage(T1 t1) + : t1_(move(t1)) {} + + unique_ptr_storage(T1 t1, T2 t2) + : t2_(move(t2)), t1_(move(t1)) {} + + T1& first() {return t1_;} + const T1& first() const {return t1_;} + + T2& second() {return *this;} + const T2& second() const {return *this;} +}; + +template <class T1, class T2, bool b> +inline +void +swap(unique_ptr_storage<T1, T2, b>& x, unique_ptr_storage<T1, T2, b>& y) +{ + using std::swap; + swap(x.first(), y.first()); + swap(x.second(), y.second()); +} + +} // detail_unique_ptr + +template <class T> +struct default_delete +{ + default_delete() {} + template <class U> + default_delete(const default_delete<U>&, + typename enable_if_c<detail_unique_ptr::is_convertible<U*, T*>::value>::type* = 0) + {} + + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete ptr; + } +}; + +template <class T> +struct default_delete<T[]> +{ + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete [] ptr; + } + +private: + + template <class U> void operator()(U*) const; +}; + +namespace detail_unique_ptr +{ + +namespace pointer_type_imp +{ + +template <class U> static two test(...); +template <class U> static one test(typename U::pointer* = 0); + +} // pointer_type_imp + +template <class T> +struct has_pointer_type +{ + static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1; +}; + +namespace pointer_type_imp +{ + +template <class T, class D, bool = has_pointer_type<D>::value> +struct pointer_type +{ + typedef typename D::pointer type; +}; + +template <class T, class D> +struct pointer_type<T, D, false> +{ + typedef T* type; +}; + +} // pointer_type_imp + +template <class T, class D> +struct pointer_type +{ + typedef typename pointer_type_imp::pointer_type<T, + typename boost::remove_reference<D>::type>::type type; +}; + +} // detail_unique_ptr + +template <class T, class D = default_delete<T> > +class unique_ptr +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; + +private: + detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; + + typedef typename add_reference<deleter_type>::type deleter_reference; + typedef typename add_reference<const deleter_type>::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + +public: + operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} + unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} + unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + + unique_ptr() + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p) + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + unique_ptr(pointer p, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type d) + : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} + + template <class U, class E> + unique_ptr(unique_ptr<U, E> u, + typename enable_if_c + < + !boost::is_array<U>::value && + detail_unique_ptr::is_convertible<typename unique_ptr<U>::pointer, pointer>::value && + detail_unique_ptr::is_convertible<E, deleter_type>::value && + ( + !is_reference<deleter_type>::value || + is_same<deleter_type, E>::value + ) + >::type* = 0) + : ptr_(u.release(), forward<D>(forward<E>(u.get_deleter()))) {} + + ~unique_ptr() {reset();} + + unique_ptr& operator=(int nat::*) + { + reset(); + return *this; + } + + template <class U, class E> + unique_ptr& + operator=(unique_ptr<U, E> u) + { + reset(u.release()); + ptr_.second() = move(u.get_deleter()); + return *this; + } + + typename add_reference<T>::type operator*() const {return *get();} + pointer operator->() const {return get();} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} +}; + +template <class T, class D> +class unique_ptr<T[], D> +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; + +private: + detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; + + typedef typename add_reference<deleter_type>::type deleter_reference; + typedef typename add_reference<const deleter_type>::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + +public: + operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} + unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} + unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + + unique_ptr() + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p) + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + unique_ptr(pointer p, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type d) + : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} + + ~unique_ptr() {reset();} + + T& operator[](size_t i) const {return get()[i];} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} +private: + template <class U> + explicit unique_ptr(U, + typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); + + template <class U> + unique_ptr(U, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type, + typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); +}; + +template<class T, class D> +inline +void +swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) +{ + x.swap(y); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return x.get() == y.get(); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(x == y); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return x.get() < y.get(); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(y < x); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return y < x; +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(x < y); +} + +} // boost + +#endif // UNIQUE_PTR_HPP Property changes on: cpp-commons/trunk/src/commons/unique_ptr.hpp ___________________________________________________________________ Added: svn:mergeinfo + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-25 07:45:31
|
Revision: 1231 http://assorted.svn.sourceforge.net/assorted/?rev=1231&view=rev Author: yangzhang Date: 2009-02-25 07:45:26 +0000 (Wed, 25 Feb 2009) Log Message: ----------- lots of general cleanup - fixed warnings on remaining files - added swap for arrays, size_t - in st_reader, using (the faster) memcpy instead of (the slower) copy, after some experiments - using new check functions in load_file() - added algo.h, with just swap() - fixed missing includes - fixed include guards - added tools for generating build tests, checking include guard names, listing sources - added test Makefile with lots of warnings - moved files around so that third-party sources are not in commons/ - updated the README Modified Paths: -------------- cpp-commons/trunk/README cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/cpuid.h cpp-commons/trunk/src/commons/delegates.h cpp-commons/trunk/src/commons/exceptions.h cpp-commons/trunk/src/commons/files.h cpp-commons/trunk/src/commons/pthread/barrier.h cpp-commons/trunk/src/commons/rand.h cpp-commons/trunk/src/commons/region.h cpp-commons/trunk/src/commons/st/st.h cpp-commons/trunk/src/commons/strings.h cpp-commons/trunk/src/commons/threads.h cpp-commons/trunk/src/commons/x86asm.h Added Paths: ----------- cpp-commons/trunk/src/boost/ cpp-commons/trunk/src/boost/unique_ptr.hpp cpp-commons/trunk/src/commons/algo.h cpp-commons/trunk/src/test/Makefile cpp-commons/trunk/src/yonat/ cpp-commons/trunk/tools/check.bash Removed Paths: ------------- cpp-commons/trunk/src/commons/unique_ptr.hpp cpp-commons/trunk/src/commons/yonat/ cpp-commons/trunk/src/test/all.cc Modified: cpp-commons/trunk/README =================================================================== --- cpp-commons/trunk/README 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/README 2009-02-25 07:45:26 UTC (rev 1231) @@ -14,7 +14,6 @@ - RAII utilities, such as for closing file descriptors and `finally` objects - smart arrays: sized arrays, "managed" (moveable, conditionally scope-destroyed) arrays -- Howard Hinnant's C++03-emulated TR1 `unique_ptr.hpp` - `pool`: fixed-size object pools - bit manipulation - bundles of header includes @@ -40,6 +39,20 @@ - micro-utilities: noncopyable, expander annotations - x86 architecture-specific tools +Third-party code: + +- Howard Hinnant's [C++03-emulated TR1 `unique_ptr.hpp`] +- [Yonat's STL extensions] + - pointainer: auto-cleaning STL container of pointers. Many times this is a + better alternative than using smart pointers (no overhead, no + multi-threading problems). + - pointerator: iterator to T* that behaves like iterator to T. Useful for + iterating pointainers and containers of smart pointers. + - stringizer: turns an object into a std::string. + +[C++03-emulated TR1 `unique_ptr.hpp`]: http://home.roadrunner.com/~hinnant/unique_ptr03.html +[Yonat's STL extensions]: http://ootips.org/yonat/4dev/ + Setup ----- Copied: cpp-commons/trunk/src/boost/unique_ptr.hpp (from rev 1219, cpp-commons/trunk/src/commons/unique_ptr.hpp) =================================================================== --- cpp-commons/trunk/src/boost/unique_ptr.hpp (rev 0) +++ cpp-commons/trunk/src/boost/unique_ptr.hpp 2009-02-25 07:45:26 UTC (rev 1231) @@ -0,0 +1,535 @@ +/////////////////////////////////////////////////////////////////////////////// +// unique_ptr.hpp header file +// +// Copyright 2009 Howard Hinnant, Ion Gaztañaga. +// 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) +// See http://www.boost.org/libs/foreach for documentation + +// This is a C++03 emulation of std::unique_ptr placed in namespace boost. +// Reference http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf +// for the latest unique_ptr specification, and +// reference http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html +// for any pending issues against this specification. + +#ifndef UNIQUE_PTR_HPP +#define UNIQUE_PTR_HPP + +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits.hpp> +#include <boost/static_assert.hpp> +#include <boost/mpl/if.hpp> + +namespace boost +{ + +namespace detail_unique_ptr +{ + +typedef char one; +struct two {one _[2];}; + +// An is_convertible<From, To> that considers From an rvalue (consistent with C++0X). +// This is a simplified version neglecting the types function, array, void and abstract types +// I had to make a special case out of is_convertible<T,T> to make move-only +// types happy. + +namespace is_conv_imp +{ +template <class T> one test1(const T&); +template <class T> two test1(...); +template <class T> one test2(T); +template <class T> two test2(...); +template <class T> T source(); +} + +template <class T1, class T2> +struct is_convertible +{ + static const bool value = sizeof(is_conv_imp::test1<T2>(is_conv_imp::source<T1>())) == 1; +}; + +template <class T> +struct is_convertible<T, T> +{ + static const bool value = sizeof(is_conv_imp::test2<T>(is_conv_imp::source<T>())) == 1; +}; + +template <class T> +class rv +{ + T& r_; + +public: + explicit rv(T& r) : r_(r) {} + T* operator->() {return &r_;} + T& operator*() {return r_;} +}; + +template <class T> +struct identity +{ + typedef T type; +}; + +} // detail_unique_ptr + +template <class T> +inline +typename enable_if_c +< + !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + T& +>::type +move(T& t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + const T& +>::type +move(const T& t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + T +>::type +move(T& t) +{ + return T(detail_unique_ptr::rv<T>(t)); +} + +template <class T> +inline +typename enable_if_c +< + is_reference<T>::value, + T +>::type +forward(typename detail_unique_ptr::identity<T>::type t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + !is_reference<T>::value, + T +>::type +forward(typename detail_unique_ptr::identity<T>::type& t) +{ + return move(t); +} + +template <class T> +inline +typename enable_if_c +< + !is_reference<T>::value, + T +>::type +forward(const typename detail_unique_ptr::identity<T>::type& t) +{ + return move(const_cast<T&>(t)); +} + +namespace detail_unique_ptr { + +// A move-aware but stripped-down compressed_pair which only optimizes storage for T2 +template <class T1, class T2, bool = is_empty<T2>::value> +class unique_ptr_storage +{ + T1 t1_; + T2 t2_; + + typedef typename add_reference<T2>::type T2_reference; + typedef typename add_reference<const T2>::type T2_const_reference; + + unique_ptr_storage(const unique_ptr_storage&); + unique_ptr_storage& operator=(const unique_ptr_storage&); +public: + operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} + + unique_ptr_storage() : t1_(), t2_() {} + + explicit unique_ptr_storage(T1 t1) + : t1_(move(t1)), t2_() {} + + unique_ptr_storage(T1 t1, T2 t2) + : t1_(move(t1)), t2_(forward<T2>(t2)) {} + + T1& first() {return t1_;} + const T1& first() const {return t1_;} + + T2_reference second() {return t2_;} + T2_const_reference second() const {return t2_;} +}; + +template <class T1, class T2> +class unique_ptr_storage<T1, T2, true> + : private T2 +{ + T1 t1_; + typedef T2 t2_; + + unique_ptr_storage(const unique_ptr_storage&); + unique_ptr_storage& operator=(const unique_ptr_storage&); +public: + operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} + + unique_ptr_storage() : t1_() {} + + explicit unique_ptr_storage(T1 t1) + : t1_(move(t1)) {} + + unique_ptr_storage(T1 t1, T2 t2) + : t2_(move(t2)), t1_(move(t1)) {} + + T1& first() {return t1_;} + const T1& first() const {return t1_;} + + T2& second() {return *this;} + const T2& second() const {return *this;} +}; + +template <class T1, class T2, bool b> +inline +void +swap(unique_ptr_storage<T1, T2, b>& x, unique_ptr_storage<T1, T2, b>& y) +{ + using std::swap; + swap(x.first(), y.first()); + swap(x.second(), y.second()); +} + +} // detail_unique_ptr + +template <class T> +struct default_delete +{ + default_delete() {} + template <class U> + default_delete(const default_delete<U>&, + typename enable_if_c<detail_unique_ptr::is_convertible<U*, T*>::value>::type* = 0) + {} + + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete ptr; + } +}; + +template <class T> +struct default_delete<T[]> +{ + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete [] ptr; + } + +private: + + template <class U> void operator()(U*) const; +}; + +namespace detail_unique_ptr +{ + +namespace pointer_type_imp +{ + +template <class U> static two test(...); +template <class U> static one test(typename U::pointer* = 0); + +} // pointer_type_imp + +template <class T> +struct has_pointer_type +{ + static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1; +}; + +namespace pointer_type_imp +{ + +template <class T, class D, bool = has_pointer_type<D>::value> +struct pointer_type +{ + typedef typename D::pointer type; +}; + +template <class T, class D> +struct pointer_type<T, D, false> +{ + typedef T* type; +}; + +} // pointer_type_imp + +template <class T, class D> +struct pointer_type +{ + typedef typename pointer_type_imp::pointer_type<T, + typename boost::remove_reference<D>::type>::type type; +}; + +} // detail_unique_ptr + +template <class T, class D = default_delete<T> > +class unique_ptr +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; + +private: + detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; + + typedef typename add_reference<deleter_type>::type deleter_reference; + typedef typename add_reference<const deleter_type>::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + +public: + operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} + unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} + unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + + unique_ptr() + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p) + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + unique_ptr(pointer p, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type d) + : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} + + template <class U, class E> + unique_ptr(unique_ptr<U, E> u, + typename enable_if_c + < + !boost::is_array<U>::value && + detail_unique_ptr::is_convertible<typename unique_ptr<U>::pointer, pointer>::value && + detail_unique_ptr::is_convertible<E, deleter_type>::value && + ( + !is_reference<deleter_type>::value || + is_same<deleter_type, E>::value + ) + >::type* = 0) + : ptr_(u.release(), forward<D>(forward<E>(u.get_deleter()))) {} + + ~unique_ptr() {reset();} + + unique_ptr& operator=(int nat::*) + { + reset(); + return *this; + } + + template <class U, class E> + unique_ptr& + operator=(unique_ptr<U, E> u) + { + reset(u.release()); + ptr_.second() = move(u.get_deleter()); + return *this; + } + + typename add_reference<T>::type operator*() const {return *get();} + pointer operator->() const {return get();} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} +}; + +template <class T, class D> +class unique_ptr<T[], D> +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; + +private: + detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; + + typedef typename add_reference<deleter_type>::type deleter_reference; + typedef typename add_reference<const deleter_type>::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + +public: + operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} + unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} + unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + + unique_ptr() + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p) + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + unique_ptr(pointer p, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type d) + : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} + + ~unique_ptr() {reset();} + + T& operator[](size_t i) const {return get()[i];} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} +private: + template <class U> + explicit unique_ptr(U, + typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); + + template <class U> + unique_ptr(U, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type, + typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); +}; + +template<class T, class D> +inline +void +swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) +{ + x.swap(y); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return x.get() == y.get(); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(x == y); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return x.get() < y.get(); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(y < x); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return y < x; +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(x < y); +} + +} // boost + +#endif // UNIQUE_PTR_HPP Added: cpp-commons/trunk/src/commons/algo.h =================================================================== --- cpp-commons/trunk/src/commons/algo.h (rev 0) +++ cpp-commons/trunk/src/commons/algo.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -0,0 +1,16 @@ +#ifndef COMMONS_ALGO_H +#define COMMONS_ALGO_H + +#include <sys/types.h> + +namespace commons { + + void swap(size_t &x, size_t &y) { + x = x ^ y; + y = x ^ y; + x = x ^ y; + } + +} + +#endif Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/array.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -1,15 +1,19 @@ #ifndef COMMONS_ARRAY_H #define COMMONS_ARRAY_H +#include <boost/unique_ptr.hpp> +#include <commons/algo.h> #include <commons/check.h> #include <commons/nullptr.h> -#include <commons/unique_ptr.hpp> #include <commons/utility.h> namespace commons { using namespace boost; + template<typename T> class array; + template<typename T> void swap(array<T> &a, array<T> &b); + /** * A thin wrapper around arrays. Like a fixed-size vector. Unlike array * since the size can be dynamically determined. @@ -17,6 +21,7 @@ template<typename T> class array { EXPAND(unique_ptr<T[]>) + friend void swap<>(array<T> &a, array<T> &b); public: explicit array(size_t n) : p_(checkpass(new T[n])), n_(n) {} size_t size() const { return n_; } @@ -30,6 +35,17 @@ }; /** + * Swap two arrays. + */ + template<typename T> + void + swap(array<T> &a, array<T> &b) + { + swap(a.p_, b.p_); + swap(a.n_, b.n_); + } + + /** * Conditionally-scoped, move-able, release-able, un-sized array. */ template<typename T> Modified: cpp-commons/trunk/src/commons/cpuid.h =================================================================== --- cpp-commons/trunk/src/commons/cpuid.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/cpuid.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -31,7 +31,7 @@ { unsigned int a, b, c, d; cpuid(1, a, b, c, d); - return (unsigned short) (high(b) * 8); + return static_cast<unsigned short>(high(b) * 8); } /** Modified: cpp-commons/trunk/src/commons/delegates.h =================================================================== --- cpp-commons/trunk/src/commons/delegates.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/delegates.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -1,5 +1,5 @@ -#ifndef COMMONS_BOOST_DELEGATES_H -#define COMMONS_BOOST_DELEGATES_H +#ifndef COMMONS_DELEGATES_H +#define COMMONS_DELEGATES_H #include <boost/function.hpp> #include <boost/scoped_ptr.hpp> Modified: cpp-commons/trunk/src/commons/exceptions.h =================================================================== --- cpp-commons/trunk/src/commons/exceptions.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/exceptions.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -2,6 +2,7 @@ #define COMMONS_EXCEPTIONS_H #include <exception> +#include <string> namespace commons { Modified: cpp-commons/trunk/src/commons/files.h =================================================================== --- cpp-commons/trunk/src/commons/files.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/files.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -19,7 +19,7 @@ using namespace std; - class file_not_found_exception : exception { + class file_not_found_exception : std::exception { public: file_not_found_exception(const string & name) : name(name) {} virtual ~file_not_found_exception() throw() {} @@ -50,40 +50,35 @@ * buffer (size of the file). * TODO this probably isn't very safe, since we're demoting an off_t to a * size_t. Is there a healthier approach? - * TODO move to C99 commons */ char * - load_file(const char *path, size_t & len, unsigned int ncpus) { + load_file(const char *path, size_t & len, unsigned int ncpus) + { struct stat sb; - int fd; + int fd = checkpass(open(path, 0)); - fd = open(path, 0); - check(fd >= 0); - - check(fstat(fd, &sb) == 0); + check0x(fstat(fd, &sb)); check(sb.st_size <= 0xffffffff); // TODO Why don't we need (static) cast here? Isn't this a lossy cast? len = sb.st_size; - char *buf = new char[len + 1]; - check(buf); + char *buf = checkpass(new char[len + 1]); + checkeqnneg(pread(fd, buf, len, 0), static_cast<ssize_t>(len)); - ssize_t status = pread(fd, buf, len, 0); - size_t nread = static_cast<size_t>(status); - check(status != -1 && nread == len); - // TODO Use threads to pull data to the correct initial locations? - // size_t chunk_len = len / ncpus; - // for (unsigned int i = 0; i < ncpus; i++) { - // int off = i *chunk_len; - // ssize_t status = pread(fd, buf + off, chunk_len, off); - // // We read the whole chunk or hit the end. - // size_t nread = static_cast<size_t>(status); - // check(status != -1 && (nread == chunk_len || off + nread == len)); - // } + if (false) { + size_t chunk_len = len / ncpus; + for (unsigned int i = 0; i < ncpus; i++) { + size_t off = i * chunk_len; + size_t nread = static_cast<size_t> + (checknnegerr(pread(fd, buf + off, chunk_len, off))); + // We read the whole chunk or hit the end. + check(nread == chunk_len || off + nread == len); + } + } - check(close(fd) == 0); + check0x(close(fd)); buf[len] = '\0'; // don't let strcmp() run off the end return buf; Modified: cpp-commons/trunk/src/commons/pthread/barrier.h =================================================================== --- cpp-commons/trunk/src/commons/pthread/barrier.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/pthread/barrier.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -21,7 +21,8 @@ }; int -pthread_barrier_init(pthread_barrier_t* b, pthread_barrierattr_t* a, unsigned count) +pthread_barrier_init(pthread_barrier_t* b, pthread_barrierattr_t*, + unsigned count) { check0(pthread_mutex_init(&b->lock, NULL)); check0(pthread_cond_init (&b->cond, NULL)); Modified: cpp-commons/trunk/src/commons/rand.h =================================================================== --- cpp-commons/trunk/src/commons/rand.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/rand.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -1,5 +1,5 @@ -#ifndef COMMONS_RAND_H_ -#define COMMONS_RAND_H_ +#ifndef COMMONS_RAND_H +#define COMMONS_RAND_H #include <cassert> #include <cstdlib> // random, RAND_MAX Modified: cpp-commons/trunk/src/commons/region.h =================================================================== --- cpp-commons/trunk/src/commons/region.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/region.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -173,14 +173,16 @@ */ pointer allocate(size_type num, const void* = 0) { - return (pointer) region->alloc_mem(num * sizeof(T)); + return reinterpret_cast<pointer>(region->alloc_mem(num * sizeof(T))); } /** * Initialize elements of allocated storage p with value `value` using * placement new. */ - void construct(pointer p, const T& value) { new((void*)p)T(value); } + void construct(pointer p, const T& value) { + new (static_cast<void*>(p)) T(value); + } /** * Destroy elements of initialized storage p by calling their destructor. Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -401,6 +401,11 @@ size_t rem() { return buf_.end() - end_; } /** + * The entire read buffer. + */ + array<char> &buf() { return buf_; } + + /** * Discard the requested number of bytes. */ void skip(size_t req, st_utime_t to = ST_UTIME_NO_TIMEOUT) { @@ -440,7 +445,7 @@ // Handle large arrays specially. if (req > buf_.size()) { managed_array<char> p(checkpass(new char[req]), true); - copy(start_, end_, p.get()); + memcpy(p.get(), start_, unread()); checkeqnneg(st_read_fully(fd_, p + unread(), req - unread(), to), static_cast<ssize_t>(req - unread())); start_ = end_ = buf_.get(); return p; @@ -448,7 +453,7 @@ // Shift things down if necessary. if (req > static_cast<size_t>(buf_.end() - end_)) { - copy(start_, end_, buf_.get()); + memmove(buf_.get(), start_, unread()); size_t diff = start_ - buf_.get(); start_ -= diff; end_ -= diff; @@ -486,7 +491,7 @@ // Shift things down if necessary. if (req > static_cast<size_t>(buf_.end() - end_)) { - copy(start_, end_, buf_.get()); + memmove(buf_.get(), start_, unread()); size_t diff = start_ - buf_.get(); start_ -= diff; end_ -= diff; Modified: cpp-commons/trunk/src/commons/strings.h =================================================================== --- cpp-commons/trunk/src/commons/strings.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/strings.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -49,19 +49,21 @@ /** * Look for a substring, but without null-termination conventions. + * + * TODO: remove or fix */ inline char * - unsafe_strstr(char *p, const char *q, const char *lim) + unsafe_strstr(char *p, const char *, const char *lim) { if (lim == 0) { while (true) { - for (; !(*p == '\0' && *(p+1) == '\0'); p++); + for (; !(*p == '\0' && *(p+1) == '\0'); p++) {} return p; } } else { check(p < lim); while (true) { - for (; !(*p == '\0' && *(p+1) == '\0') && p < lim; p++); + for (; !(*p == '\0' && *(p+1) == '\0') && p < lim; p++) {} if (p == lim) return NULL; return p; } @@ -74,7 +76,7 @@ inline const char* unsafe_strstr(const char *p, const char *q, const char *lim) { - return unsafe_strstr((char*) p, q, lim); + return unsafe_strstr(const_cast<char*>(p), q, lim); } /** @@ -87,9 +89,9 @@ scan(const void* buf, size_t len) { char sum = 0; - const char* start = (const char*) buf; + const char* start = reinterpret_cast<const char*>(buf); for (const char* p = start; p < start + len; p++) { - sum += *p; + sum = static_cast<char>(sum | *p); } return sum; } @@ -105,7 +107,7 @@ { const size_t sz = 1024; char tmp[sz]; - const char* p = (const char*) buf; + const char* p = reinterpret_cast<const char*>(buf); const char* end = p + len; for (; p + sz < end; p += 1024) { memcpy(tmp, p, sz); Modified: cpp-commons/trunk/src/commons/threads.h =================================================================== --- cpp-commons/trunk/src/commons/threads.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/threads.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -2,6 +2,7 @@ #define COMMONS_THREADS_H #include <pthread.h> +#include <sched.h> #include <sys/syscall.h> #include <sys/types.h> #include <unistd.h> @@ -18,13 +19,19 @@ using namespace boost; /** + * Work-around to make CPU_SET etc. -Wold-style-cast-safe. + */ +#undef __CPUMASK +#define __CPUMASK(cpu) (static_cast<__cpu_mask>(1) << ((cpu) % __NCPUBITS)) + + /** * Get the current thread ID. Glibc does not provide a wrapper for this * system call. */ inline pid_t gettid() { - return (pid_t) syscall(SYS_gettid); + return static_cast<pid_t>(syscall(SYS_gettid)); } /** @@ -60,7 +67,8 @@ spawn(const boost::function<void()>& f) { pthread_t t; - return pthread_create(&t, NULL, &run_function0_null, (void*) new boost::function<void()>(f)) == 0 ? t : 0; + return pthread_create(&t, NULL, &run_function0_null, + new boost::function<void()>(f)) == 0 ? t : 0; } } Deleted: cpp-commons/trunk/src/commons/unique_ptr.hpp =================================================================== --- cpp-commons/trunk/src/commons/unique_ptr.hpp 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/unique_ptr.hpp 2009-02-25 07:45:26 UTC (rev 1231) @@ -1,535 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// unique_ptr.hpp header file -// -// Copyright 2009 Howard Hinnant, Ion Gaztañaga. -// 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) -// See http://www.boost.org/libs/foreach for documentation - -// This is a C++03 emulation of std::unique_ptr placed in namespace boost. -// Reference http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf -// for the latest unique_ptr specification, and -// reference http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html -// for any pending issues against this specification. - -#ifndef UNIQUE_PTR_HPP -#define UNIQUE_PTR_HPP - -#include <boost/utility/enable_if.hpp> -#include <boost/type_traits.hpp> -#include <boost/static_assert.hpp> -#include <boost/mpl/if.hpp> - -namespace boost -{ - -namespace detail_unique_ptr -{ - -typedef char one; -struct two {one _[2];}; - -// An is_convertible<From, To> that considers From an rvalue (consistent with C++0X). -// This is a simplified version neglecting the types function, array, void and abstract types -// I had to make a special case out of is_convertible<T,T> to make move-only -// types happy. - -namespace is_conv_imp -{ -template <class T> one test1(const T&); -template <class T> two test1(...); -template <class T> one test2(T); -template <class T> two test2(...); -template <class T> T source(); -} - -template <class T1, class T2> -struct is_convertible -{ - static const bool value = sizeof(is_conv_imp::test1<T2>(is_conv_imp::source<T1>())) == 1; -}; - -template <class T> -struct is_convertible<T, T> -{ - static const bool value = sizeof(is_conv_imp::test2<T>(is_conv_imp::source<T>())) == 1; -}; - -template <class T> -class rv -{ - T& r_; - -public: - explicit rv(T& r) : r_(r) {} - T* operator->() {return &r_;} - T& operator*() {return r_;} -}; - -template <class T> -struct identity -{ - typedef T type; -}; - -} // detail_unique_ptr - -template <class T> -inline -typename enable_if_c -< - !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, - T& ->::type -move(T& t) -{ - return t; -} - -template <class T> -inline -typename enable_if_c -< - !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, - const T& ->::type -move(const T& t) -{ - return t; -} - -template <class T> -inline -typename enable_if_c -< - detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, - T ->::type -move(T& t) -{ - return T(detail_unique_ptr::rv<T>(t)); -} - -template <class T> -inline -typename enable_if_c -< - is_reference<T>::value, - T ->::type -forward(typename detail_unique_ptr::identity<T>::type t) -{ - return t; -} - -template <class T> -inline -typename enable_if_c -< - !is_reference<T>::value, - T ->::type -forward(typename detail_unique_ptr::identity<T>::type& t) -{ - return move(t); -} - -template <class T> -inline -typename enable_if_c -< - !is_reference<T>::value, - T ->::type -forward(const typename detail_unique_ptr::identity<T>::type& t) -{ - return move(const_cast<T&>(t)); -} - -namespace detail_unique_ptr { - -// A move-aware but stripped-down compressed_pair which only optimizes storage for T2 -template <class T1, class T2, bool = is_empty<T2>::value> -class unique_ptr_storage -{ - T1 t1_; - T2 t2_; - - typedef typename add_reference<T2>::type T2_reference; - typedef typename add_reference<const T2>::type T2_const_reference; - - unique_ptr_storage(const unique_ptr_storage&); - unique_ptr_storage& operator=(const unique_ptr_storage&); -public: - operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} - - unique_ptr_storage() : t1_(), t2_() {} - - explicit unique_ptr_storage(T1 t1) - : t1_(move(t1)), t2_() {} - - unique_ptr_storage(T1 t1, T2 t2) - : t1_(move(t1)), t2_(forward<T2>(t2)) {} - - T1& first() {return t1_;} - const T1& first() const {return t1_;} - - T2_reference second() {return t2_;} - T2_const_reference second() const {return t2_;} -}; - -template <class T1, class T2> -class unique_ptr_storage<T1, T2, true> - : private T2 -{ - T1 t1_; - typedef T2 t2_; - - unique_ptr_storage(const unique_ptr_storage&); - unique_ptr_storage& operator=(const unique_ptr_storage&); -public: - operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} - - unique_ptr_storage() : t1_() {} - - explicit unique_ptr_storage(T1 t1) - : t1_(move(t1)) {} - - unique_ptr_storage(T1 t1, T2 t2) - : t2_(move(t2)), t1_(move(t1)) {} - - T1& first() {return t1_;} - const T1& first() const {return t1_;} - - T2& second() {return *this;} - const T2& second() const {return *this;} -}; - -template <class T1, class T2, bool b> -inline -void -swap(unique_ptr_storage<T1, T2, b>& x, unique_ptr_storage<T1, T2, b>& y) -{ - using std::swap; - swap(x.first(), y.first()); - swap(x.second(), y.second()); -} - -} // detail_unique_ptr - -template <class T> -struct default_delete -{ - default_delete() {} - template <class U> - default_delete(const default_delete<U>&, - typename enable_if_c<detail_unique_ptr::is_convertible<U*, T*>::value>::type* = 0) - {} - - void operator()(T* ptr) const - { - BOOST_STATIC_ASSERT(sizeof(T) > 0); - delete ptr; - } -}; - -template <class T> -struct default_delete<T[]> -{ - void operator()(T* ptr) const - { - BOOST_STATIC_ASSERT(sizeof(T) > 0); - delete [] ptr; - } - -private: - - template <class U> void operator()(U*) const; -}; - -namespace detail_unique_ptr -{ - -namespace pointer_type_imp -{ - -template <class U> static two test(...); -template <class U> static one test(typename U::pointer* = 0); - -} // pointer_type_imp - -template <class T> -struct has_pointer_type -{ - static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1; -}; - -namespace pointer_type_imp -{ - -template <class T, class D, bool = has_pointer_type<D>::value> -struct pointer_type -{ - typedef typename D::pointer type; -}; - -template <class T, class D> -struct pointer_type<T, D, false> -{ - typedef T* type; -}; - -} // pointer_type_imp - -template <class T, class D> -struct pointer_type -{ - typedef typename pointer_type_imp::pointer_type<T, - typename boost::remove_reference<D>::type>::type type; -}; - -} // detail_unique_ptr - -template <class T, class D = default_delete<T> > -class unique_ptr -{ -public: - typedef T element_type; - typedef D deleter_type; - typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; - -private: - detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; - - typedef typename add_reference<deleter_type>::type deleter_reference; - typedef typename add_reference<const deleter_type>::type deleter_const_reference; - - struct nat {int for_bool_;}; - - unique_ptr(unique_ptr&); - unique_ptr& operator=(unique_ptr&); - -public: - operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} - unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} - unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) - { - reset(r->release()); - ptr_.second() = move(r->get_deleter()); - return *this; - } - - unique_ptr() - { - BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); - BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); - } - - explicit unique_ptr(pointer p) - : ptr_(p) - { - BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); - BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); - } - - unique_ptr(pointer p, typename mpl::if_<is_reference<D>, - volatile typename remove_reference<D>::type&, D>::type d) - : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} - - template <class U, class E> - unique_ptr(unique_ptr<U, E> u, - typename enable_if_c - < - !boost::is_array<U>::value && - detail_unique_ptr::is_convertible<typename unique_ptr<U>::pointer, pointer>::value && - detail_unique_ptr::is_convertible<E, deleter_type>::value && - ( - !is_reference<deleter_type>::value || - is_same<deleter_type, E>::value - ) - >::type* = 0) - : ptr_(u.release(), forward<D>(forward<E>(u.get_deleter()))) {} - - ~unique_ptr() {reset();} - - unique_ptr& operator=(int nat::*) - { - reset(); - return *this; - } - - template <class U, class E> - unique_ptr& - operator=(unique_ptr<U, E> u) - { - reset(u.release()); - ptr_.second() = move(u.get_deleter()); - return *this; - } - - typename add_reference<T>::type operator*() const {return *get();} - pointer operator->() const {return get();} - pointer get() const {return ptr_.first();} - deleter_reference get_deleter() {return ptr_.second();} - deleter_const_reference get_deleter() const {return ptr_.second();} - operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} - - void reset(pointer p = pointer()) - { - pointer t = get(); - if (t != pointer()) - get_deleter()(t); - ptr_.first() = p; - } - - pointer release() - { - pointer tmp = get(); - ptr_.first() = pointer(); - return tmp; - } - - void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} -}; - -template <class T, class D> -class unique_ptr<T[], D> -{ -public: - typedef T element_type; - typedef D deleter_type; - typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; - -private: - detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; - - typedef typename add_reference<deleter_type>::type deleter_reference; - typedef typename add_reference<const deleter_type>::type deleter_const_reference; - - struct nat {int for_bool_;}; - - unique_ptr(unique_ptr&); - unique_ptr& operator=(unique_ptr&); - -public: - operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} - unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} - unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) - { - reset(r->release()); - ptr_.second() = move(r->get_deleter()); - return *this; - } - - unique_ptr() - { - BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); - BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); - } - - explicit unique_ptr(pointer p) - : ptr_(p) - { - BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); - BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); - } - - unique_ptr(pointer p, typename mpl::if_<is_reference<D>, - volatile typename remove_reference<D>::type&, D>::type d) - : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} - - ~unique_ptr() {reset();} - - T& operator[](size_t i) const {return get()[i];} - pointer get() const {return ptr_.first();} - deleter_reference get_deleter() {return ptr_.second();} - deleter_const_reference get_deleter() const {return ptr_.second();} - operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} - - void reset(pointer p = pointer()) - { - pointer t = get(); - if (t != pointer()) - get_deleter()(t); - ptr_.first() = p; - } - - pointer release() - { - pointer tmp = get(); - ptr_.first() = pointer(); - return tmp; - } - - void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} -private: - template <class U> - explicit unique_ptr(U, - typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); - - template <class U> - unique_ptr(U, typename mpl::if_<is_reference<D>, - volatile typename remove_reference<D>::type&, D>::type, - typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); -}; - -template<class T, class D> -inline -void -swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) -{ - x.swap(y); -} - -template<class T1, class D1, class T2, class D2> -inline -bool -operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ - return x.get() == y.get(); -} - -template<class T1, class D1, class T2, class D2> -inline -bool -operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ - return !(x == y); -} - -template<class T1, class D1, class T2, class D2> -inline -bool -operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ - return x.get() < y.get(); -} - -template<class T1, class D1, class T2, class D2> -inline -bool -operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ - return !(y < x); -} - -template<class T1, class D1, class T2, class D2> -inline -bool -operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ - return y < x; -} - -template<class T1, class D1, class T2, class D2> -inline -bool -operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) -{ - return !(x < y); -} - -} // boost - -#endif // UNIQUE_PTR_HPP Modified: cpp-commons/trunk/src/commons/x86asm.h =================================================================== --- cpp-commons/trunk/src/commons/x86asm.h 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/commons/x86asm.h 2009-02-25 07:45:26 UTC (rev 1231) @@ -11,7 +11,7 @@ inline unsigned char high(unsigned int r) { - return ((r >> 8) & 0xffU); + return static_cast<unsigned char>((r >> 8) & 0xffU); } /** @@ -21,7 +21,7 @@ inline unsigned char low(unsigned int r) { - return (r & 0xffU); + return static_cast<unsigned char>(r & 0xffU); } } Added: cpp-commons/trunk/src/test/Makefile =================================================================== --- cpp-commons/trunk/src/test/Makefile (rev 0) +++ cpp-commons/trunk/src/test/Makefile 2009-02-25 07:45:26 UTC (rev 1231) @@ -0,0 +1,35 @@ +CXXFLAGS = \ + -Wall \ + -Werror \ + -Wextra \ + -Wstrict-null-sentinel \ + -Wold-style-cast \ + -Woverloaded-virtual \ + -Wsign-promo \ + -Wformat=2 \ + -Winit-self \ + -Wswitch-enum \ + -Wunused \ + -Wfloat-equal \ + -Wundef \ + -Wunsafe-loop-optimizations \ + -Wpointer-arith \ + -Wcast-qual \ + -Wcast-align \ + -Wwrite-strings \ + -Wconversion \ + -Wlogical-op \ + -Wno-aggregate-return \ + -Wno-missing-declarations \ + -Wno-missing-field-initializers \ + -Wmissing-format-attribute \ + -Wpacked \ + -Wredundant-decls \ + -Winvalid-pch \ + -Wlong-long \ + -Wvolatile-register-var \ + -std=gnu++0x \ + +all: $(patsubst %.cc,%.o,$(wildcard *.cc)) + +.PHONY: all Deleted: cpp-commons/trunk/src/test/all.cc =================================================================== --- cpp-commons/trunk/src/test/all.cc 2009-02-24 20:03:15 UTC (rev 1230) +++ cpp-commons/trunk/src/test/all.cc 2009-02-25 07:45:26 UTC (rev 1231) @@ -1,35 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Yang Zhang * - * gmail:yaaang * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU Library General Public License as * - * published by the Free Software Foundation; either version 2 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <commons/boost/threads.h> -#include <commons/check.h> -#include <commons/cpuid.h> -#include <commons/files.h> -#include <commons/hash.h> -#include <commons/strings.h> -#include <commons/time.h> -#include <commons/threads.h> -#include <commons/x86asm.h> - Property changes on: cpp-commons/trunk/src/yonat ___________________________________________________________________ Added: svn:mergeinfo + Added: cpp-commons/trunk/tools/check.bash =================================================================== --- cpp-commons/trunk/tools/check.bash (rev 0) +++ cpp-commons/trunk/tools/check.bash 2009-02-25 07:45:26 UTC (rev 1231) @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +. common.bash || exit 1 + +cd "$(dirname $0)/../src/" + +srcs() { + find boost/ commons/ yonat/ -name '*.h' -o -name '*.hpp' +} + +my-srcs() { + find commons/ -name '*.h' +} + +clobber-if-diff() { + if [[ -f "$1" ]] ; then + cat > "$1.tmp" + if diff "$1" "$1.tmp" > /dev/null + then rm "$1.tmp" + else mv "$1.tmp" "$1" + fi + else + cat > "$1" + fi +} + +build-tests() { + my-srcs | sed 's/^/#include </; s/$/>/' > test/all.cc + for i in $(my-srcs) + do echo "#include <$i>" | clobber-if-diff test/$(basename ${i%.h}).cc + done + make -C test/ +} + +check-include-guards() { + python -c " +from __future__ import with_statement +import re, sys +def check(x, y): + if not x == y: + raise Exception('failed: %s != %s' % (x,y)) +for path in sys.argv[1:]: + expected = '#ifndef ' + re.sub(r'[/\\.]', '_', path).upper() + with file(path) as f: + for line in f: + if line.strip() == expected: + break + else: + raise Exception('line not found: ' + expected) +" $(my-srcs) +} + +eval "$@" Property changes on: cpp-commons/trunk/tools/check.bash ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-25 19:25:57
|
Revision: 1232 http://assorted.svn.sourceforge.net/assorted/?rev=1232&view=rev Author: yangzhang Date: 2009-02-25 19:25:50 +0000 (Wed, 25 Feb 2009) Log Message: ----------- - st_reader takes an externally managed buffer and allows for manual pointer adjustment via reset_range() - reset_range - added sized_array and associated swap() - updated setup.bash for the reorganized files Modified Paths: -------------- cpp-commons/trunk/setup.bash cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/setup.bash =================================================================== --- cpp-commons/trunk/setup.bash 2009-02-25 07:45:26 UTC (rev 1231) +++ cpp-commons/trunk/setup.bash 2009-02-25 19:25:50 UTC (rev 1232) @@ -3,4 +3,4 @@ pkg=cpp-commons . simple-setup.bash version=0.1 -install include/ src/commons +install include/ src/{boost,commons,yonat} Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-02-25 07:45:26 UTC (rev 1231) +++ cpp-commons/trunk/src/commons/array.h 2009-02-25 19:25:50 UTC (rev 1232) @@ -12,13 +12,36 @@ using namespace boost; template<typename T> class array; + template<typename T> class sized_array; template<typename T> void swap(array<T> &a, array<T> &b); + template<typename T> void swap(sized_array<T> &a, sized_array<T> &b); + // TODO: rename /** * A thin wrapper around arrays. Like a fixed-size vector. Unlike array * since the size can be dynamically determined. */ template<typename T> + class sized_array { + friend void swap<>(sized_array<T> &a, sized_array<T> &b); + public: + explicit sized_array(char *p, size_t n) : p_(p), n_(n) {} + size_t size() const { return n_; } + T *get() const { return p_; } + T *end() const { return p_ + n_; } + T operator[](size_t i) const { return p_[i]; } + void reset(T *p, size_t n) { p_ = p; n_ = n; } + private: + T *p_; + size_t n_; + }; + + // TODO: rename + /** + * A thin wrapper around arrays. Like a fixed-size vector. Unlike array + * since the size can be dynamically determined. + */ + template<typename T> class array { EXPAND(unique_ptr<T[]>) friend void swap<>(array<T> &a, array<T> &b); @@ -26,9 +49,10 @@ explicit array(size_t n) : p_(checkpass(new T[n])), n_(n) {} size_t size() const { return n_; } T *get() const { return p_.get(); } - void release() { p_.release(); } + T *release() { return p_.release(); } T *end() const { return this->get() + n_; } T operator[](size_t i) const { return p_[i]; } + void reset(T *p) { p_.reset(p); } private: unique_ptr<T[]> p_; size_t n_; @@ -45,7 +69,19 @@ swap(a.n_, b.n_); } + // TODO: try just specifying a single templated function /** + * Swap two arrays. + */ + template<typename T> + void + swap(sized_array<T> &a, sized_array<T> &b) + { + swap(a.p_, b.p_); + swap(a.n_, b.n_); + } + + /** * Conditionally-scoped, move-able, release-able, un-sized array. */ template<typename T> @@ -63,6 +99,7 @@ operator T*() { return p_; } operator const T*() const { return p_; } bool scoped() const { return scoped_; } + bool &scoped() { return scoped_; } private: T *p_; bool scoped_; Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-25 07:45:26 UTC (rev 1231) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-25 19:25:50 UTC (rev 1232) @@ -383,9 +383,9 @@ { NONCOPYABLE(st_reader) public: - st_reader(st_netfd_t fd, size_t bufsize = 1e7) : + st_reader(st_netfd_t fd, char *buf, size_t bufsize) : fd_(fd), - buf_(bufsize), + buf_(buf, bufsize), start_(buf_.get()), end_(buf_.get()) {} @@ -403,9 +403,17 @@ /** * The entire read buffer. */ - array<char> &buf() { return buf_; } + sized_array<char> &buf() { return buf_; } /** + * Manually update/adjust the pointers; useful after changing buf_. + */ + void reset_range(char *start, char *end) { + start_ = start; + end_ = end; + } + + /** * Discard the requested number of bytes. */ void skip(size_t req, st_utime_t to = ST_UTIME_NO_TIMEOUT) { @@ -519,7 +527,7 @@ /** * The temporary storage buffer. */ - array<char> buf_; + sized_array<char> buf_; /** * The start of the unconsumed range of bytes. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-03-18 09:58:55
|
Revision: 1303 http://assorted.svn.sourceforge.net/assorted/?rev=1303&view=rev Author: yangzhang Date: 2009-03-18 09:58:41 +0000 (Wed, 18 Mar 2009) Log Message: ----------- - added anchored_stream_reader and associated functions - added default ctor for sized_array - added within - tweaks to stream_writer - simplified and error-check current_time_millis() - added unused warning for static functions die, _vcheck, _check, swap - added BEGIN_NAMESPACE, END_NAMESPACE - added readptr, ptr, skip to raw_reader, raw_writer - added todos to readme Modified Paths: -------------- cpp-commons/trunk/README cpp-commons/trunk/src/commons/algo.h cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/check.h cpp-commons/trunk/src/commons/die.h cpp-commons/trunk/src/commons/memory.h cpp-commons/trunk/src/commons/streamreader.h cpp-commons/trunk/src/commons/streamwriter.h cpp-commons/trunk/src/commons/time.h cpp-commons/trunk/src/commons/utility.h Modified: cpp-commons/trunk/README =================================================================== --- cpp-commons/trunk/README 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/README 2009-03-18 09:58:41 UTC (rev 1303) @@ -104,3 +104,8 @@ [GNU Common C++]: http://www.gnu.org/software/commoncpp/ [dlib]: http://dclib.sourceforge.net/ [FC++]: http://www.cc.gatech.edu/~yannis/fc++/ + +Todo +---- + +- Get to the bottom of statics, inlines, unused Modified: cpp-commons/trunk/src/commons/algo.h =================================================================== --- cpp-commons/trunk/src/commons/algo.h 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/src/commons/algo.h 2009-03-18 09:58:41 UTC (rev 1303) @@ -5,7 +5,8 @@ namespace commons { - void swap(size_t &x, size_t &y) { + __attribute__((unused)) inline void + swap(size_t &x, size_t &y) { x = x ^ y; y = x ^ y; x = x ^ y; Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/src/commons/array.h 2009-03-18 09:58:41 UTC (rev 1303) @@ -27,6 +27,7 @@ friend void swap<>(sized_array<T> &a, sized_array<T> &b); public: explicit sized_array(char *p, size_t n) : p_(p), n_(n) {} + sized_array() : p_(nullptr), n_(0) {} size_t size() const { return n_; } T *get() const { return p_; } T *begin() const { return p_; } @@ -125,6 +126,14 @@ bool scoped_; }; + /** + * Checks if a pointer is in an array. + */ + template<typename T> + inline bool within(T &a, const void *p) { + return a.begin() <= p && p < a.end(); + } + } #endif Modified: cpp-commons/trunk/src/commons/check.h =================================================================== --- cpp-commons/trunk/src/commons/check.h 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/src/commons/check.h 2009-03-18 09:58:41 UTC (rev 1303) @@ -47,7 +47,7 @@ const string name; }; - __attribute__((format(printf, 4, 0))) inline void + __attribute__((format(printf, 4, 0))) inline static void _vcheck(bool cond, const char *file, int line, const char *fmt, va_list ap) { if (!cond) { @@ -62,7 +62,7 @@ } } - __attribute__((format(printf, 4, 5))) void + __attribute__((format(printf, 4, 5))) static void _check(bool cond, const char *file, int line, const char *fmt, ...) { va_list ap; @@ -71,7 +71,7 @@ va_end(ap); } - inline void + inline static void _check(bool cond, const char *file, int line) { _check(cond, file, line, NULL); Modified: cpp-commons/trunk/src/commons/die.h =================================================================== --- cpp-commons/trunk/src/commons/die.h 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/src/commons/die.h 2009-03-18 09:58:41 UTC (rev 1303) @@ -15,7 +15,7 @@ * * TODO: move into C Commons. */ - __attribute__((format(printf, 1, 2))) void + __attribute__((format(printf, 1, 2),unused)) static void die(const char *format, ...) { const char *errstr; Modified: cpp-commons/trunk/src/commons/memory.h =================================================================== --- cpp-commons/trunk/src/commons/memory.h 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/src/commons/memory.h 2009-03-18 09:58:41 UTC (rev 1303) @@ -38,6 +38,8 @@ void write(const T &x) { memput(p_, x); p_ += sizeof(T); } /** Get the current value of the pointer. */ void *ptr() const { return p_; } + /** Skip n bytes. */ + void skip(size_t n) { p_ += n; } }; class raw_reader @@ -49,7 +51,12 @@ template<typename T> void read(T& x) { memget(p_, x); p_ += sizeof(T); } template<typename T> - T &read() { void *p = p_; p_ += sizeof(T); return memget<T>(p_); } + T &read() { void *p = p_; p_ += sizeof(T); return memget<T>(p); } + template<typename T> + T *readptr() { return reinterpret_cast<T*>(readptr(sizeof(T))); } + void *readptr(size_t n) { void *p = p_; p_ += n; return p; } + void *ptr() const { return p_; } + void skip(size_t n) { p_ += n; } }; } Modified: cpp-commons/trunk/src/commons/streamreader.h =================================================================== --- cpp-commons/trunk/src/commons/streamreader.h 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/src/commons/streamreader.h 2009-03-18 09:58:41 UTC (rev 1303) @@ -264,6 +264,252 @@ char *anchor_; }; + /** + * General-purpose stream reader for arbitrary data source streams, plus the + * ability to hold on to (don't discard) parts of the stream. + * + * TODO actually don't need anchor!!! factor that out and rename, and adjust + * the external functions accordingly. also look into replacing the + * pointer-ref-returning functions with just reset() method(s) (overload this + * to replace/not replace the buffer as well). + */ + class anchored_stream_reader + { + NONCOPYABLE(anchored_stream_reader) + public: + anchored_stream_reader(boost::function<size_t(char*, size_t)> reader, + boost::function<void(anchored_stream_reader&)> overflow, + char *buf, size_t bufsize) : + reader_(reader), + full_reader_(repeat_reader(reader_)), + overflow_(overflow), + buf_(buf, bufsize), + start_(buf), + end_(buf), + anchor_(buf) + {} + + anchored_stream_reader(boost::function<size_t(char*, size_t)> reader, + boost::function<void(char*, size_t)> full_reader, + boost::function<void(anchored_stream_reader&)> overflow, + char *buf, size_t bufsize) : + reader_(reader), + full_reader_(full_reader), + overflow_(overflow), + buf_(buf, bufsize), + start_(buf), + end_(buf), + anchor_(buf) + {} + + /** + * The size of the unconsumed range of bytes. + */ + size_t unread() { return end_ - start_; } + size_t anchored() { return end_ - anchor_; } + + /** + * The remaining number of bytes in the buffer + */ + size_t rem() { return buf_.end() - end_; } + + /** + * The entire read buffer. + */ + sized_array<char> &buf() { return buf_; } + + void set_anchor() { anchor_ = start_; } + + /** + * Reset the pointers, emptying the buffer. + */ + void reset() { + start_ = end_ = anchor_ = buf_.get(); + } + + char *start() const { return start_; } + char *end() const { return end_; } + char *anchor() const { return anchor_; } + char *&start() { return start_; } + char *&end() { return end_; } + char *&anchor() { return anchor_; } + +#if 0 + /** + * Discard the requested number of bytes. Disregards anchor. + */ + void skip(size_t req) { + if (unread() >= req) { + // We have more unconsumed bytes than requested, so we're done. + start_ += req; + return; + } + + // We have more requested bytes than unconsumed, so need to keep + // reading. Skip over bytes that are immediately available... + req -= unread(); + // ...and reset pointers to discard current buffer. + reset(); + + // Keep reading until we have enough. + while (true) { + size_t res = reader_(end_, rem()); + if (res == 0) throw eof_exception(); + if (res == req) break; + if (res > req) { + // Now skip over the rest of the bytes, which weren't available. + start_ += req; + end_ += res; + break; + } + req -= res; + } + } +#endif + + /** + * Read req bytes; if we hit an error or EOF, then an exception is + * thrown. Returns old value of start() normally (this call then + * increments start()), or returns nullptr if req too large for buffer. + */ + char *read(size_t req) { + // Do we need to perform a read (or do we already + // have requested data)? + if (unread() < req) { + // Do we have enough space? + if (req > buf_.size()) return nullptr; + + // Shift things down if necessary. + if (req > rem()) overflow_(*this); + ASSERT(req <= rem()); + + // Keep reading until we have enough. + while (unread() < req) { + size_t res = reader_(end_, rem()); + if (res == 0) break; + else end_ += res; + } + + // If we got a premature EOF. + if (unread() < req) + throw eof_exception(); + } + + char *ret = start_; + start_ += req; + return ret; + } + + template<typename T> + T read() + { + size_t req = sizeof(T); + + // Do we need to perform a read (or do we already + // have the requested data)? + if (unread() < req) { + ASSERT(req <= buf_.size()); + + // Shift things down if necessary. + if (req > rem()) overflow_(*this); + ASSERT(req <= rem()); + + // Keep reading until we have enough. + while (unread() < req) { + size_t res = reader_(end_, rem()); + if (res == 0) break; + else end_ += res; + } + + // If we got a premature EOF. + if (unread() < req) + throw eof_exception(); + } + + T x = *reinterpret_cast<const T*>(start_); + start_ += req; + return x; + } + +#if 0 + /** + * Shift the unread bytes down to the start of the buffer. + */ + void shift() { + memmove(buf_.get(), start_, unread()); + size_t diff = start_ - buf_.get(); + start_ -= diff; + end_ -= diff; + } +#endif + + private: + boost::function<size_t(char*, size_t)> reader_; + + boost::function<void(char*, size_t)> full_reader_; + + boost::function<void(anchored_stream_reader&)> overflow_; + + /** + * The temporary storage buffer. + */ + sized_array<char> buf_; + + /** + * The start of the unconsumed range of bytes. + */ + char *start_; + + /** + * The end of the unconsumed range of bytes. + */ + char *end_; + + /** + * Do not discard bytes >= this. + */ + char *anchor_; + }; + + template<typename T> + inline void + reset_reader(T &reader, char *anchor, char *start, char *end) { + reader.anchor() = anchor; + reader.start() = start; + reader.end() = end; + } + + template<typename T> + inline void + reset_reader(T &reader, sized_array<char> &buf, char *anchor, char *start, char *end) { + swap(reader.buf(), buf); + reset_reader(reader, anchor, start, end); + } + + template<typename T> + inline void + shift_reader(T &reader) + { + memmove(reader.buf().get(), reader.anchor(), reader.anchored()); + ptrdiff_t diff = reader.anchor() - reader.buf().get(); + reset_reader(reader, + reader.anchor() - diff, + reader.start() - diff, + reader.end() - diff); + } + + template<typename T> + inline void + replace_reader(T &reader) + { + sized_array<char> buf(new char[reader.buf().size()], reader.buf().size()); + memcpy(buf.get(), reader.anchor(), reader.anchored()); + reset_reader(reader, buf, + buf.get(), + buf.get() + (reader.start() - reader.anchor()), + buf.get() + (reader.end() - reader.anchor())); + } + } #endif Modified: cpp-commons/trunk/src/commons/streamwriter.h =================================================================== --- cpp-commons/trunk/src/commons/streamwriter.h 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/src/commons/streamwriter.h 2009-03-18 09:58:41 UTC (rev 1303) @@ -23,7 +23,7 @@ char *mark_; char *p_; boost::function<void(void*, size_t)> flushcb; - char *reserve(int n, char *p) { + char *reserve(size_t n, char *p) { if (p + n > a_.end()) { // check that the reserved space will fit ASSERT(size_t(p - mark_ + n + sizeof(uint32_t)) <= a_.size()); @@ -51,15 +51,16 @@ size_t pos() { return p_ - mark_; } size_t size() { return a_.size(); } void mark() { + ASSERT(p_ >= mark_); if (p_ > mark_) { // prefix last segment with its length - *reinterpret_cast<uint32_t*>(prefix()) = uint32_t(p_ - mark_); + *reinterpret_cast<uint32_t*>(prefix()) = htonl(uint32_t(pos())); // start new segment mark_ = (p_ += sizeof(uint32_t)); } } void reset() { p_ = mark_; } - void reserve(int n) { reserve(n, p_); } + void reserve(size_t n) { reserve(n, p_); } void mark_and_flush() { mark(); flush(); @@ -71,7 +72,8 @@ unsent_ = prefix(); } } - template<typename T> void skip() { reserve(sizeof(T)); p_ += sizeof(T); } + void skip(size_t n) { reserve(n); p_ += n; } + template<typename T> void skip() { skip(sizeof(T)); } template<typename T> void write(T x) { write_(x, p_); p_ += sizeof x; } template<typename T> void write(T x, size_t off) { write_(x, mark_ + off); } void show() { Modified: cpp-commons/trunk/src/commons/time.h =================================================================== --- cpp-commons/trunk/src/commons/time.h 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/src/commons/time.h 2009-03-18 09:58:41 UTC (rev 1303) @@ -7,6 +7,8 @@ #include <sys/time.h> #include <time.h> +#include <commons/check.h> + namespace commons { @@ -19,15 +21,9 @@ inline long long current_time_millis() { - long long t; struct timeval tv; - - gettimeofday(&tv, 0); - - t = tv.tv_sec; - t = (t *1000) + (tv.tv_usec/1000); - - return t; + check0x(gettimeofday(&tv, 0)); + return 1000LL * tv.tv_sec + tv.tv_usec / 1000; } /** Modified: cpp-commons/trunk/src/commons/utility.h =================================================================== --- cpp-commons/trunk/src/commons/utility.h 2009-03-18 09:36:57 UTC (rev 1302) +++ cpp-commons/trunk/src/commons/utility.h 2009-03-18 09:58:41 UTC (rev 1303) @@ -11,4 +11,8 @@ * expand the given type. */ #define EXPAND(type) +/** To avoid indentation. */ +#define BEGIN_NAMESPACE(ns) namespace ns { +#define END_NAMESPACE } + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |