Thread: [Assorted-commits] SF.net SVN: assorted:[991] cpp-commons/trunk/src/commons
Brought to you by:
yangzhang
From: <yan...@us...> - 2008-10-06 22:24:23
|
Revision: 991 http://assorted.svn.sourceforge.net/assorted/?rev=991&view=rev Author: yangzhang Date: 2008-10-06 22:24:13 +0000 (Mon, 06 Oct 2008) Log Message: ----------- added closingfd; reworked tcp_listen into tcp_listen (with non-blocking option) and server_socket Modified Paths: -------------- cpp-commons/trunk/src/commons/closing.h cpp-commons/trunk/src/commons/sockets.h Modified: cpp-commons/trunk/src/commons/closing.h =================================================================== --- cpp-commons/trunk/src/commons/closing.h 2008-10-05 18:44:39 UTC (rev 990) +++ cpp-commons/trunk/src/commons/closing.h 2008-10-06 22:24:13 UTC (rev 991) @@ -14,6 +14,11 @@ T x; }; + class closingfd : closing<int> { + public: + closingfd(int x) : closing<int>(x) {} + }; + } #endif Modified: cpp-commons/trunk/src/commons/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/sockets.h 2008-10-05 18:44:39 UTC (rev 990) +++ cpp-commons/trunk/src/commons/sockets.h 2008-10-06 22:24:13 UTC (rev 991) @@ -14,17 +14,28 @@ { /** - * Create a listener socket, with SO_REUSEADDR. + * Create a server socket bound to localhost, with SO_REUSEADDR enabled. * \param[in] port The port to listen on. - * \return The listener socket. + * \param[in] nb Whether the socket should be non-blocking. + * \return The server socket. */ int - tcp_listen(int port) + server_socket(int port, bool nb = false) { // Create the socket. - int sfd = checknneg(socket(PF_INET, SOCK_STREAM, 0)); + int fd = checknneg(socket(PF_INET, SOCK_STREAM, 0)); try { + // Configure the socket. + int n = 1; + check0x(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&n, + sizeof(n))); + + // Make our socket non-blocking if desired. + if (nb) { + checknneg(fcntl(fd, F_SETFL, O_NONBLOCK | fcntl(fd, F_GETFL, 0))); + } + // Create the local socket address. struct sockaddr_in sa; bzero(&sa, sizeof(sa)); @@ -32,19 +43,33 @@ sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(INADDR_ANY); - // Configure the socket. - int n = 1; - check0x(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof(n))); - // Bind the socket to the local socket address. - check0x(bind(sfd, (struct sockaddr*) &sa, sizeof(struct sockaddr_in))); + check0x(bind(fd, (struct sockaddr*) &sa, sizeof(struct sockaddr_in))); - // Start listening. - check0x(listen(sfd, 256)); + return fd; + } catch (...) { + close(fd); + throw; + } + } - return sfd; + /** + * Create a server socket and listen on it. + * \param[in] port The port to listen on. + * \param[in] nb Whether the socket should be non-blocking. + * \return The listener socket. + */ + int + tcp_listen(int port, bool nb = false) + { + int fd = server_socket(port, nb); + try { + // SOMAXCONN is the kernel's limit on the maximum number of socket + // connections. + check0x(listen(fd, SOMAXCONN)); + return fd; } catch (...) { - close(sfd); + close(fd); throw; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-10-08 22:05:17
|
Revision: 1008 http://assorted.svn.sourceforge.net/assorted/?rev=1008&view=rev Author: yangzhang Date: 2008-10-08 22:05:15 +0000 (Wed, 08 Oct 2008) Log Message: ----------- added: pool, array Added Paths: ----------- cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/pool.h Added: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h (rev 0) +++ cpp-commons/trunk/src/commons/array.h 2008-10-08 22:05:15 UTC (rev 1008) @@ -0,0 +1,33 @@ +#ifndef COMMONS_ARRAY_H +#define COMMONS_ARRAY_H + +#include <boost/scoped_array.hpp> + +namespace commons { + + using namespace boost; + + /** + * A thin wrapper around arrays. Like a fixed-size vector. Unlike array + * since the size can be dynamically determined. + */ + template<typename T> + class array : public scoped_array<T> { + public: + explicit array(size_t n) : scoped_array<T>(new T[n]), n_(n) {} + size_t size() { return n_; } + private: + size_t n_; + }; + + //template<typename T> + // class array { + // public: + // explicit array(int n) : a(new T[n]) {} + // private: + // scoped_array<T> a; + // }; + +} + +#endif Added: cpp-commons/trunk/src/commons/pool.h =================================================================== --- cpp-commons/trunk/src/commons/pool.h (rev 0) +++ cpp-commons/trunk/src/commons/pool.h 2008-10-08 22:05:15 UTC (rev 1008) @@ -0,0 +1,63 @@ +#ifndef COMMONS_POOL_H +#define COMMONS_POOL_H + +#include <boost/circular_buffer.hpp> +#include <commons/array.h> + +namespace commons { + + using namespace boost; + + /** + * A fixed-size pool of resources. + */ + template<typename T> + class pool { + public: + /** + * Create a pool of size \p size. These resources are created and stored + * in an array. + * \param[in] size The number of elements to create. + */ + pool(int size) : xs(size), ps(size) { + for (size_t i = 0; i < xs.size(); i++) + ps.push_back(&xs[i]); + } + + /** + * Take an item from the pool. + * \throw exception The pool is empty. + */ + T *take() { + check(!ps.empty(), "taking from empty pool"); + T *p = ps[0]; + ps.pop_front(); + return p; + } + + /** + * Release an item back into the pool. This doesn't check that the pointer + * being released was one that was originally taken from this pool. + * \param[in] The pointer to release. + * \throw exception The pool is full. + */ + void drop(T *p) { + check(ps.size() < ps.max_size(), "dropping into full pool"); + ps.push_back(p); + } + + /** + * Get the number of (remaining) items in the pool. + */ + size_t size() { + return ps.size(); + } + + private: + array<T> xs; + circular_buffer<T*> ps; + }; + +} + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-11-30 22:22:25
|
Revision: 1077 http://assorted.svn.sourceforge.net/assorted/?rev=1077&view=rev Author: yangzhang Date: 2008-11-30 21:34:08 +0000 (Sun, 30 Nov 2008) Log Message: ----------- - added nullptr - delegates - added swallow - removed exception handling from run_function0 - st - updated stfd - cleaned up st_tcp_listen - split st_tcp_connect into overloads - added st_lock, st_join, st_mutex, st_cond, st_bool, st_channel, st_intr_hub, st_intr_cond, st_intr_bool, st_intr, st_group_join_exception, st_joining, st_thread_group - sockets - cleaned up casts - updated tcp_listen signature - check - added checkerr, checknnegerr, checkeqnneg - added some comments on how to revamp check.h Modified Paths: -------------- cpp-commons/trunk/src/commons/boost/delegates.h cpp-commons/trunk/src/commons/check.h cpp-commons/trunk/src/commons/sockets.h cpp-commons/trunk/src/commons/st/st.h Added Paths: ----------- cpp-commons/trunk/src/commons/nullptr.h Modified: cpp-commons/trunk/src/commons/boost/delegates.h =================================================================== --- cpp-commons/trunk/src/commons/boost/delegates.h 2008-11-29 07:51:27 UTC (rev 1076) +++ cpp-commons/trunk/src/commons/boost/delegates.h 2008-11-30 21:34:08 UTC (rev 1077) @@ -3,12 +3,20 @@ #include <boost/function.hpp> #include <boost/scoped_ptr.hpp> +#include <iostream> // for cerr namespace commons { using namespace boost; + using namespace std; + void + swallow(const function0<void> f) { + try { f(); } + catch (exception &ex) { cerr << ex.what() << endl; } + } + /** * Delegate for running a 0-ary void function. */ @@ -16,8 +24,7 @@ run_function0(void *p) { scoped_ptr< const function0<void> > pf((const function0<void>*) p); - try { (*pf)(); } - catch (exception ex) { cerr << ex.what() << endl; } + (*pf)(); } /** @@ -30,6 +37,17 @@ 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 (exception &ex) { return exception(ex); } +// } + } #endif Modified: cpp-commons/trunk/src/commons/check.h =================================================================== --- cpp-commons/trunk/src/commons/check.h 2008-11-29 07:51:27 UTC (rev 1076) +++ cpp-commons/trunk/src/commons/check.h 2008-11-30 21:34:08 UTC (rev 1077) @@ -1,16 +1,32 @@ #ifndef COMMONS_CHECK_H #define COMMONS_CHECK_H -#define buflen 4096 - #include <exception> #include <sstream> #include <string> #include <commons/die.h> +// TODO: rename: +// - chk(x): verifies and return x; if not, throw strerror +// - chk(x, msg...): prepend "$msg: " to strerror +// - chk(x, false): don't use errno/strerror +// - chk(x, false, msg...) +// - chknoret(x): doesn't return x and doesn't use strerror +// - chk0(x): verifies !x; if not, throw strerror +// - same overloads as chk +// - chkpos(x): returns x; if not positive, throw strerror +// - same overloads as chk +// - chknneg(x): returns x; if negative, throw strerror +// - same overloads as chk +// - chkeq(x,y): if x!=y, throw; if x<0, throw strerror +// +// - chkr(): same as chk but returns -1 instead of throwing + namespace commons { + enum { buflen = 4096 }; + // TODO: deal with va args // TODO: provide strerror in other functions too // TODO: better way to deal with errno? (rather than resetting it) @@ -22,7 +38,7 @@ public: check_exception(const string & name) : name(name) {} virtual ~check_exception() throw() {} - const char *what() const throw() { return name.c_str(); } + virtual const char *what() const throw() { return name.c_str(); } private: const string name; }; @@ -38,7 +54,6 @@ vsnprintf(buf, buflen, fmt, ap); ss << buf; } - ss << endl; throw check_exception(ss.str()); } } @@ -72,6 +87,28 @@ return x; } + template<typename T> inline T + _checknnegerr(T x, const char *file, int line) + { + if (x < 0) { + int e = errno; + errno = 0; + _check(x, file, line, "expecting >=0, got %d: %s", x, strerror(e)); + } + return x; + } + + template<typename T> inline T + _checkerr(T x, const char *file, int line) + { + if (!x) { + int e = errno; + errno = 0; + _check(x, file, line, "expecting !=0, got %d: %s", x, strerror(e)); + } + return x; + } + template<typename T> inline void _check0(T x, const char *file, int line) { @@ -97,6 +134,19 @@ } } + template<typename T, typename U> inline void + _checkeqnneg(T l, U r, const char *file, int line) + { + if (l < 0) { + int e = errno; + errno = 0; + _check(l == r, file, line, + "expecting %d, got %d: %s", r, l, strerror(e)); + } else { + _checkeq(l, r, file, line); + } + } + } /** @@ -117,11 +167,21 @@ #define checkpass(expr, msg...) _checkpass(expr, __FILE__, __LINE__, ## msg) /** + * Same as checkpass(), but includes the strerror message in the exception. + */ +#define checkerr(expr) _checkerr(expr, __FILE__, __LINE__) + +/** * Checks that the value is non-negative. */ #define checknneg(expr, msg...) _checknneg(expr, __FILE__, __LINE__, ## msg) /** + * Same as checknneg, but include the strerror in the exception. + */ +#define checknnegerr(expr) _checknnegerr(expr, __FILE__, __LINE__) + +/** * Checks that the value is 0. Same as check0(), but throws an error rather * than return. Also clears the errno on error. The resulting exception * includes the strerror(). @@ -134,6 +194,13 @@ */ #define checkeq(l, r, msg...) _checkeq(l, r, __FILE__, __LINE__, ## msg) +/** + * Like checkeq, but if the left value is negative, then interpret that as a + * sign of error, and include the errorstr in the exception message. + */ +#define checkeqnneg(l, r, msg...) \ + _checkeqnneg(l, r, __FILE__, __LINE__, ## msg) + #if 0 #define checkmsg(cond, msg) \ bool b__ = cond; \ Added: cpp-commons/trunk/src/commons/nullptr.h =================================================================== --- cpp-commons/trunk/src/commons/nullptr.h (rev 0) +++ cpp-commons/trunk/src/commons/nullptr.h 2008-11-30 21:34:08 UTC (rev 1077) @@ -0,0 +1,28 @@ +#ifndef COMMONS_NULLPTR_H +#define COMMONS_NULLPTR_H + +// From <http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/nullptr> + +namespace commons +{ + + const // It is a const object... + class nullptr_t + { + public: + template<class T> + operator T*() const // convertible to any type of null non-member pointer... + { return 0; } + + template<class C, class T> + operator T C::*() const // or any type of null member pointer... + { return 0; } + + private: + void operator&() const; // Can't take address of nullptr + + } nullptr = {}; + +} + +#endif Modified: cpp-commons/trunk/src/commons/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/sockets.h 2008-11-29 07:51:27 UTC (rev 1076) +++ cpp-commons/trunk/src/commons/sockets.h 2008-11-30 21:34:08 UTC (rev 1077) @@ -6,6 +6,8 @@ #include <netinet/in.h> #include <strings.h> #include <sys/socket.h> +#include <sys/types.h> +#include <fcntl.h> #include <unistd.h> #include <commons/check.h> @@ -20,7 +22,7 @@ * \return The server socket. */ int - server_socket(int port, bool nb = false) + server_socket(uint16_t port, bool nb = false) { // Create the socket. int fd = checknneg(socket(PF_INET, SOCK_STREAM, 0)); @@ -28,8 +30,8 @@ try { // Configure the socket. int n = 1; - check0x(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&n, - sizeof(n))); + check0x(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast<char *>(&n), sizeof(n))); // Make our socket non-blocking if desired. if (nb) { @@ -37,14 +39,14 @@ } // Create the local socket address. - struct sockaddr_in sa; + sockaddr_in sa; bzero(&sa, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(INADDR_ANY); // Bind the socket to the local socket address. - check0x(bind(fd, (struct sockaddr*) &sa, sizeof(struct sockaddr_in))); + check0x(bind(fd, (sockaddr*) &sa, sizeof sa)); return fd; } catch (...) { @@ -60,7 +62,7 @@ * \return The listener socket. */ int - tcp_listen(int port, bool nb = false) + tcp_listen(uint16_t port, bool nb = false) { int fd = server_socket(port, nb); try { Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2008-11-29 07:51:27 UTC (rev 1076) +++ cpp-commons/trunk/src/commons/st/st.h 2008-11-30 21:34:08 UTC (rev 1077) @@ -1,12 +1,22 @@ #ifndef COMMONS_ST_ST_H #define COMMONS_ST_ST_H +#include <exception> +#include <map> +#include <queue> +#include <set> +#include <sstream> #include <st.h> #include <stx.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 <boost/foreach.hpp> #include <boost/function.hpp> +#define foreach BOOST_FOREACH + namespace commons { using namespace boost; @@ -28,20 +38,32 @@ }; /** - * non-copyable. - * \todo remove? this seems to be bad if it closes the file! + * \todo Make non-copyable. */ class stfd { public: stfd(st_netfd_t fd) : fd_(fd), sclose(fd) {} - const st_netfd_t fd() const { return fd_; } + st_netfd_t fd() const { return fd_; } + operator st_netfd_t() const { return fd_; } private: const st_netfd_t fd_; st_closing sclose; }; /** + * RAII to acquire and release a st_mutex_t. Non-copyable. + */ + class st_lock + { + public: + st_lock(st_mutex_t mx) : mx_(mx) { check0x(st_mutex_lock(mx)); } + ~st_lock() { check0x(st_mutex_unlock(mx_)); } + private: + st_mutex_t mx_; + }; + + /** * 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 a pointer? @@ -55,36 +77,35 @@ default_stack_size); } + void + st_join(st_thread_t t) + { + check0x(st_thread_join(t, nullptr)); + } + /** * Connect to a TCP socket address. - * \param[in] host Either an IP address or hostname. + * \param[in] host An IP address. * \param[in] port The destination port. - * \param[in] timeout The timeout for each of the DNS lookup and the connect - * operation. - * \todo Create variants that take or return the sockaddr. + * \param[in] timeout The timeout for the connect operation. */ st_netfd_t - st_tcp_connect(char *host, int port, st_utime_t timeout) + st_tcp_connect(in_addr host, uint16_t port, st_utime_t timeout) { // Create remote socket address. struct sockaddr_in sa; bzero(&sa, sizeof sa); sa.sin_family = AF_INET; sa.sin_port = htons(port); + sa.sin_addr = host; - // First try to parse as IP address. Note: inet_addr() is obsolete. - if (inet_aton(host, &sa.sin_addr) != 0) { - // Then look up by hostname. - check0x(stx_dns_getaddr(host, &sa.sin_addr, timeout)); - } - // Create the socket. int sfd = checknneg(socket(PF_INET, SOCK_STREAM, 0)); st_netfd_t nfd = st_netfd_open_socket(sfd); // Connect. try { - check0x(st_connect(nfd, (struct sockaddr*) &sa, sizeof sa, timeout)); + check0x(st_connect(nfd, (sockaddr*) &sa, sizeof sa, timeout)); return nfd; } catch (...) { st_netfd_close(nfd); @@ -93,26 +114,261 @@ } /** + * Connect to a TCP socket address. + * \param[in] host Either an IP address or hostname. + * \param[in] port The destination port. + * \param[in] timeout The timeout for each of the DNS lookup and the connect + * operation. + * \todo Create variants that take and/or return sockaddr_in's. + */ + st_netfd_t + st_tcp_connect(const char *host, uint16_t port, st_utime_t timeout) + { + in_addr ipaddr; + + // First try to parse as IP address. Note: inet_addr() is obsolete. Note: + // inet_aton returns 0 if address is invalid. + if (inet_aton(host, &ipaddr) == 0) { + // Then look up by hostname. + check0x(stx_dns_getaddr(host, &ipaddr, timeout)); + } + + return st_tcp_connect(ipaddr, port, timeout); + } + + /** * Create a listener st_netfd_t. * \param[in] port The port to listen on. * \return The st_netfd_t. */ st_netfd_t - st_tcp_listen(int port) + st_tcp_listen(uint16_t port) { int sfd = tcp_listen(port); try { // Create a net file descriptor around a listener socket. - st_netfd_t nfd = st_netfd_open_socket(sfd); - checkpass(nfd); - //st_netfd_t nfd = checkpass(st_netfd_open_socket(sfd)); - return nfd; + return checkpass(st_netfd_open_socket(sfd)); } catch (...) { close(sfd); throw; } } + /** + * Wraps st_cond_* errno-functions with exceptions and cleans up on + * destruction. + */ + class st_cond + { + public: + st_cond() : c(checkerr(st_cond_new())) {} + ~st_cond() { check0x(st_cond_destroy(c)); } + void wait() { check0x(st_cond_wait(c)); } + void wait(st_utime_t t) { check0x(st_cond_timedwait(c, t)); } + void signal() { st_cond_signal(c); } + void bcast() { st_cond_broadcast(c); } + private: + st_cond_t c; + }; + + /** + * Synchronized boolean. + */ + class st_bool + { + public: + st_bool(bool init = false) : b(init) {} + void set() { b = true; c.bcast(); } + void reset() { b = false; c.bcast(); } + void waitset() { if (!b) c.wait(); } + void waitreset() { if (b) c.wait(); } + operator bool() { return b; } + private: + st_cond c; + bool b; + }; + + /** + * Wraps st_mutex_* errno-functions with exceptions and cleans up on + * destruction. + */ + class st_mutex + { + public: + st_mutex() : m(checkerr(st_mutex_new())) {} + ~st_mutex() { check0x(st_mutex_destroy(m)); } + void lock() { check0x(st_mutex_lock(m)); } + bool trylock() { + int res = st_mutex_trylock(m); + if (res == 0) return true; + else if (errno == EBUSY) return false; + else check0x(res); + } + void unlock() { check0x(st_mutex_unlock(m)); } + private: + st_mutex_t m; + }; + + /** + * An unbounded FIFO queue. ST threads can wait on this until elements have + * been pushed in (resulting in a waking signal). + */ + template <typename T> + class st_channel + { + public: + void push(const T &x) { + q_.push(x); + empty_.signal(); + } + T take() { + while (q_.empty()) + empty_.wait(); + T x = front(); + q_.pop(); + return x; + } + const T& front() const { return q_.front(); } + bool empty() const { return q_.empty(); } + void pop() { q_.pop(); } + void clear() { while (!q_.empty()) q_.pop(); } + const std::queue<T> &queue() const { return q_; } + private: + std::queue<T> q_; + st_cond empty_; + }; + + /** + * A hub is a single point to signal to wake up a set of threads. Threads + * join the hub before calling a blocking operation if they want to make + * themselves interruptible on this hub. + */ + class st_intr_hub + { + public: + virtual void insert(st_thread_t t) = 0; + virtual void erase(st_thread_t t) = 0; + }; + + /** + * The simplest hub, which only interrupts those who are currently joined in + * the hub (like a condition variable broadcast). + */ + class st_intr_cond : public st_intr_hub + { + public: + void insert(st_thread_t t) { threads.insert(t); } + void erase(st_thread_t t) { threads.erase(t); } + void signal() { + foreach (st_thread_t t, threads) { + st_thread_interrupt(t); + } + threads.clear(); + } + private: + set<st_thread_t> threads; + }; + + /** + * Like st_intr_cond, but a bool instead, so there's state; newly joining + * threads may immediately be interrupted. Interruption occurs when this is + * set to true. + */ + class st_intr_bool : public st_intr_hub + { + public: + void insert(st_thread_t t) { + if (b) st_thread_interrupt(t); + else threads.insert(t); + } + void erase(st_thread_t t) { threads.erase(t); } + void set() { + b = true; + foreach (st_thread_t t, threads) { + st_thread_interrupt(t); + } + threads.clear(); + } + void reset() { + // If b is true, then any threads that join are immediately + // interrupted, so the set must be empty. + assert(!b || threads.empty()); + b = false; + } + operator bool() const { return b; } + private: + std::set<st_thread_t> threads; + bool b; + }; + + /** + * RAII for making the current thread interruptible on a certain hub. + */ + class st_intr + { + public: + st_intr(st_intr_hub &hub) : hub_(hub) { hub.insert(st_thread_self()); } + ~st_intr() { hub_.erase(st_thread_self()); } + private: + st_intr_hub &hub_; + }; + + class st_group_join_exception : public exception + { + public: + st_group_join_exception(const map<st_thread_t, 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; + foreach (p p, th2ex_) { + ss << (first ? "" : ", ") << p.first << " -> " << p.second.what(); + first = false; + } + const_cast<string&>(s) = ss.str(); + } + return s.c_str(); + } + private: + map<st_thread_t, exception> th2ex_; + string s; + }; + + /** + * RAII for joining on a single thread. + */ + class st_joining + { + public: + st_joining(st_thread_t t) : t_(t) {} + ~st_joining() { st_join(t_); } + private: + st_thread_t t_; + }; + + /** + * RAII for joining on all contained threads. Warning: st_join may throw + * exceptions. + */ + class st_thread_group + { + public: + ~st_thread_group() { + map<st_thread_t, exception> th2ex; + foreach (st_thread_t t, ts) { + try { st_join(t); } + catch (exception &ex) { th2ex[t] = ex; } + } + if (!th2ex.empty()) throw st_group_join_exception(th2ex); + } + void insert(st_thread_t t) { ts.insert(t); } + private: + set<st_thread_t> ts; + }; + } #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-13 20:54:54
|
Revision: 1177 http://assorted.svn.sourceforge.net/assorted/?rev=1177&view=rev Author: yangzhang Date: 2009-02-13 20:54:46 +0000 (Fri, 13 Feb 2009) Log Message: ----------- - added release to closing - made closingfd publically inherit closing - refactored and cleaned up sockets code - added st_reader - fixed formatting bugs in check messages - added auto_array, array_view Modified Paths: -------------- cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/check.h cpp-commons/trunk/src/commons/closing.h cpp-commons/trunk/src/commons/sockets.h cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-02-11 19:59:53 UTC (rev 1176) +++ cpp-commons/trunk/src/commons/array.h 2009-02-13 20:54:46 UTC (rev 1177) @@ -2,6 +2,8 @@ #define COMMONS_ARRAY_H #include <boost/scoped_array.hpp> +#include <commons/check.h> +#include <commons/nullptr.h> namespace commons { @@ -14,20 +16,54 @@ template<typename T> class array : public scoped_array<T> { public: - explicit array(size_t n) : scoped_array<T>(new T[n]), n_(n) {} + explicit array(size_t n) : scoped_array<T>(checkpass(new T[n])), n_(n) {} size_t size() { return n_; } + char *end() { return this->get() + n_; } private: size_t n_; }; - //template<typename T> - // class array { - // public: - // explicit array(int n) : a(new T[n]) {} - // private: - // scoped_array<T> a; - // }; + /** + * A release-able array. + */ + template<typename T> + class auto_array { + public: + auto_array(T *p) : p_(p) {} + ~auto_array() { if (p_ != nullptr) delete [] p_; } + T *release() { T *p = p_; p_ = nullptr; return p; } + T *get() { return p_; } + const T *get() const { return p_; } + operator T*() { return p_; } + operator const T*() const { return p_; } + private: + T *p_; + }; + /** + * Move-able, conditionally-scoped array. + * + * TODO: rename to managed_array + */ + template<typename T> + class array_view { + public: + array_view(T *p, bool scoped) : p_(p), scoped_(scoped) {} +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + array_view(array_view<T> &&a) : p_(a.p_), scoped_(a.scoped_) { a.release(); } +#endif + ~array_view() { if (scoped_) delete [] p_; } + T *release() { T *p = p_; p_ = nullptr; scoped_ = false; return p; } + T *get() { return p_; } + const T *get() const { return p_; } + operator T*() { return p_; } + operator const T*() const { return p_; } + bool scoped() const { return scoped_; } + private: + T *p_; + bool scoped_; + }; + } #endif Modified: cpp-commons/trunk/src/commons/check.h =================================================================== --- cpp-commons/trunk/src/commons/check.h 2009-02-11 19:59:53 UTC (rev 1176) +++ cpp-commons/trunk/src/commons/check.h 2009-02-13 20:54:46 UTC (rev 1177) @@ -23,6 +23,8 @@ // // - chkr(): same as chk but returns -1 instead of throwing +// TODO: incorporate __PRETTY_FUNCTION__ + namespace commons { @@ -60,7 +62,7 @@ } } - __attribute__((format(printf, 4, 5))) inline void + __attribute__((format(printf, 4, 5))) void _check(bool cond, const char *file, int line, const char *fmt, ...) { va_list ap; @@ -85,7 +87,11 @@ template<typename T> inline T _checknneg(T x, const char *file, int line) { - _check(x >= 0, file, line, "expecting non-negative, got %d", x); + if (x < 0) { + stringstream ss; + ss << "expecting non-negative, got " << x; + _check(false, file, line, "%s", ss.str().c_str()); + } return x; } @@ -95,7 +101,9 @@ if (x < 0) { int e = errno; errno = 0; - _check(x, file, line, "expecting >=0, got %d: %s", x, strerror(e)); + stringstream ss; + ss << "expecting >=0, got " << x << ": " << strerror(e); + _check(false, file, line, "%s", ss.str().c_str()); } return x; } @@ -106,8 +114,9 @@ if (!x) { int e = errno; errno = 0; - _check(x, file, line, "expecting !=0, got %s: %s", - lexical_cast<string>(x).c_str(), strerror(e)); + stringstream ss; + ss << "expecting !=0, got " << x << ": " << strerror(e); + _check(false, file, line, "%s", ss.str().c_str()); } return x; } Modified: cpp-commons/trunk/src/commons/closing.h =================================================================== --- cpp-commons/trunk/src/commons/closing.h 2009-02-11 19:59:53 UTC (rev 1176) +++ cpp-commons/trunk/src/commons/closing.h 2009-02-13 20:54:46 UTC (rev 1177) @@ -8,13 +8,16 @@ class closing { public: - closing(T x) : x(x) {} - ~closing() { close(x); } + closing(T x) : x(x), scoped(true) {} + ~closing() { if (scoped) close(x); } + T get() { return x; } + T release() { scoped = false; return x; } private: T x; + bool scoped; }; - class closingfd : closing<int> { + class closingfd : public closing<int> { public: closingfd(int x) : closing<int>(x) {} }; Modified: cpp-commons/trunk/src/commons/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/sockets.h 2009-02-11 19:59:53 UTC (rev 1176) +++ cpp-commons/trunk/src/commons/sockets.h 2009-02-13 20:54:46 UTC (rev 1177) @@ -11,11 +11,78 @@ #include <unistd.h> #include <commons/check.h> +#include <commons/closing.h> +#include <commons/nullptr.h> namespace commons { /** + * Create a TCP socket. + */ + int + tcp_socket(bool nb) + { + int fd = checknnegerr(socket(PF_INET, SOCK_STREAM, 0)); + // Make our socket non-blocking if desired. + if (nb) + checknnegerr(fcntl(fd, F_SETFL, O_NONBLOCK | fcntl(fd, F_GETFL, 0))); + return fd; + } + + /** + * Initialize an inet address with just the port. + */ + void + sockaddr_init(sockaddr_in &a, uint16_t port) + { + bzero(&a, sizeof a); + a.sin_family = AF_INET; + a.sin_port = htons(port); + } + + /** + * Initialize an inet address. + */ + void + sockaddr_init(sockaddr_in &a, const char *host, uint16_t port) + { + sockaddr_init(a, port); + if (host == nullptr) { + a.sin_addr.s_addr = htonl(INADDR_ANY); + } else { + // First try to interpret host as a dot-notation string. + if (!inet_aton(host, (struct in_addr *) &a.sin_addr.s_addr)) { + // Now try to resolve the hostname. + struct hostent *res = checkpass(gethostbyname(host)); + memcpy(&a.sin_addr, res->h_addr_list[0], res->h_length); + } + } + } + + /** + * Initialize an inet address. + */ + void + sockaddr_init(sockaddr_in &a, in_addr host, uint16_t port) + { + sockaddr_init(a, port); + a.sin_addr = host; + } + + /** + * Construct an inet address. + */ + template <typename T> + sockaddr_in + make_sockaddr(T host, uint16_t port) + { + sockaddr_in a; + sockaddr_init(a, host, port); + return a; + } + + /** * Create a server socket bound to localhost, with SO_REUSEADDR enabled. * \param[in] port The port to listen on. * \param[in] nb Whether the socket should be non-blocking. @@ -25,34 +92,21 @@ server_socket(uint16_t port, bool nb = false) { // Create the socket. - int fd = checknneg(socket(PF_INET, SOCK_STREAM, 0)); + closingfd c(tcp_socket(nb)); + int fd = c.get(); - try { - // Configure the socket. - int n = 1; - check0x(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - reinterpret_cast<char *>(&n), sizeof(n))); + // Configure the socket. + int n = 1; + check0x(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast<char*>(&n), sizeof(n))); - // Make our socket non-blocking if desired. - if (nb) { - checknneg(fcntl(fd, F_SETFL, O_NONBLOCK | fcntl(fd, F_GETFL, 0))); - } + // Create the local socket address. + sockaddr_in sa = make_sockaddr(nullptr, port); - // Create the local socket address. - sockaddr_in sa; - bzero(&sa, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - sa.sin_addr.s_addr = htonl(INADDR_ANY); + // Bind the socket to the local socket address. + check0x(::bind(fd, (sockaddr*) &sa, sizeof sa)); - // Bind the socket to the local socket address. - check0x(::bind(fd, (sockaddr*) &sa, sizeof sa)); - - return fd; - } catch (...) { - close(fd); - throw; - } + return c.release(); } /** @@ -75,6 +129,19 @@ throw; } } + + /** + * Connect to a TCP socket. + */ + int + tcp_connect(const char *host, uint16_t port) + { + closingfd c(tcp_socket(false)); + sockaddr_in a = make_sockaddr(host, port); + check0x(connect(c.get(), reinterpret_cast<sockaddr*>(&a), sizeof a)); + return c.release(); + } + } #endif Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-11 19:59:53 UTC (rev 1176) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-13 20:54:46 UTC (rev 1177) @@ -1,6 +1,7 @@ #ifndef COMMONS_ST_ST_H #define COMMONS_ST_ST_H +#include <algorithm> #include <exception> #include <map> #include <queue> @@ -8,14 +9,17 @@ #include <sstream> #include <st.h> #include <stx.h> +#include <commons/array.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 <boost/foreach.hpp> #include <boost/function.hpp> +#include <boost/shared_ptr.hpp> #define foreach BOOST_FOREACH +#define shared_ptr boost::shared_ptr namespace commons { @@ -31,7 +35,7 @@ { public: st_closing(st_netfd_t x) : attached(true), x(x) {} - ~st_closing() { if (attached) st_netfd_close(x); } + ~st_closing() { if (attached) check0x(st_netfd_close(x)); } void detach() { attached = false; } private: bool attached; @@ -47,6 +51,7 @@ stfd(st_netfd_t fd) : fd_(fd), sclose(fd) {} st_netfd_t fd() const { return fd_; } operator st_netfd_t() const { return fd_; } + st_netfd_t release() { sclose.detach(); return fd_; } private: const st_netfd_t fd_; st_closing sclose; @@ -94,24 +99,14 @@ st_tcp_connect(in_addr host, uint16_t port, st_utime_t timeout) { // Create remote socket address. - struct sockaddr_in sa; - bzero(&sa, sizeof sa); - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - sa.sin_addr = host; + sockaddr_in sa = make_sockaddr(host, port); // Create the socket. - int sfd = checknnegerr(socket(PF_INET, SOCK_STREAM, 0)); - st_netfd_t nfd = st_netfd_open_socket(sfd); + stfd s(checkpass(st_netfd_open_socket(tcp_socket(true)))); // Connect. - try { - check0x(st_connect(nfd, (sockaddr*) &sa, sizeof sa, timeout)); - return nfd; - } catch (...) { - check0x(st_netfd_close(nfd)); - throw; - } + check0x(st_connect(s.fd(), reinterpret_cast<sockaddr*>(&sa), sizeof sa, timeout)); + return s.release(); } /** @@ -394,6 +389,100 @@ std::set<st_thread_t> ts; }; + class eof_exception : public std::exception { + const char *what() const throw() { return "EOF"; } + }; + + /** + * Convenience class for reading from sockets. + */ + class st_reader + { + public: + st_reader(st_netfd_t fd, size_t bufsize = 1e7) : + fd_(fd), + buf_(bufsize), + start_(buf_.get()), + end_(buf_.get()) + {} + + /** + * The size of the unconsumed range of bytes. + */ + size_t amt() { return end_ - start_; } + + /** + * The remaining number of bytes in the buffer + */ + size_t rem() { return buf_.end() - end_; } + + /** + * Returns a char array that contains the requested number of bytes. If + * we hit an error or EOF, then an exception is thrown. + */ + array_view<char> read(size_t req = 0, st_utime_t to = ST_UTIME_NO_TIMEOUT) { + // Do we already have the requested data? + if (amt() >= req) { + array_view<char> p(start_, false); + start_ += req; + return p; + } + + // Handle large arrays specially. + if (req > buf_.size()) { + array_view<char> p(checkpass(new char[req]), true); + copy(start_, end_, p.get()); + checkeqnneg(st_read_fully(fd_, p + amt(), req, to), static_cast<ssize_t>(req)); + start_ = end_ = buf_.get(); + return p; + } + + // Shift things down if necessary. + if (req > static_cast<size_t>(buf_.end() - end_)) { + copy(start_, end_, buf_.get()); + size_t diff = start_ - buf_.get(); + start_ -= diff; + end_ -= diff; + } + + // Keep reading until we have enough. + while (amt() < req) { + ssize_t res = st_read(fd_, end_, rem(), to); + checknneg(res); + if (res == 0) break; + else end_ += res; + } + + // If we got a premature EOF. + if (amt() < req) + throw eof_exception(); + + array_view<char> p(start_, false); + start_ += req; + return p; + } + + private: + st_reader(const st_reader &); + + st_netfd_t fd_; + + /** + * The temporary storage buffer. + */ + array<char> buf_; + + /** + * The start of the unconsumed range of bytes. + */ + char *start_; + + /** + * The end of the unconsumed range of bytes. + */ + char *end_; + }; + } #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-17 04:33:57
|
Revision: 1186 http://assorted.svn.sourceforge.net/assorted/?rev=1186&view=rev Author: yangzhang Date: 2009-02-17 04:33:52 +0000 (Tue, 17 Feb 2009) Log Message: ----------- - renamed array_view to managed_array - added read<T>() to st_reader Modified Paths: -------------- cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-02-16 21:05:26 UTC (rev 1185) +++ cpp-commons/trunk/src/commons/array.h 2009-02-17 04:33:52 UTC (rev 1186) @@ -24,7 +24,7 @@ }; /** - * A release-able array. + * A scoped, release-able array. */ template<typename T> class auto_array { @@ -41,18 +41,16 @@ }; /** - * Move-able, conditionally-scoped array. - * - * TODO: rename to managed_array + * Conditionally-scoped, move-able, release-able, un-sized array. */ template<typename T> - class array_view { + class managed_array { public: - array_view(T *p, bool scoped) : p_(p), scoped_(scoped) {} + managed_array(T *p, bool scoped) : p_(p), scoped_(scoped) {} #ifdef __GXX_EXPERIMENTAL_CXX0X__ - array_view(array_view<T> &&a) : p_(a.p_), scoped_(a.scoped_) { a.release(); } + managed_array(managed_array<T> &&a) : p_(a.p_), scoped_(a.scoped_) { a.release(); } #endif - ~array_view() { if (scoped_) delete [] p_; } + ~managed_array() { if (scoped_) delete [] p_; } T *release() { T *p = p_; p_ = nullptr; scoped_ = false; return p; } T *get() { return p_; } const T *get() const { return p_; } Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-16 21:05:26 UTC (rev 1185) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-17 04:33:52 UTC (rev 1186) @@ -420,17 +420,17 @@ * Returns a char array that contains the requested number of bytes. If * we hit an error or EOF, then an exception is thrown. */ - array_view<char> read(size_t req = 0, st_utime_t to = ST_UTIME_NO_TIMEOUT) { + managed_array<char> read(size_t req = 0, st_utime_t to = ST_UTIME_NO_TIMEOUT) { // Do we already have the requested data? if (amt() >= req) { - array_view<char> p(start_, false); + managed_array<char> p(start_, false); start_ += req; return p; } // Handle large arrays specially. if (req > buf_.size()) { - array_view<char> p(checkpass(new char[req]), true); + managed_array<char> p(checkpass(new char[req]), true); copy(start_, end_, p.get()); checkeqnneg(st_read_fully(fd_, p + amt(), req, to), static_cast<ssize_t>(req)); start_ = end_ = buf_.get(); @@ -457,11 +457,50 @@ if (amt() < req) throw eof_exception(); - array_view<char> p(start_, false); + managed_array<char> p(start_, false); start_ += req; return p; } + template<typename T> + T read(st_utime_t to = ST_UTIME_NO_TIMEOUT) + { + size_t req = sizeof(T); + + // Do we already have the requested data? + if (amt() >= req) { + T x = *reinterpret_cast<const T*>(start_); + start_ += req; + return x; + } + + assert(req <= buf_.size()); + + // Shift things down if necessary. + if (req > static_cast<size_t>(buf_.end() - end_)) { + copy(start_, end_, buf_.get()); + size_t diff = start_ - buf_.get(); + start_ -= diff; + end_ -= diff; + } + + // Keep reading until we have enough. + while (amt() < req) { + ssize_t res = st_read(fd_, end_, rem(), to); + checknneg(res); + if (res == 0) break; + else end_ += res; + } + + // If we got a premature EOF. + if (amt() < req) + throw eof_exception(); + + T x = *reinterpret_cast<const T*>(start_); + start_ += req; + return x; + } + private: st_reader(const st_reader &); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-20 19:37:42
|
Revision: 1210 http://assorted.svn.sourceforge.net/assorted/?rev=1210&view=rev Author: yangzhang Date: 2009-02-20 19:37:33 +0000 (Fri, 20 Feb 2009) Log Message: ----------- added exceptions; fixed delegates.h inclusion guard Modified Paths: -------------- cpp-commons/trunk/src/commons/boost/delegates.h Added Paths: ----------- cpp-commons/trunk/src/commons/exceptions.h Modified: cpp-commons/trunk/src/commons/boost/delegates.h =================================================================== --- cpp-commons/trunk/src/commons/boost/delegates.h 2009-02-20 19:04:02 UTC (rev 1209) +++ cpp-commons/trunk/src/commons/boost/delegates.h 2009-02-20 19:37:33 UTC (rev 1210) @@ -1,5 +1,5 @@ -#ifndef COMMONS_DELEGATES_H -#define COMMONS_DELEGATES_H +#ifndef COMMONS_BOOST_DELEGATES_H +#define COMMONS_BOOST_DELEGATES_H #include <boost/function.hpp> #include <boost/scoped_ptr.hpp> Added: cpp-commons/trunk/src/commons/exceptions.h =================================================================== --- cpp-commons/trunk/src/commons/exceptions.h (rev 0) +++ cpp-commons/trunk/src/commons/exceptions.h 2009-02-20 19:37:33 UTC (rev 1210) @@ -0,0 +1,25 @@ +#ifndef COMMONS_EXCEPTIONS_H +#define COMMONS_EXCEPTIONS_H + +#include <exception> + +namespace commons +{ + + using namespace std; + + class operation_not_supported : public std::exception + { + public: + operation_not_supported(const string &op) : msg("operation not supported: " + op) {} + ~operation_not_supported() throw() {} + const char *what() const throw() { return msg.c_str(); } + private: + const string msg; + }; + +#define throw_operation_not_supported() throw operation_not_supported(__PRETTY_FUNCTION__) + +} + +#endif 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:33:38
|
Revision: 1216 http://assorted.svn.sourceforge.net/assorted/?rev=1216&view=rev Author: yangzhang Date: 2009-02-22 06:33:36 +0000 (Sun, 22 Feb 2009) Log Message: ----------- - added utility.h with NONCOPYABLE and EXPAND - fixed a bunch of warnings - re-organized closing, closingfd, st_closing/stfd - added unique_ptr.hpp - re-did the array classes Modified Paths: -------------- cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/boost/delegates.h cpp-commons/trunk/src/commons/closing.h cpp-commons/trunk/src/commons/rand.h cpp-commons/trunk/src/commons/sockets.h cpp-commons/trunk/src/commons/st/st.h Added Paths: ----------- cpp-commons/trunk/src/commons/boost/unique_ptr.hpp cpp-commons/trunk/src/commons/utility.h Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-02-22 00:14:14 UTC (rev 1215) +++ cpp-commons/trunk/src/commons/array.h 2009-02-22 06:33:36 UTC (rev 1216) @@ -2,8 +2,10 @@ #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/utility.h> namespace commons { @@ -14,37 +16,26 @@ * since the size can be dynamically determined. */ template<typename T> - class array : public scoped_array<T> { + class array { + EXPAND(unique_ptr<T[]>) public: - explicit array(size_t n) : scoped_array<T>(checkpass(new T[n])), n_(n) {} - size_t size() { return n_; } - char *end() { return this->get() + n_; } + 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 *end() const { return this->get() + n_; } + T operator[](size_t i) const { return p_[i]; } private: + unique_ptr<T[]> p_; size_t n_; }; /** - * A scoped, release-able array. - */ - template<typename T> - class auto_array { - public: - auto_array(T *p) : p_(p) {} - ~auto_array() { if (p_ != nullptr) delete [] p_; } - T *release() { T *p = p_; p_ = nullptr; return p; } - T *get() { return p_; } - const T *get() const { return p_; } - operator T*() { return p_; } - operator const T*() const { return p_; } - private: - T *p_; - }; - - /** * Conditionally-scoped, move-able, release-able, un-sized array. */ template<typename T> class managed_array { + NONCOPYABLE(managed_array) public: managed_array(T *p, bool scoped) : p_(p), scoped_(scoped) {} #ifdef __GXX_EXPERIMENTAL_CXX0X__ Modified: cpp-commons/trunk/src/commons/boost/delegates.h =================================================================== --- cpp-commons/trunk/src/commons/boost/delegates.h 2009-02-22 00:14:14 UTC (rev 1215) +++ cpp-commons/trunk/src/commons/boost/delegates.h 2009-02-22 06:33:36 UTC (rev 1216) @@ -11,8 +11,10 @@ using namespace boost; using namespace std; + typedef std::function<void()> fn; + void - swallow(const function0<void> f) { + swallow(const fn f) { try { f(); } catch (std::exception &ex) { cerr << ex.what() << endl; } } @@ -21,9 +23,9 @@ * Delegate for running a 0-ary void function. */ void - run_function0(void *p) + run_function0(const void *p) { - scoped_ptr< const function0<void> > pf((const function0<void>*) p); + scoped_ptr<const fn> pf(reinterpret_cast<const fn*>(p)); (*pf)(); } Added: cpp-commons/trunk/src/commons/boost/unique_ptr.hpp =================================================================== --- cpp-commons/trunk/src/commons/boost/unique_ptr.hpp (rev 0) +++ cpp-commons/trunk/src/commons/boost/unique_ptr.hpp 2009-02-22 06:33:36 UTC (rev 1216) @@ -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 Modified: cpp-commons/trunk/src/commons/closing.h =================================================================== --- cpp-commons/trunk/src/commons/closing.h 2009-02-22 00:14:14 UTC (rev 1215) +++ cpp-commons/trunk/src/commons/closing.h 2009-02-22 06:33:36 UTC (rev 1216) @@ -1,26 +1,35 @@ #ifndef COMMONS_CLOSING_H #define COMMONS_CLOSING_H -namespace +#include <boost/utility.hpp> +#include <commons/check.h> +#include <commons/utility.h> + +namespace commons { - template<typename T> + using namespace boost; + + // void checked_close(int &fd) { check0x(close(fd)); } + + struct fd_closer { static void apply(int fd) { check0x(close(fd)); } }; + + template<typename T, typename Closer> class closing { + NONCOPYABLE(closing) public: closing(T x) : x(x), scoped(true) {} - ~closing() { if (scoped) close(x); } + ~closing() { if (scoped) Closer::apply(x); } T get() { return x; } + operator T() { return x; } T release() { scoped = false; return x; } private: T x; bool scoped; }; - class closingfd : public closing<int> { - public: - closingfd(int x) : closing<int>(x) {} - }; + typedef closing<int, fd_closer> closingfd; } Modified: cpp-commons/trunk/src/commons/rand.h =================================================================== --- cpp-commons/trunk/src/commons/rand.h 2009-02-22 00:14:14 UTC (rev 1215) +++ cpp-commons/trunk/src/commons/rand.h 2009-02-22 06:33:36 UTC (rev 1216) @@ -16,7 +16,7 @@ private: unsigned long randx; public: - inline posix_rand(long s = 0) { randx = s; } + inline posix_rand(long s = 0) : randx(s) {} inline void seed(long s) { randx = s; } inline long abs(long x) { return x & 0x7fffffff; } inline long draw() { return randx = randx * 1103515245 + 12345; } Modified: cpp-commons/trunk/src/commons/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/sockets.h 2009-02-22 00:14:14 UTC (rev 1215) +++ cpp-commons/trunk/src/commons/sockets.h 2009-02-22 06:33:36 UTC (rev 1216) @@ -52,9 +52,9 @@ a.sin_addr.s_addr = htonl(INADDR_ANY); } else { // First try to interpret host as a dot-notation string. - if (!inet_aton(host, (struct in_addr *) &a.sin_addr.s_addr)) { + if (!inet_aton(host, reinterpret_cast<in_addr*>(&a.sin_addr.s_addr))) { // Now try to resolve the hostname. - struct hostent *res = checkpass(gethostbyname(host)); + hostent *res = checkpass(gethostbyname(host)); memcpy(&a.sin_addr, res->h_addr_list[0], res->h_length); } } @@ -104,7 +104,7 @@ sockaddr_in sa = make_sockaddr(nullptr, port); // Bind the socket to the local socket address. - check0x(::bind(fd, (sockaddr*) &sa, sizeof sa)); + check0x(::bind(fd, reinterpret_cast<sockaddr*>(&sa), sizeof sa)); return c.release(); } Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-22 00:14:14 UTC (rev 1215) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-22 06:33:36 UTC (rev 1216) @@ -14,6 +14,7 @@ // 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> #include <boost/shared_ptr.hpp> @@ -28,40 +29,18 @@ enum { default_stack_size = 65536 }; - /** - * RAII to st_netfd_close() a netfd. - */ - class st_closing - { - public: - st_closing(st_netfd_t x) : attached(true), x(x) {} - ~st_closing() { if (attached) check0x(st_netfd_close(x)); } - void detach() { attached = false; } - private: - bool attached; - st_netfd_t x; + struct stfd_closer { + static void apply(st_netfd_t fd) { check0x(st_netfd_close(fd)); } }; - /** - * \todo Make non-copyable. - */ - class stfd - { - public: - stfd(st_netfd_t fd) : fd_(fd), sclose(fd) {} - st_netfd_t fd() const { return fd_; } - operator st_netfd_t() const { return fd_; } - st_netfd_t release() { sclose.detach(); return fd_; } - private: - const st_netfd_t fd_; - st_closing sclose; - }; + typedef closing<st_netfd_t, stfd_closer> st_closing; /** * RAII to acquire and release a st_mutex_t. Non-copyable. */ class st_lock { + NONCOPYABLE(st_lock) public: st_lock(st_mutex_t mx) : mx_(mx) { check0x(st_mutex_lock(mx)); } ~st_lock() { check0x(st_mutex_unlock(mx_)); } @@ -78,7 +57,7 @@ st_spawn(const function0<void>& f) { return st_thread_create(&run_function0_null, - (void*) new function0<void>(f), + new function0<void>(f), true, default_stack_size); } @@ -102,10 +81,10 @@ sockaddr_in sa = make_sockaddr(host, port); // Create the socket. - stfd s(checkpass(st_netfd_open_socket(tcp_socket(true)))); + st_closing s(checkpass(st_netfd_open_socket(tcp_socket(true)))); // Connect. - check0x(st_connect(s.fd(), reinterpret_cast<sockaddr*>(&sa), sizeof sa, timeout)); + check0x(st_connect(s.get(), reinterpret_cast<sockaddr*>(&sa), sizeof sa, timeout)); return s.release(); } @@ -156,6 +135,7 @@ */ class st_cond { + NONCOPYABLE(st_cond) public: st_cond() : c(checkerr(st_cond_new())) {} ~st_cond() { check0x(st_cond_destroy(c)); } @@ -173,7 +153,7 @@ class st_bool { public: - st_bool(bool init = false) : b(init) {} + st_bool(bool init = false) : c(), b(init) {} void set() { b = true; c.bcast(); } void reset() { b = false; c.bcast(); } void waitset() { if (!b) c.wait(); } @@ -192,6 +172,7 @@ */ class st_mutex { + NONCOPYABLE(st_mutex) public: st_mutex() : m(checkerr(st_mutex_new())) {} ~st_mutex() { check0x(st_mutex_destroy(m)); } @@ -268,6 +249,7 @@ public: virtual void insert(st_thread_t t) = 0; virtual void erase(st_thread_t t) = 0; + virtual ~st_intr_hub() {}; }; /** @@ -277,6 +259,7 @@ class st_intr_cond : public st_intr_hub { public: + virtual ~st_intr_cond() {} void insert(st_thread_t t) { threads.insert(t); } void erase(st_thread_t t) { threads.erase(t); } void signal() { @@ -348,13 +331,13 @@ ss << (first ? "" : ", ") << p.first << " -> " << p.second.what(); first = false; } - const_cast<string&>(s) = ss.str(); + s = ss.str(); } return s.c_str(); } private: map<st_thread_t, std::exception> th2ex_; - string s; + mutable string s; }; /** @@ -362,6 +345,7 @@ */ class st_joining { + NONCOPYABLE(st_joining) public: st_joining(st_thread_t t) : t_(t) {} ~st_joining() { st_join(t_); } @@ -398,6 +382,7 @@ */ class st_reader { + NONCOPYABLE(st_reader) public: st_reader(st_netfd_t fd, size_t bufsize = 1e7) : fd_(fd), @@ -500,8 +485,6 @@ } private: - st_reader(const st_reader &); - st_netfd_t fd_; /** Added: cpp-commons/trunk/src/commons/utility.h =================================================================== --- cpp-commons/trunk/src/commons/utility.h (rev 0) +++ cpp-commons/trunk/src/commons/utility.h 2009-02-22 06:33:36 UTC (rev 1216) @@ -0,0 +1,14 @@ +#ifndef COMMONS_UTILITY_H +#define COMMONS_UTILITY_H + +/** For use within a type definition. Makes the type non-copyable. */ +#define NONCOPYABLE(type) \ + private: \ + type(const type&); \ + void operator=(const type&); + +/** For use within a type definition. Documents that the type is intended to + * expand the given type. */ +#define EXPAND(type) + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-22 07:46:02
|
Revision: 1221 http://assorted.svn.sourceforge.net/assorted/?rev=1221&view=rev Author: yangzhang Date: 2009-02-22 07:45:59 +0000 (Sun, 22 Feb 2009) Log Message: ----------- added yonat C++ tools Added Paths: ----------- cpp-commons/trunk/src/commons/yonat/ cpp-commons/trunk/src/commons/yonat/pointainer.h cpp-commons/trunk/src/commons/yonat/pointerator.h cpp-commons/trunk/src/commons/yonat/stringizer.h Added: cpp-commons/trunk/src/commons/yonat/pointainer.h =================================================================== --- cpp-commons/trunk/src/commons/yonat/pointainer.h (rev 0) +++ cpp-commons/trunk/src/commons/yonat/pointainer.h 2009-02-22 07:45:59 UTC (rev 1221) @@ -0,0 +1,129 @@ +/* + * pointainer - auto-cleaning container of pointers + * + * Example usage: + * { + * pointainer< std::vector<int*> > v; + * // v can be manipulated like any std::vector<int*>. + * + * v.push_back(new int(42)); + * v.push_back(new int(17)); + * // v now owns the allocated int-s + * + * v.erase(v.begin()); + * // frees the memory allocated for the int 42, and then removes the + * // first element of v. + * } + * // v's destructor is called, and it frees the memory allocated for + * // the int 17. + * + * Notes: + * 1. Assumes all elements are unique (you don't have two elements + * pointing to the same object, otherwise you might delete it twice). + * 2. Not usable with pair associative containers (map and multimap). + * 3. For ANSI-challenged compilers, you may want to #define + * NO_MEMBER_TEMPLATES. + * + * Written 10-Jan-1999 by Yonat Sharon <yo...@oo...> + * Last updated 07-Feb-1999 + */ + +#ifndef POINTAINER_H +#define POINTAINER_H + +#ifdef NO_MEMBER_TEMPLATES +#include <functional> // for binder2nd +#endif + +template <typename Cnt> +class pointainer : public Cnt +{ +public: + using typename Cnt::size_type; + using typename Cnt::difference_type; + using typename Cnt::reference; + using typename Cnt::const_reference; + using typename Cnt::value_type; + using typename Cnt::iterator; + using typename Cnt::const_iterator; + using typename Cnt::reverse_iterator; + using typename Cnt::const_reverse_iterator; + typedef pointainer<Cnt> its_type; + + pointainer() {} + pointainer(const Cnt& c) : Cnt(c) {} + its_type& operator=(const Cnt& c) {Cnt::operator=(c); return *this;} + ~pointainer() {clean_all();} + + void clear() {clean_all(); Cnt::clear();} + iterator erase(iterator i) {clean(i); return Cnt::erase(i);} + iterator erase(iterator f, iterator l) {clean(f,l); return Cnt::erase(f,l);} + + // for associative containers: erase() a value + size_type erase(const value_type& v) + { + iterator i = find(v); + size_type found(i != end()); // can't have more than 1 + if (found) + erase(i); + return found; + } + + // for sequence containers: pop_front(), pop_back(), resize() and assign() + void pop_front() {clean(begin()); Cnt::pop_front();} + void pop_back() {iterator i(end()); clean(--i); Cnt::pop_back();} + void resize(size_type s, value_type c = value_type()) + { + if (s < size()) + clean(begin()+s, end()); + Cnt::resize(s, c); + } +#ifndef NO_MEMBER_TEMPLATES + template <class InIter> void assign(InIter f, InIter l) +#else + void assign(iterator f, iterator l) +#endif + { + clean_all(); + Cnt::assign(f,l); + } +#ifndef NO_MEMBER_TEMPLATES + template <class Size, class T> void assign(Size n, const T& t = T()) +#else + void assign(size_t n, const value_type& t = value_type()) +#endif + { + clean_all(); + Cnt::assign(n,t); + } + + // for std::list: remove() and remove_if() + void remove(const value_type& v) + { + clean( std::find(begin(), end(), v) ); + Cnt::remove(v); + } +#ifndef NO_MEMBER_TEMPLATES + template <class Pred> +#else + typedef std::binder2nd<std::not_equal_to<value_type> > Pred; +#endif + void remove_if(Pred pr) + { + for (iterator i = begin(); i != end(); ++i) + if (pr(*i)) + clean(i); + Cnt::remove_if(pr); + } + +private: + void clean(iterator i) {delete *i;} + void clean(iterator f, iterator l) {while (f != l) clean(f++);} + void clean_all() {clean( begin(), end() );} + + // we can't have two pointainers own the same objects: + pointainer(const its_type&) {} + its_type& operator=(const its_type&) {} +}; + +#endif // POINTAINER_H Added: cpp-commons/trunk/src/commons/yonat/pointerator.h =================================================================== --- cpp-commons/trunk/src/commons/yonat/pointerator.h (rev 0) +++ cpp-commons/trunk/src/commons/yonat/pointerator.h 2009-02-22 07:45:59 UTC (rev 1221) @@ -0,0 +1,117 @@ +/* + * pointerator - iterator to T* that behaves like iterator to T + * + * Example usage: + * + * std::vector<int*> v; + * v.push_back(new int(42)); + * v.push_back(new int(17)); + * + * typedef pointerator<std::vector<int*>::iterator> Iter; + * // Note: if your compiler does not support partial template + * // specialization, you should write: + * // typedef pointerator<std::vector<int*>::iterator, int> Iter; + * + * Iter i = std::find(Iter(v.begin()), Iter(v.end()), 17); + * // finds the second element of v + * + * std::cout << *i.get_iterator() << " points to " << *i; + * // *i is 17 + * + * Note: For ANSI-challenged compilers, you may want to #define + * NO_PARTIAL_SPECIALIZATION. + * + * Written 07-Feb-1999 by Yonat Sharon <yo...@oo...> + */ + +#ifndef POINTERATOR_H +#define POINTERATOR_H + +#ifndef NO_PARTIAL_SPECIALIZATION +#include <iterator> // for iterator_traits +#else +#include <cstddef> // for ptrdiff_t +#endif + +#ifndef NO_PARTIAL_SPECIALIZATION +template <typename Iter> +#else +template <typename Iter, typename Val> +#endif // NO_PARTIAL_SPECIALIZATION +class pointerator +{ +public: + +#ifndef NO_PARTIAL_SPECIALIZATION + typedef pointerator<Iter> its_type; + template <typename T> struct dereference {typedef void type;}; + template <typename T> struct dereference<T*> {typedef T type;}; + typedef typename dereference<typename Iter::value_type>::type Val; + typedef typename std::iterator_traits<Iter>::iterator_category iterator_category; + typedef typename std::iterator_traits<Iter>::difference_type difference_type; +#else + typedef pointerator<Iter,Val> its_type; + typedef ptrdiff_t difference_type; +#endif // NO_PARTIAL_SPECIALIZATION + + typedef Val value_type; + typedef Val& reference; + typedef const Val& const_reference; + typedef Val* pointer; + typedef const Val* const_pointer; + + pointerator() {} + pointerator(Iter i) : itsIter(i) {} + Iter get_iterator() const {return itsIter;} + + reference operator*() const {return **itsIter;} + pointer operator->() const {return *itsIter;} + reference operator[](difference_type n) const {return **itsIter[n];} + + its_type& operator++() {++itsIter; return *this;} + its_type& operator--() {--itsIter; return *this;} + its_type operator++(int) {its_type t(*this); ++itsIter; return t;} + its_type operator--(int) {its_type t(*this); --itsIter; return t;} + its_type& operator+=(difference_type n) {itsIter+=n; return *this;} + its_type& operator-=(difference_type n) {itsIter-=n; return *this;} + its_type operator+(difference_type n) const {return its_type(itsIter+n);} + its_type operator-(difference_type n) const {return its_type(itsIter-n);} + + bool operator==(const its_type& r) const {return itsIter == r.itsIter;} + bool operator!=(const its_type& r) const {return itsIter != r.itsIter;} + bool operator<(const its_type& r) const {return itsIter < r.itsIter;} + +private: + Iter itsIter; +}; + +#ifndef NO_PARTIAL_SPECIALIZATION +# define POINTERATOR pointerator<Iter> +# define TEMPLATE_ARGS template <typename Iter> +#else +# define POINTERATOR pointerator<Iter, T> +# define TEMPLATE_ARGS template <typename Iter, typename T> +#endif + +TEMPLATE_ARGS inline POINTERATOR +operator+(POINTERATOR ::difference_type n, const POINTERATOR& r) +{ + return POINTERATOR(x.get_iterator() - n); +} + +TEMPLATE_ARGS inline POINTERATOR ::difference_type +operator-(const POINTERATOR& l, const POINTERATOR& r) +{ + return l.get_iterator() - r.get_iterator(); +} + +TEMPLATE_ARGS inline POINTERATOR +make_pointerator(Iter it) +{ + return POINTERATOR(it); +} + +#undef POINTERATOR +#undef TEMPLATE_ARGS + +#endif // POINTERATOR_H Added: cpp-commons/trunk/src/commons/yonat/stringizer.h =================================================================== --- cpp-commons/trunk/src/commons/yonat/stringizer.h (rev 0) +++ cpp-commons/trunk/src/commons/yonat/stringizer.h 2009-02-22 07:45:59 UTC (rev 1221) @@ -0,0 +1,79 @@ +/* + * basic_stringizer - a functor that turns an object into a basic_string + * stringize/wstringize - functions that turn an object into a string/wstring + * + * The object you stringize must have the output operator defined + * (operator<< with an ostream argument). + * + * Note: For ANSI-challenged compilers, you may want to #define + * NO_PARTIAL_SPECIALIZATION. + * + * // example: creating a string from an int + * std::string s = "The answer, my friend, is " + stringize(42); + * + * // example: transforming a vector of doubles to a vector of strings + * std::vector<double> vf; + * std::vector<std::string> vs; + * vf.push_back(3.14159); + * vf.push_back(2.71828); + * vf.push_back(1.57079); + * std::transform( + * vf.begin(), vf.end(), // from + * std::back_inserter(vs), // to + * stringizer() ); // transformation + */ + +#ifndef STRINGIZER_H +#define STRINGIZER_H + +#include <sstream> + +template <typename Char> +struct basic_stringizer +{ + typedef std::basic_string<Char> String; + + template <typename T> + String operator()(const T& t) + { + std::basic_stringstream<Char> s; + s << t; + return s.str(); + } + +#ifndef NO_PARTIAL_SPECIALIZATION + template <> + String operator()<Char*>(const Char* s) + { return s; } + + template <> + String operator()<String>(const String& s) + { return s; } + + template <typename T> + String operator()<T*>(const T* p) + { return operator()<void*>(p); } + + template <> + String operator()<void*>(const void* p) + { + std::basic_stringstream<Char> s; + s << const_cast<void*>(p); + return s.str(); + } +#endif // NO_PARTIAL_SPECIALIZATION +}; + + +typedef basic_stringizer<char> stringizer; +typedef basic_stringizer<wchar_t> wstringizer; + +template <typename T> +inline std::string stringize(T t) +{ return stringizer()(t); } + +template <typename T> +inline std::wstring wstringize(T t) +{ return wstringizer()(t); } + +#endif // STRINGIZER_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-23 23:54:35
|
Revision: 1227 http://assorted.svn.sourceforge.net/assorted/?rev=1227&view=rev Author: yangzhang Date: 2009-02-23 23:54:23 +0000 (Mon, 23 Feb 2009) Log Message: ----------- - fixed function0<> vs. function<> discrepancy (causing seg faults; they are def. not interchangeable) - tweaks to st_reader - added st_reader::skip() - added work-arounds for various g++ warnings that don't play well with the C standard library macros Modified Paths: -------------- cpp-commons/trunk/src/commons/delegates.h cpp-commons/trunk/src/commons/sockets.h cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/src/commons/delegates.h =================================================================== --- cpp-commons/trunk/src/commons/delegates.h 2009-02-23 04:49:55 UTC (rev 1226) +++ cpp-commons/trunk/src/commons/delegates.h 2009-02-23 23:54:23 UTC (rev 1227) @@ -55,13 +55,12 @@ * 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(const fn &f): f_(f) {} ~finally() { f_(); } private: - T f_; + fn f_; }; } Modified: cpp-commons/trunk/src/commons/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/sockets.h 2009-02-23 04:49:55 UTC (rev 1226) +++ cpp-commons/trunk/src/commons/sockets.h 2009-02-23 23:54:23 UTC (rev 1227) @@ -18,6 +18,28 @@ { /** + * Work-around for the -Wold-style-cast-unsafe FD_* macros (see select(2)). + */ +#undef __FDMASK +#define __FDMASK(d) (static_cast<__fd_mask>(1) << ((d) % __NFDBITS)) + + /** + * Work-around for the -Wold-style-cast-unsafe INADDR_ANY + */ + const in_addr_t inaddr_any = in_addr_t(0); + + /** + * Make a TCP socket non-blocking. + */ + int + set_non_blocking(int fd) + { + checknnegerr(fcntl(fd, F_SETFL, + O_NONBLOCK | checknnegerr(fcntl(fd, F_GETFL, 0)))); + return fd; + } + + /** * Create a TCP socket. */ int @@ -25,12 +47,20 @@ { int fd = checknnegerr(socket(PF_INET, SOCK_STREAM, 0)); // Make our socket non-blocking if desired. - if (nb) - checknnegerr(fcntl(fd, F_SETFL, O_NONBLOCK | fcntl(fd, F_GETFL, 0))); + if (nb) set_non_blocking(fd); return fd; } /** + * -Wconversion-safe version of htons + */ + inline uint16_t + safe_htons(uint16_t x) + { + return (x & 0x00ff << 8) | (x & 0xff00 >> 8); + } + + /** * Initialize an inet address with just the port. */ void @@ -38,7 +68,7 @@ { bzero(&a, sizeof a); a.sin_family = AF_INET; - a.sin_port = htons(port); + a.sin_port = safe_htons(port); } /** @@ -49,7 +79,7 @@ { sockaddr_init(a, port); if (host == nullptr) { - a.sin_addr.s_addr = htonl(INADDR_ANY); + a.sin_addr.s_addr = htonl(inaddr_any); } else { // First try to interpret host as a dot-notation string. if (!inet_aton(host, reinterpret_cast<in_addr*>(&a.sin_addr.s_addr))) { Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-23 04:49:55 UTC (rev 1226) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-23 23:54:23 UTC (rev 1227) @@ -2,6 +2,14 @@ #define COMMONS_ST_ST_H #include <algorithm> +#include <boost/foreach.hpp> +#include <boost/function.hpp> +#include <boost/shared_ptr.hpp> +#include <commons/array.h> +#include <commons/delegates.h> +#include <commons/nullptr.h> +#include <commons/sockets.h> +#include <commons/utility.h> #include <exception> #include <map> #include <queue> @@ -9,15 +17,6 @@ #include <sstream> #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/utility.h> -#include <boost/foreach.hpp> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> #define foreach BOOST_FOREACH #define shared_ptr boost::shared_ptr @@ -54,10 +53,10 @@ * \todo Is it safe to treat the pthread_t as a pointer? */ st_thread_t - st_spawn(const function0<void>& f) + st_spawn(const fn& f) { return st_thread_create(&run_function0_null, - new function0<void>(f), + new fn(f), true, default_stack_size); } @@ -394,7 +393,7 @@ /** * The size of the unconsumed range of bytes. */ - size_t amt() { return end_ - start_; } + size_t unread() { return end_ - start_; } /** * The remaining number of bytes in the buffer @@ -402,12 +401,37 @@ size_t rem() { return buf_.end() - end_; } /** + * Discard the requested number of bytes. + */ + void skip(size_t req, st_utime_t to = ST_UTIME_NO_TIMEOUT) { + while (true) { + if (unread() >= req) { + // We have more unconsumed bytes than requested, so we're done. + start_ += req; + break; + } + + // We have more requested bytes than unconsumed, so need to keep + // reading. Skip over bytes... + req -= unread(); + // ...and reset pointers to discard current buffer. + start_ = end_ = buf_.get(); + + ssize_t res = checknnegerr(st_read(fd_, end_, rem(), to)); + end_ += res; + + // If we got a premature EOF. + if (res == 0 && unread() < req) throw eof_exception(); + } + } + + /** * Returns a char array that contains the requested number of bytes. If * we hit an error or EOF, then an exception is thrown. */ - managed_array<char> read(size_t req = 0, st_utime_t to = ST_UTIME_NO_TIMEOUT) { + managed_array<char> read(size_t req, st_utime_t to = ST_UTIME_NO_TIMEOUT) { // Do we already have the requested data? - if (amt() >= req) { + if (unread() >= req) { managed_array<char> p(start_, false); start_ += req; return p; @@ -417,7 +441,7 @@ if (req > buf_.size()) { managed_array<char> p(checkpass(new char[req]), true); copy(start_, end_, p.get()); - checkeqnneg(st_read_fully(fd_, p + amt(), req - amt(), to), static_cast<ssize_t>(req - amt())); + checkeqnneg(st_read_fully(fd_, p + unread(), req - unread(), to), static_cast<ssize_t>(req - unread())); start_ = end_ = buf_.get(); return p; } @@ -431,14 +455,14 @@ } // Keep reading until we have enough. - while (amt() < req) { + while (unread() < req) { ssize_t res = checknnegerr(st_read(fd_, end_, rem(), to)); if (res == 0) break; else end_ += res; } // If we got a premature EOF. - if (amt() < req) + if (unread() < req) throw eof_exception(); managed_array<char> p(start_, false); @@ -452,7 +476,7 @@ size_t req = sizeof(T); // Do we already have the requested data? - if (amt() >= req) { + if (unread() >= req) { T x = *reinterpret_cast<const T*>(start_); start_ += req; return x; @@ -469,14 +493,14 @@ } // Keep reading until we have enough. - while (amt() < req) { + while (unread() < req) { ssize_t res = checknnegerr(st_read(fd_, end_, rem(), to)); if (res == 0) break; else end_ += res; } // If we got a premature EOF. - if (amt() < req) + if (unread() < req) throw eof_exception(); T x = *reinterpret_cast<const T*>(start_); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-26 03:16:07
|
Revision: 1235 http://assorted.svn.sourceforge.net/assorted/?rev=1235&view=rev Author: yangzhang Date: 2009-02-26 03:15:58 +0000 (Thu, 26 Feb 2009) Log Message: ----------- - removed checkpass wrappers around new operator - changed array::reset() to take size Modified Paths: -------------- cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/files.h cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-02-25 21:13:24 UTC (rev 1234) +++ cpp-commons/trunk/src/commons/array.h 2009-02-26 03:15:58 UTC (rev 1235) @@ -46,13 +46,13 @@ 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) {} + explicit array(size_t n) : p_(new T[n]), n_(n) {} size_t size() const { return n_; } T *get() const { return p_.get(); } 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); } + void reset(T *p, size_t n) { p_.reset(p); n_ = n; } private: unique_ptr<T[]> p_; size_t n_; Modified: cpp-commons/trunk/src/commons/files.h =================================================================== --- cpp-commons/trunk/src/commons/files.h 2009-02-25 21:13:24 UTC (rev 1234) +++ cpp-commons/trunk/src/commons/files.h 2009-02-26 03:15:58 UTC (rev 1235) @@ -63,7 +63,7 @@ // TODO Why don't we need (static) cast here? Isn't this a lossy cast? len = sb.st_size; - char *buf = checkpass(new char[len + 1]); + char *buf = new char[len + 1]; checkeqnneg(pread(fd, buf, len, 0), static_cast<ssize_t>(len)); // TODO Use threads to pull data to the correct initial locations? Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-25 21:13:24 UTC (rev 1234) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-26 03:15:58 UTC (rev 1235) @@ -452,7 +452,7 @@ // Handle large arrays specially. if (req > buf_.size()) { - managed_array<char> p(checkpass(new char[req]), true); + managed_array<char> p(new char[req], true); 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(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-03-08 09:40:11
|
Revision: 1270 http://assorted.svn.sourceforge.net/assorted/?rev=1270&view=rev Author: yangzhang Date: 2009-03-08 09:40:09 +0000 (Sun, 08 Mar 2009) Log Message: ----------- tweaks to get unique_ptr to work; still need to fully understand things Modified Paths: -------------- cpp-commons/trunk/src/commons/fast_map.h cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/src/commons/fast_map.h =================================================================== --- cpp-commons/trunk/src/commons/fast_map.h 2009-03-08 09:39:11 UTC (rev 1269) +++ cpp-commons/trunk/src/commons/fast_map.h 2009-03-08 09:40:09 UTC (rev 1270) @@ -125,8 +125,7 @@ * the application, but more importantly, the interface required the ability * to serialize the map, and partially. The internals have to be exposed in * order for fast serialization (i.e. memcpy) to be possible; also, the - * ability to serialize just a certain range of the fast_map is also - * important. + * ability to serialize just a certain range of the fast_map was required. */ template <typename Key, typename Data> class fast_map Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-03-08 09:39:11 UTC (rev 1269) +++ cpp-commons/trunk/src/commons/st/st.h 2009-03-08 09:40:09 UTC (rev 1270) @@ -196,6 +196,10 @@ class st_channel { public: + void push(T &&x) { + q_.push(boost::move(x)); + empty_.signal(); + } void push(const T &x) { q_.push(x); empty_.signal(); @@ -204,11 +208,12 @@ while (q_.empty()) { empty_.wait(); } - T x = front(); + T x = boost::move(front()); q_.pop(); - return x; + return boost::move(x); } const T& front() const { return q_.front(); } + T& front() { return q_.front(); } bool empty() const { return q_.empty(); } void pop() { q_.pop(); } void clear() { while (!q_.empty()) q_.pop(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-03-09 22:56:40
|
Revision: 1275 http://assorted.svn.sourceforge.net/assorted/?rev=1275&view=rev Author: yangzhang Date: 2009-03-09 22:56:37 +0000 (Mon, 09 Mar 2009) Log Message: ----------- - added fast_map::set_size - added c++0x unique_ptr - added memory.h with memput, memget, raw_reader, raw_writer - use proper moving/forwarding in st_channel - made array moveable, non-copyable Modified Paths: -------------- cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/fast_map.h cpp-commons/trunk/src/commons/st/st.h Added Paths: ----------- cpp-commons/trunk/src/commons/memory.h cpp-commons/trunk/src/commons/unique_ptr.h Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-03-09 22:55:47 UTC (rev 1274) +++ cpp-commons/trunk/src/commons/array.h 2009-03-09 22:56:37 UTC (rev 1275) @@ -2,15 +2,14 @@ #define COMMONS_ARRAY_H #include <algorithm> -#include <boost/unique_ptr.hpp> #include <commons/algo.h> #include <commons/check.h> #include <commons/nullptr.h> +#include <commons/unique_ptr.h> #include <commons/utility.h> namespace commons { - using namespace boost; using namespace std; template<typename T> class array; @@ -48,9 +47,26 @@ template<typename T> class array { EXPAND(unique_ptr<T[]>) + NONCOPYABLE(array) friend void swap<>(array<T> &a, array<T> &b); public: explicit array(size_t n) : p_(new T[n]), n_(n) {} + array() : p_(), n_(0) {} + array(array<T> &&src) : p_(src.release()), n_(src.n_) {} +#if 0 + array(array<T> src) : p_(new T[src.size()]), n_(src.size()) { + memcpy(p_.get(), src.get(), size()); + } +#endif + array<T> &operator=(array<T> &&src) { + if (this != &src) { + p_.reset(src.release()); + n_ = src.n_; + } + return *this; + } + operator const T*() const { return p_.get(); } + operator T*() { return p_.get(); } size_t size() const { return n_; } T *get() const { return p_.get(); } T *release() { return p_.release(); } @@ -71,7 +87,7 @@ void swap(array<T> &a, array<T> &b) { - boost::swap(a.p_, b.p_); + std::swap(a.p_, b.p_); swap(a.n_, b.n_); } @@ -95,9 +111,7 @@ NONCOPYABLE(managed_array) public: managed_array(T *p, bool scoped) : p_(p), scoped_(scoped) {} -#ifdef __GXX_EXPERIMENTAL_CXX0X__ managed_array(managed_array<T> &&a) : p_(a.p_), scoped_(a.scoped_) { a.release(); } -#endif ~managed_array() { if (scoped_) delete [] p_; } T *release() { T *p = p_; p_ = nullptr; scoped_ = false; return p; } T *get() { return p_; } Modified: cpp-commons/trunk/src/commons/fast_map.h =================================================================== --- cpp-commons/trunk/src/commons/fast_map.h 2009-03-09 22:55:47 UTC (rev 1274) +++ cpp-commons/trunk/src/commons/fast_map.h 2009-03-09 22:56:37 UTC (rev 1275) @@ -193,6 +193,7 @@ resize(initsize); } size_t size() const { return count; } + void set_size(size_t size) { count = size; } void erase(iterator) { throw_not_implemented(); } array<value_type> &get_table() { return table; } const array<value_type> &get_table() const { return table; } @@ -225,6 +226,7 @@ if (table[pos].first == empty_key) return end(); if (table[pos].first == k) return const_iterator(*this, &table[pos]); pos = (pos + ++probe) & mask; + assert(probe < table.size()); } } @@ -235,6 +237,7 @@ if (table[pos].first == empty_key) return end(); if (table[pos].first == k) return iterator(*this, &table[pos]); pos = (pos + ++probe) & mask; + assert(probe < table.size()); } #if 0 for (; Added: cpp-commons/trunk/src/commons/memory.h =================================================================== --- cpp-commons/trunk/src/commons/memory.h (rev 0) +++ cpp-commons/trunk/src/commons/memory.h 2009-03-09 22:56:37 UTC (rev 1275) @@ -0,0 +1,57 @@ +#ifndef COMMONS_MEMORY_H +#define COMMONS_MEMORY_H + +namespace commons +{ + + /** + * Copy a datum directly to a memory location. Useful for serializing small + * data (e.g. ints). Faster than memcpy. + */ + template<typename T> + void memput(void *dst, const T &src) { + *reinterpret_cast<T*>(dst) = src; + } + + template<typename T> + void memget(void *src, T &dst) { + dst = *reinterpret_cast<T*>(src); + } + + template<typename T> + T &memget(void *src) { + return *reinterpret_cast<T*>(src); + } + + /** + * Lets you write a bunch of values to a buffer. + */ + class raw_writer + { + private: + char *p_; + public: + /** Initialize the pointer to point to p. */ + raw_writer(void *p) : p_(reinterpret_cast<char*>(p)) {} + /** Write a datum to the buffer, advancing the pointer. */ + template<typename T> + void write(const T &x) { memput(p_, x); p_ += sizeof(T); } + /** Get the current value of the pointer. */ + void *ptr() const { return p_; } + }; + + class raw_reader + { + private: + char *p_; + public: + raw_reader(void *p) : p_(reinterpret_cast<char*>(p)) {} + 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_); } + }; + +} + +#endif Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-03-09 22:55:47 UTC (rev 1274) +++ cpp-commons/trunk/src/commons/st/st.h 2009-03-09 22:56:37 UTC (rev 1275) @@ -18,6 +18,7 @@ #include <sstream> #include <st.h> #include <stx.h> +#include <utility> #define foreach BOOST_FOREACH #define shared_ptr boost::shared_ptr @@ -196,21 +197,17 @@ class st_channel { public: - void push(T &&x) { - q_.push(boost::move(x)); + template<typename U> void push(U &&x) { + q_.push(forward<U>(x)); empty_.signal(); } - void push(const T &x) { - q_.push(x); - empty_.signal(); - } T take() { while (q_.empty()) { empty_.wait(); } - T x = boost::move(front()); + T x = move(front()); q_.pop(); - return boost::move(x); + return x; } const T& front() const { return q_.front(); } T& front() { return q_.front(); } Added: cpp-commons/trunk/src/commons/unique_ptr.h =================================================================== --- cpp-commons/trunk/src/commons/unique_ptr.h (rev 0) +++ cpp-commons/trunk/src/commons/unique_ptr.h 2009-03-09 22:56:37 UTC (rev 1275) @@ -0,0 +1,459 @@ +// unique_ptr implementation -*- C++ -*- + +// Copyright (C) 2008, 2009 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library 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 General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/** @file unique_ptr.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _UNIQUE_PTR_H +#define _UNIQUE_PTR_H 1 + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +# include <c++0x_warning.h> +#endif + +#include <bits/c++config.h> +#include <debug/debug.h> +#include <type_traits> +#include <utility> +#include <tuple> + +_GLIBCXX_BEGIN_NAMESPACE(std) + + /** + * @addtogroup pointer_abstractions + * @{ + */ + + /// Primary template, default_delete. + template<typename _Tp> + struct default_delete + { + default_delete() { } + + template<typename _Up> + default_delete(const default_delete<_Up>&) { } + + void + operator()(_Tp* __ptr) const + { + static_assert(sizeof(_Tp)>0, + "can't delete pointer to incomplete type"); + delete __ptr; + } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 740 - omit specialization for array objects with a compile time length + /// Specialization, default_delete. + template<typename _Tp> + struct default_delete<_Tp[]> + { + void + operator()(_Tp* __ptr) const + { + static_assert(sizeof(_Tp)>0, + "can't delete pointer to incomplete type"); + delete [] __ptr; + } + }; + + /// 20.7.12.2 unique_ptr for single objects. + template <typename _Tp, typename _Tp_Deleter = default_delete<_Tp> > + class unique_ptr + { + typedef std::tuple<_Tp*, _Tp_Deleter> __tuple_type; + typedef __tuple_type unique_ptr::* __unspecified_bool_type; + typedef _Tp* unique_ptr::* __unspecified_pointer_type; + + public: + typedef _Tp* pointer; + typedef _Tp element_type; + typedef _Tp_Deleter deleter_type; + + // Constructors. + unique_ptr() + : _M_t(pointer(), deleter_type()) + { static_assert(!std::is_pointer<deleter_type>::value, + "constructed with null function pointer deleter"); } + + explicit + unique_ptr(pointer __p) + : _M_t(__p, deleter_type()) + { static_assert(!std::is_pointer<deleter_type>::value, + "constructed with null function pointer deleter"); } + + unique_ptr(pointer __p, + typename std::conditional<std::is_reference<deleter_type>::value, + deleter_type, const deleter_type&>::type __d) + : _M_t(__p, __d) { } + + unique_ptr(pointer __p, + typename std::remove_reference<deleter_type>::type&& __d) + : _M_t(std::move(__p), std::move(__d)) + { static_assert(!std::is_reference<deleter_type>::value, + "rvalue deleter bound to reference"); } + + // Move constructors. + unique_ptr(unique_ptr&& __u) + : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } + + template<typename _Up, typename _Up_Deleter> + unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) + : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) + { } + + // Destructor. + ~unique_ptr() { reset(); } + + // Assignment. + unique_ptr& + operator=(unique_ptr&& __u) + { + reset(__u.release()); + get_deleter() = std::move(__u.get_deleter()); + return *this; + } + + template<typename _Up, typename _Up_Deleter> + unique_ptr& + operator=(unique_ptr<_Up, _Up_Deleter>&& __u) + { + reset(__u.release()); + get_deleter() = std::move(__u.get_deleter()); + return *this; + } + + unique_ptr& + operator=(__unspecified_pointer_type) + { + reset(); + return *this; + } + + // Observers. + typename std::add_lvalue_reference<element_type>::type operator*() const + { + _GLIBCXX_DEBUG_ASSERT(get() != 0); + return *get(); + } + + pointer + operator->() const + { + _GLIBCXX_DEBUG_ASSERT(get() != 0); + return get(); + } + + pointer + get() const + { return std::get<0>(_M_t); } + + typename std::add_lvalue_reference<deleter_type>::type + get_deleter() + { return std::get<1>(_M_t); } + + typename std::add_lvalue_reference< + typename std::add_const<deleter_type>::type + >::type + get_deleter() const + { return std::get<1>(_M_t); } + + operator __unspecified_bool_type () const + { return get() == 0 ? 0 : &unique_ptr::_M_t; } + + // Modifiers. + pointer + release() + { + pointer __p = get(); + std::get<0>(_M_t) = 0; + return __p; + } + + void + reset(pointer __p = pointer()) + { + if (__p != get()) + { + get_deleter()(get()); + std::get<0>(_M_t) = __p; + } + } + + void + swap(unique_ptr&& __u) + { + using std::swap; + swap(_M_t, __u._M_t); + } + + private: + // Disable copy from lvalue. + unique_ptr(const unique_ptr&); + + template<typename _Up, typename _Up_Deleter> + unique_ptr(const unique_ptr<_Up, _Up_Deleter>&); + + unique_ptr& operator=(const unique_ptr&); + + template<typename _Up, typename _Up_Deleter> + unique_ptr& operator=(const unique_ptr<_Up, _Up_Deleter>&); + + private: + __tuple_type _M_t; + }; + + /// 20.7.12.3 unique_ptr for array objects with a runtime length + // [unique.ptr.runtime] + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 740 - omit specialization for array objects with a compile time length + template<typename _Tp, typename _Tp_Deleter> + class unique_ptr<_Tp[], _Tp_Deleter> + { + typedef std::tuple<_Tp*, _Tp_Deleter> __tuple_type; + typedef __tuple_type unique_ptr::* __unspecified_bool_type; + typedef _Tp* unique_ptr::* __unspecified_pointer_type; + + public: + typedef _Tp* pointer; + typedef _Tp element_type; + typedef _Tp_Deleter deleter_type; + + // Constructors. + unique_ptr() + : _M_t(pointer(), deleter_type()) + { static_assert(!std::is_pointer<deleter_type>::value, + "constructed with null function pointer deleter"); } + + explicit + unique_ptr(pointer __p) + : _M_t(__p, deleter_type()) + { static_assert(!std::is_pointer<deleter_type>::value, + "constructed with null function pointer deleter"); } + + unique_ptr(pointer __p, + typename std::conditional<std::is_reference<deleter_type>::value, + deleter_type, const deleter_type&>::type __d) + : _M_t(__p, __d) { } + + unique_ptr(pointer __p, + typename std::remove_reference<deleter_type>::type && __d) + : _M_t(std::move(__p), std::move(__d)) + { static_assert(!std::is_reference<deleter_type>::value, + "rvalue deleter bound to reference"); } + + // Move constructors. + unique_ptr(unique_ptr&& __u) + : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } + + template<typename _Up, typename _Up_Deleter> + unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) + : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) + { } + + // Destructor. + ~unique_ptr() { reset(); } + + // Assignment. + unique_ptr& + operator=(unique_ptr&& __u) + { + reset(__u.release()); + get_deleter() = std::move(__u.get_deleter()); + return *this; + } + + template<typename _Up, typename _Up_Deleter> + unique_ptr& + operator=(unique_ptr<_Up, _Up_Deleter>&& __u) + { + reset(__u.release()); + get_deleter() = std::move(__u.get_deleter()); + return *this; + } + + unique_ptr& + operator=(__unspecified_pointer_type) + { + reset(); + return *this; + } + + // Observers. + typename std::add_lvalue_reference<element_type>::type + operator[](size_t __i) const + { + _GLIBCXX_DEBUG_ASSERT(get() != 0); + return get()[__i]; + } + + pointer + get() const + { return std::get<0>(_M_t); } + + typename std::add_lvalue_reference<deleter_type>::type + get_deleter() + { return std::get<1>(_M_t); } + + typename std::add_lvalue_reference< + typename std::add_const<deleter_type>::type + >::type + get_deleter() const + { return std::get<1>(_M_t); } + + operator __unspecified_bool_type () const + { return get() == 0 ? 0 : &unique_ptr::_M_t; } + + // Modifiers. + pointer + release() + { + pointer __p = get(); + std::get<0>(_M_t) = 0; + return __p; + } + + void + reset(pointer __p = pointer()) + { + if (__p != get()) + { + get_deleter()(get()); + std::get<0>(_M_t) = __p; + } + } + + private: + // DR 821. + template<typename _Up> + void reset(_Up); + + public: + void + swap(unique_ptr&& __u) + { + using std::swap; + swap(_M_t, __u._M_t); + } + + private: + // Disable copy from lvalue. + unique_ptr(const unique_ptr&); + unique_ptr& operator=(const unique_ptr&); + + // Disable construction from convertible pointer types. + // (N2315 - 20.6.5.3.1) + template<typename _Up> + unique_ptr(_Up*, typename + std::conditional<std::is_reference<deleter_type>::value, + deleter_type, const deleter_type&>::type, + typename std::enable_if<std::is_convertible<_Up*, + pointer>::value>::type* = 0); + + template<typename _Up> + unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&, + typename std::enable_if<std::is_convertible<_Up*, + pointer>::value>::type* = 0); + + template<typename _Up> + explicit + unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, + pointer>::value>::type* = 0); + + private: + __tuple_type _M_t; + }; + + template<typename _Tp, typename _Tp_Deleter> + inline void + swap(unique_ptr<_Tp, _Tp_Deleter>& __x, + unique_ptr<_Tp, _Tp_Deleter>& __y) + { __x.swap(__y); } + + template<typename _Tp, typename _Tp_Deleter> + inline void + swap(unique_ptr<_Tp, _Tp_Deleter>&& __x, + unique_ptr<_Tp, _Tp_Deleter>& __y) + { __x.swap(__y); } + + template<typename _Tp, typename _Tp_Deleter> + inline void + swap(unique_ptr<_Tp, _Tp_Deleter>& __x, + unique_ptr<_Tp, _Tp_Deleter>&& __y) + { __x.swap(__y); } + + template<typename _Tp, typename _Tp_Deleter, + typename _Up, typename _Up_Deleter> + inline bool + operator==(const unique_ptr<_Tp, _Tp_Deleter>& __x, + const unique_ptr<_Up, _Up_Deleter>& __y) + { return __x.get() == __y.get(); } + + template<typename _Tp, typename _Tp_Deleter, + typename _Up, typename _Up_Deleter> + inline bool + operator!=(const unique_ptr<_Tp, _Tp_Deleter>& __x, + const unique_ptr<_Up, _Up_Deleter>& __y) + { return !(__x.get() == __y.get()); } + + template<typename _Tp, typename _Tp_Deleter, + typename _Up, typename _Up_Deleter> + inline bool + operator<(const unique_ptr<_Tp, _Tp_Deleter>& __x, + const unique_ptr<_Up, _Up_Deleter>& __y) + { return __x.get() < __y.get(); } + + template<typename _Tp, typename _Tp_Deleter, + typename _Up, typename _Up_Deleter> + inline bool + operator<=(const unique_ptr<_Tp, _Tp_Deleter>& __x, + const unique_ptr<_Up, _Up_Deleter>& __y) + { return !(__y.get() < __x.get()); } + + template<typename _Tp, typename _Tp_Deleter, + typename _Up, typename _Up_Deleter> + inline bool + operator>(const unique_ptr<_Tp, _Tp_Deleter>& __x, + const unique_ptr<_Up, _Up_Deleter>& __y) + { return __y.get() < __x.get(); } + + template<typename _Tp, typename _Tp_Deleter, + typename _Up, typename _Up_Deleter> + inline bool + operator>=(const unique_ptr<_Tp, _Tp_Deleter>& __x, + const unique_ptr<_Up, _Up_Deleter>& __y) + { return !(__x.get() < __y.get()); } + + // @} group pointer_abstractions + +_GLIBCXX_END_NAMESPACE + +#endif /* _UNIQUE_PTR_H */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-03-12 19:54:40
|
Revision: 1289 http://assorted.svn.sourceforge.net/assorted/?rev=1289&view=rev Author: yangzhang Date: 2009-03-12 19:54:31 +0000 (Thu, 12 Mar 2009) Log Message: ----------- using ASSERT instead of assert Modified Paths: -------------- cpp-commons/trunk/src/commons/fast_map.h cpp-commons/trunk/src/commons/rand.h cpp-commons/trunk/src/commons/st/st.h cpp-commons/trunk/src/commons/streamreader.h cpp-commons/trunk/src/commons/streamwriter.h Modified: cpp-commons/trunk/src/commons/fast_map.h =================================================================== --- cpp-commons/trunk/src/commons/fast_map.h 2009-03-12 19:53:53 UTC (rev 1288) +++ cpp-commons/trunk/src/commons/fast_map.h 2009-03-12 19:54:31 UTC (rev 1289) @@ -2,8 +2,8 @@ #define COMMONS_DENSE_HASH_MAP_H #include <boost/functional/hash.hpp> -#include <cassert> #include <commons/array.h> +#include <commons/assert.h> #include <commons/exceptions.h> #include <utility> @@ -167,7 +167,7 @@ for (size_t probe = 0; newtab[pos].first != empty_key; pos = (pos + ++probe) & mask) { - assert(probe < newtab.size()); + ASSERT(probe < newtab.size()); } newtab[pos] = table[i]; } @@ -177,7 +177,7 @@ void grow() { resize(table.size() << 1); } void shrink() { resize(table.size() >> 1); } - void assert_init() const { assert(has_empty_key && has_deleted_key); } + void assert_init() const { ASSERT(has_empty_key && has_deleted_key); } public: fast_map() : @@ -229,7 +229,7 @@ if (table[pos].first == empty_key) return end(); if (table[pos].first == k) return const_iterator(*this, &table[pos]); pos = (pos + ++probe) & mask; - assert(probe < table.size()); + ASSERT(probe < table.size()); } } @@ -240,13 +240,13 @@ if (table[pos].first == empty_key) return end(); if (table[pos].first == k) return iterator(*this, &table[pos]); pos = (pos + ++probe) & mask; - assert(probe < table.size()); + ASSERT(probe < table.size()); } #if 0 for (; table[pos].first != empty_key && table[pos].first != k; pos = (pos + ++probe) & mask) { - assert(probe < table.size()); + ASSERT(probe < table.size()); } if (table[pos].first == empty_key) return end(); else return &table[pos]; @@ -265,14 +265,14 @@ table[pos].first != empty_key && table[pos].first != k; pos = (pos + ++probe) & mask) { - assert(probe < table.size()); + ASSERT(probe < table.size()); } if (table[pos].first == deleted_key) { size_t first_deleted = pos; for (; table[pos].first != empty_key && table[pos].first != k; pos = (pos + ++probe) & mask) { - assert(probe < table.size()); + ASSERT(probe < table.size()); } if (table[pos].first == empty_key) { // Inserting new value_type. Grow table if necessary. Modified: cpp-commons/trunk/src/commons/rand.h =================================================================== --- cpp-commons/trunk/src/commons/rand.h 2009-03-12 19:53:53 UTC (rev 1288) +++ cpp-commons/trunk/src/commons/rand.h 2009-03-12 19:54:31 UTC (rev 1289) @@ -1,7 +1,6 @@ #ifndef COMMONS_RAND_H #define COMMONS_RAND_H -#include <cassert> #include <cstdlib> // random, RAND_MAX namespace commons Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-03-12 19:53:53 UTC (rev 1288) +++ cpp-commons/trunk/src/commons/st/st.h 2009-03-12 19:54:31 UTC (rev 1289) @@ -6,6 +6,7 @@ #include <boost/function.hpp> #include <boost/shared_ptr.hpp> #include <commons/array.h> +#include <commons/assert.h> #include <commons/delegates.h> #include <commons/nullptr.h> #include <commons/streamreader.h> @@ -297,7 +298,7 @@ void reset() { // If b is true, then any threads that join are immediately // interrupted, so the set must be empty. - assert(!b || threads.empty()); + ASSERT(!b || threads.empty()); b = false; } operator bool() const { return b; } @@ -350,7 +351,7 @@ NONCOPYABLE(st_joining) public: st_joining(st_thread_t t) : t_(t) {} - ~st_joining() { st_join(t_); } + ~st_joining() { if (t_ != nullptr) st_join(t_); } private: st_thread_t t_; }; @@ -375,6 +376,11 @@ std::set<st_thread_t> ts; }; +#if 0 +/// XXX + int count = 0; + size_t glen = 0; + class st_read_fn { private: @@ -384,9 +390,28 @@ st_read_fn(st_netfd_t fd, st_utime_t to = ST_UTIME_NO_TIMEOUT) : fd_(fd), to_(to) {} size_t operator()(char *buf, size_t len) { + size_t x = size_t(checknnegerr(st_read(fd_, buf, len, to_))); + glen += x; + if ((++count & 0xf) == 0xf) + cout << "count " << count << " len " << len << " read " << x << " glen " << glen << endl; + return x; + // return size_t(checknnegerr(st_read(fd_, buf, len, to_))); + } + }; +#else + class st_read_fn + { + private: + st_netfd_t fd_; + st_utime_t to_; + public: + st_read_fn(st_netfd_t fd, st_utime_t to = ST_UTIME_NO_TIMEOUT) + : fd_(fd), to_(to) {} + size_t operator()(char *buf, size_t len) { return size_t(checknnegerr(st_read(fd_, buf, len, to_))); } }; +#endif class st_read_fully_fn { Modified: cpp-commons/trunk/src/commons/streamreader.h =================================================================== --- cpp-commons/trunk/src/commons/streamreader.h 2009-03-12 19:53:53 UTC (rev 1288) +++ cpp-commons/trunk/src/commons/streamreader.h 2009-03-12 19:54:31 UTC (rev 1289) @@ -3,6 +3,7 @@ #include <boost/function.hpp> #include <commons/array.h> +#include <commons/assert.h> #include <cstring> namespace commons { @@ -31,7 +32,7 @@ res += reader_(buf + res, len - res); if (res == 0) throw eof_exception(); } - assert(res == len); + ASSERT(res == len); } }; @@ -205,7 +206,7 @@ return x; } - assert(req <= buf_.size()); + ASSERT(req <= buf_.size()); // Shift things down if necessary. if (req > static_cast<size_t>(buf_.end() - end_)) Modified: cpp-commons/trunk/src/commons/streamwriter.h =================================================================== --- cpp-commons/trunk/src/commons/streamwriter.h 2009-03-12 19:53:53 UTC (rev 1288) +++ cpp-commons/trunk/src/commons/streamwriter.h 2009-03-12 19:54:31 UTC (rev 1289) @@ -3,6 +3,7 @@ #include <boost/function.hpp> #include <commons/array.h> +#include <commons/assert.h> #include <cstring> #include <iostream> #include <iomanip> @@ -25,7 +26,7 @@ char *reserve(int 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()); + ASSERT(size_t(p - mark_ + n + sizeof(uint32_t)) <= a_.size()); // get rid of what we have flush(); size_t diff = mark_ - (a_.get() + sizeof(uint32_t)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-03-19 10:18:20
|
Revision: 1309 http://assorted.svn.sourceforge.net/assorted/?rev=1309&view=rev Author: yangzhang Date: 2009-03-19 10:18:05 +0000 (Thu, 19 Mar 2009) Log Message: ----------- - added friendlier versions of st_read, st_write - added array ctor - made stream_writer::reserve return the current pointer Modified Paths: -------------- cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/st/st.h cpp-commons/trunk/src/commons/streamwriter.h Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-03-19 10:16:33 UTC (rev 1308) +++ cpp-commons/trunk/src/commons/array.h 2009-03-19 10:18:05 UTC (rev 1309) @@ -52,6 +52,7 @@ friend void swap<>(array<T> &a, array<T> &b); public: explicit array(size_t n) : p_(new T[n]), n_(n) {} + explicit array(T *p, size_t n) : p_(p), n_(n) {} array() : p_(), n_(0) {} array(array<T> &&src) : p_(src.release()), n_(src.n_) {} #if 0 Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-03-19 10:16:33 UTC (rev 1308) +++ cpp-commons/trunk/src/commons/st/st.h 2009-03-19 10:18:05 UTC (rev 1309) @@ -50,6 +50,33 @@ st_mutex_t mx_; }; + void + st_read(st_netfd_t fd, void *buf, size_t len) + { + checkeqnneg(st_read_fully(fd, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); + } + + template<typename T> + void + st_read(st_netfd_t fd, T &x) + { + st_read(fd, &x, sizeof x); + } + + void + st_write(st_netfd_t fd, const void *buf, size_t len) + { + checkeqnneg(st_write(fd, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); + } + + template<typename T> + void + st_write(st_netfd_t fd, const T &x) + { + st_write(fd, &x, sizeof x); + } + + /** * Run a function in pthread. * \return The new pthread_t on success, 0 on failure. Modified: cpp-commons/trunk/src/commons/streamwriter.h =================================================================== --- cpp-commons/trunk/src/commons/streamwriter.h 2009-03-19 10:16:33 UTC (rev 1308) +++ cpp-commons/trunk/src/commons/streamwriter.h 2009-03-19 10:18:05 UTC (rev 1309) @@ -60,7 +60,7 @@ } } void reset() { p_ = mark_; } - void reserve(size_t n) { reserve(n, p_); } + char *reserve(size_t n) { reserve(n, p_); return p_; } void mark_and_flush() { mark(); flush(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-03-20 20:20:38
|
Revision: 1315 http://assorted.svn.sourceforge.net/assorted/?rev=1315&view=rev Author: yangzhang Date: 2009-03-20 20:20:25 +0000 (Fri, 20 Mar 2009) Log Message: ----------- - fixed all global functions to be either inline or static - added break_exception - added UNUSED - tweaked timer ctor - fixed missing include for snap_map - added operator[]() and at() to array classes Modified Paths: -------------- cpp-commons/trunk/src/commons/algo.h cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/delegates.h cpp-commons/trunk/src/commons/exceptions.h cpp-commons/trunk/src/commons/memory.h cpp-commons/trunk/src/commons/snap_map.h cpp-commons/trunk/src/commons/sockets.h cpp-commons/trunk/src/commons/st/st.h cpp-commons/trunk/src/commons/time.h cpp-commons/trunk/src/commons/utility.h Modified: cpp-commons/trunk/src/commons/algo.h =================================================================== --- cpp-commons/trunk/src/commons/algo.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/algo.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -5,7 +5,7 @@ namespace commons { - __attribute__((unused)) inline void + inline void swap(size_t &x, size_t &y) { x = x ^ y; y = x ^ y; Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/array.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -3,7 +3,7 @@ #include <algorithm> #include <commons/algo.h> -#include <commons/check.h> +#include <commons/assert.h> #include <commons/nullptr.h> #include <commons/unique_ptr.h> #include <commons/utility.h> @@ -34,6 +34,8 @@ T *end() const { return p_ + n_; } const T &operator[](size_t i) const { return p_[i]; } T &operator[](size_t i) { return p_[i]; } + const T &at(size_t i) const { ASSERT(i < n_); return p_[i]; } + T &at(size_t i) { ASSERT(i < n_); return p_[i]; } void reset(T *p, size_t n) { p_ = p; n_ = n; } private: T *p_; @@ -74,6 +76,8 @@ T *release() { return p_.release(); } T *begin() const { return p_.get(); } T *end() const { return this->get() + n_; } + const T &at(size_t i) const { ASSERT(i < n_); return p_[i]; } + T &at(size_t i) { ASSERT(i < n_); return p_[i]; } const T &operator[](size_t i) const { return p_[i]; } T &operator[](size_t i) { return p_[i]; } void reset(T *p, size_t n) { p_.reset(p); n_ = n; } @@ -86,7 +90,7 @@ * Swap two arrays. */ template<typename T> - void + inline void swap(array<T> &a, array<T> &b) { std::swap(a.p_, b.p_); @@ -99,7 +103,7 @@ */ template<typename T> void - swap(sized_array<T> &a, sized_array<T> &b) + inline swap(sized_array<T> &a, sized_array<T> &b) { std::swap(a.p_, b.p_); swap(a.n_, b.n_); @@ -118,6 +122,8 @@ T *release() { T *p = p_; p_ = nullptr; scoped_ = false; return p; } T *get() { return p_; } const T *get() const { return p_; } + const T &operator[](size_t i) const { return p_[i]; } + T &operator[](size_t i) { return p_[i]; } operator T*() { return p_; } operator const T*() const { return p_; } bool scoped() const { return scoped_; } Modified: cpp-commons/trunk/src/commons/delegates.h =================================================================== --- cpp-commons/trunk/src/commons/delegates.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/delegates.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -4,6 +4,7 @@ #include <boost/function.hpp> #include <boost/scoped_ptr.hpp> #include <iostream> // for cerr +#include <commons/utility.h> namespace commons { @@ -13,7 +14,7 @@ typedef std::function<void()> fn; - void + UNUSED static void swallow(const fn f) { try { f(); } catch (std::exception &ex) { cerr << ex.what() << endl; } @@ -22,7 +23,7 @@ /** * Delegate for running a 0-ary void function. */ - void + UNUSED static void run_function0(const void *p) { scoped_ptr<const fn> pf(reinterpret_cast<const fn*>(p)); @@ -32,7 +33,7 @@ /** * NULL void*-returning delegate for running a 0-ary void function. */ - void* + UNUSED static void* run_function0_null(void* p) { run_function0(p); Modified: cpp-commons/trunk/src/commons/exceptions.h =================================================================== --- cpp-commons/trunk/src/commons/exceptions.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/exceptions.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -39,6 +39,11 @@ const string msg_; }; + /** + * Convenience class for performing long-jumping break. + */ + class break_exception : public std::exception {}; + #define throw_not_supported() throw not_supported_exception(__PRETTY_FUNCTION__) #define throw_not_implemented() throw not_implemented_exception(__PRETTY_FUNCTION__) Modified: cpp-commons/trunk/src/commons/memory.h =================================================================== --- cpp-commons/trunk/src/commons/memory.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/memory.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -1,6 +1,8 @@ #ifndef COMMONS_MEMORY_H #define COMMONS_MEMORY_H +#include <cstring> // for size_t + namespace commons { Modified: cpp-commons/trunk/src/commons/snap_map.h =================================================================== --- cpp-commons/trunk/src/commons/snap_map.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/snap_map.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -6,6 +6,7 @@ #include <commons/assert.h> #include <commons/exceptions.h> #include <utility> +#include <map> namespace commons { @@ -143,7 +144,7 @@ typedef typename traits::const_reference const_reference; typedef typename traits::pointer pointer; typedef typename traits::const_pointer const_pointer; - typedef map<size_t, unique_ptr<array<value_type> > > shadowmap; + typedef map<size_t, unique_ptr<commons::array<value_type> > > shadowmap; private: static const size_t initsize = 1 << 20, pagesize = 1 << 15, pagemask = pagesize - 1; Modified: cpp-commons/trunk/src/commons/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/sockets.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/sockets.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -31,7 +31,7 @@ /** * Make a TCP socket non-blocking. */ - int + inline int set_non_blocking(int fd) { checknnegerr(fcntl(fd, F_SETFL, @@ -42,7 +42,7 @@ /** * Create a TCP socket. */ - int + inline int tcp_socket(bool nb) { int fd = checknnegerr(socket(PF_INET, SOCK_STREAM, 0)); @@ -63,7 +63,7 @@ /** * Initialize an inet address with just the port. */ - void + inline void sockaddr_init(sockaddr_in &a, uint16_t port) { bzero(&a, sizeof a); @@ -74,7 +74,7 @@ /** * Initialize an inet address. */ - void + static void sockaddr_init(sockaddr_in &a, const char *host, uint16_t port) { sockaddr_init(a, port); @@ -93,7 +93,7 @@ /** * Initialize an inet address. */ - void + inline void sockaddr_init(sockaddr_in &a, in_addr host, uint16_t port) { sockaddr_init(a, port); @@ -104,7 +104,7 @@ * Construct an inet address. */ template <typename T> - sockaddr_in + inline sockaddr_in make_sockaddr(T host, uint16_t port) { sockaddr_in a; @@ -118,7 +118,7 @@ * \param[in] nb Whether the socket should be non-blocking. * \return The server socket. */ - int + UNUSED static int server_socket(uint16_t port, bool nb = false) { // Create the socket. @@ -145,7 +145,7 @@ * \param[in] nb Whether the socket should be non-blocking. * \return The listener socket. */ - int + UNUSED static int tcp_listen(uint16_t port, bool nb = false) { int fd = server_socket(port, nb); @@ -163,7 +163,7 @@ /** * Connect to a TCP socket. */ - int + UNUSED static int tcp_connect(const char *host, uint16_t port) { closingfd c(tcp_socket(false)); Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/st/st.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -50,7 +50,7 @@ st_mutex_t mx_; }; - void + UNUSED static void st_read(st_netfd_t fd, void *buf, size_t len) { checkeqnneg(st_read_fully(fd, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); @@ -63,7 +63,7 @@ st_read(fd, &x, sizeof x); } - void + UNUSED static void st_write(st_netfd_t fd, const void *buf, size_t len) { checkeqnneg(st_write(fd, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); @@ -82,7 +82,7 @@ * \return The new pthread_t on success, 0 on failure. * \todo Is it safe to treat the pthread_t as a pointer? */ - st_thread_t + UNUSED static st_thread_t st_spawn(const fn& f) { return st_thread_create(&run_function0_null, @@ -91,7 +91,7 @@ default_stack_size); } - void + UNUSED static void st_join(st_thread_t t) { check0x(st_thread_join(t, nullptr)); @@ -103,7 +103,7 @@ * \param[in] port The destination port. * \param[in] timeout The timeout for the connect operation. */ - st_netfd_t + UNUSED static st_netfd_t st_tcp_connect(in_addr host, uint16_t port, st_utime_t timeout) { // Create remote socket address. @@ -125,7 +125,7 @@ * operation. * \todo Create variants that take and/or return sockaddr_in's. */ - st_netfd_t + UNUSED static st_netfd_t st_tcp_connect(const char *host, uint16_t port, st_utime_t timeout) { in_addr ipaddr; @@ -145,7 +145,7 @@ * \param[in] port The port to listen on. * \return The st_netfd_t. */ - st_netfd_t + UNUSED static st_netfd_t st_tcp_listen(uint16_t port) { int sfd = tcp_listen(port); @@ -193,7 +193,7 @@ bool b; }; - void toggle(st_bool& b) { if (b) b.reset(); else b.set(); } + UNUSED static void toggle(st_bool& b) { if (b) b.reset(); else b.set(); } /** * Wraps st_mutex_* errno-functions with exceptions and cleans up on Modified: cpp-commons/trunk/src/commons/time.h =================================================================== --- cpp-commons/trunk/src/commons/time.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/time.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -32,7 +32,7 @@ class timer { public: - timer(const string label) : + timer(const string &label) : label(label), start(current_time_millis()), last(start) {} void print() { Modified: cpp-commons/trunk/src/commons/utility.h =================================================================== --- cpp-commons/trunk/src/commons/utility.h 2009-03-20 17:45:38 UTC (rev 1314) +++ cpp-commons/trunk/src/commons/utility.h 2009-03-20 20:20:25 UTC (rev 1315) @@ -15,4 +15,6 @@ #define BEGIN_NAMESPACE(ns) namespace ns { #define END_NAMESPACE } +#define UNUSED __attribute__((unused)) + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-03-24 06:10:27
|
Revision: 1328 http://assorted.svn.sourceforge.net/assorted/?rev=1328&view=rev Author: yangzhang Date: 2009-03-24 06:10:14 +0000 (Tue, 24 Mar 2009) Log Message: ----------- broke up st.h; added USE(); tweaked ASSERT() Modified Paths: -------------- cpp-commons/trunk/src/commons/assert.h cpp-commons/trunk/src/commons/streamwriter.h cpp-commons/trunk/src/commons/utility.h Added Paths: ----------- cpp-commons/trunk/src/commons/st/channel.h cpp-commons/trunk/src/commons/st/intr.h cpp-commons/trunk/src/commons/st/io.h cpp-commons/trunk/src/commons/st/reader.h cpp-commons/trunk/src/commons/st/sockets.h cpp-commons/trunk/src/commons/st/sync.h cpp-commons/trunk/src/commons/st/threads.h Removed Paths: ------------- cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/src/commons/assert.h =================================================================== --- cpp-commons/trunk/src/commons/assert.h 2009-03-24 00:10:13 UTC (rev 1327) +++ cpp-commons/trunk/src/commons/assert.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -8,7 +8,7 @@ // This is not the "default" because it does not conform to the requirements of the C standard, // which requires that the NDEBUG version be ((void) 0). #ifdef NDEBUG -#define ASSERT(x) do { (void)sizeof(x); } while(0) +#define ASSERT(x) do { static_cast<void>(sizeof(x)); } while(0) #else #define ASSERT(x) assert(x) #endif Added: cpp-commons/trunk/src/commons/st/channel.h =================================================================== --- cpp-commons/trunk/src/commons/st/channel.h (rev 0) +++ cpp-commons/trunk/src/commons/st/channel.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -0,0 +1,70 @@ +#ifndef COMMONS_ST_CHANNEL_H +#define COMMONS_ST_CHANNEL_H + +#include <commons/st/sync.h> +#include <boost/foreach.hpp> +#include <boost/shared_ptr.hpp> +#include <queue> +#include <vector> +#define foreach BOOST_FOREACH +#define shared_ptr boost::shared_ptr + +BEGIN_NAMESPACE(commons) + +/** + * An unbounded FIFO queue. ST threads can wait on this until elements have + * been pushed in (resulting in a waking signal). + */ +template <typename T> +class st_channel +{ + public: + template<typename U> void push(U &&x) { + q_.push(forward<U>(x)); + empty_.signal(); + } + T take() { + while (q_.empty()) { + empty_.wait(); + } + T x = move(front()); + q_.pop(); + return x; + } + const T& front() const { return q_.front(); } + T& front() { return q_.front(); } + bool empty() const { return q_.empty(); } + void pop() { q_.pop(); } + void clear() { while (!q_.empty()) q_.pop(); } + const std::queue<T> &queue() const { return q_; } + private: + std::queue<T> q_; + st_cond empty_; +}; + +/** + * An unbounded FIFO multi-cast channel, i.e. publish-subscribe. + */ +template <typename T> +class st_multichannel +{ + public: + void push(const T &x) { + foreach (shared_ptr<st_channel<T> > q, qs) { + q->push(x); + } + } + st_channel<T> &subscribe() { + shared_ptr<st_channel<T> > q(new st_channel<T>); + qs.push_back(q); + return *q; + } + private: + vector<shared_ptr<st_channel<T> > > qs; +}; + +END_NAMESPACE + +#undef shared_ptr + +#endif Added: cpp-commons/trunk/src/commons/st/intr.h =================================================================== --- cpp-commons/trunk/src/commons/st/intr.h (rev 0) +++ cpp-commons/trunk/src/commons/st/intr.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -0,0 +1,92 @@ +#ifndef COMMONS_ST_INTR_H +#define COMMONS_ST_INTR_H + +#include <boost/foreach.hpp> +#include <commons/assert.h> +#include <commons/utility.h> +#include <set> +#include <st.h> +#define foreach BOOST_FOREACH + +BEGIN_NAMESPACE(commons) + + /** + * A hub is a single point to signal to wake up a set of threads. Threads + * join the hub before calling a blocking operation if they want to make + * themselves interruptible on this hub. + */ + class st_intr_hub + { + public: + virtual void insert(st_thread_t t) = 0; + virtual void erase(st_thread_t t) = 0; + virtual ~st_intr_hub() {}; + }; + + /** + * The simplest hub, which only interrupts those who are currently joined in + * the hub (like a condition variable broadcast). + */ + class st_intr_cond : public st_intr_hub + { + public: + virtual ~st_intr_cond() {} + void insert(st_thread_t t) { threads.insert(t); } + void erase(st_thread_t t) { threads.erase(t); } + void signal() { + foreach (st_thread_t t, threads) { + st_thread_interrupt(t); + } + threads.clear(); + } + private: + std::set<st_thread_t> threads; + }; + + /** + * Like st_intr_cond, but a bool instead, so there's state; newly joining + * threads may immediately be interrupted. Interruption occurs when this is + * set to true. + */ + class st_intr_bool : public st_intr_hub + { + public: + void insert(st_thread_t t) { + if (b) st_thread_interrupt(t); + else threads.insert(t); + } + void erase(st_thread_t t) { threads.erase(t); } + void set() { + b = true; + foreach (st_thread_t t, threads) { + st_thread_interrupt(t); + } + threads.clear(); + } + void reset() { + // If b is true, then any threads that join are immediately + // interrupted, so the set must be empty. + ASSERT(!b || threads.empty()); + b = false; + } + operator bool() const { return b; } + private: + std::set<st_thread_t> threads; + bool b; + }; + + /** + * RAII for making the current thread interruptible on a certain hub. + */ + class st_intr + { + public: + st_intr(st_intr_hub &hub) : hub_(hub) { hub.insert(st_thread_self()); } + ~st_intr() { hub_.erase(st_thread_self()); } + private: + st_intr_hub &hub_; + }; + +END_NAMESPACE + +#endif Added: cpp-commons/trunk/src/commons/st/io.h =================================================================== --- cpp-commons/trunk/src/commons/st/io.h (rev 0) +++ cpp-commons/trunk/src/commons/st/io.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -0,0 +1,40 @@ +#ifndef COMMONS_ST_IO_H +#define COMMONS_ST_IO_H + +#include <commons/check.h> +#include <commons/utility.h> +#include <st.h> + +BEGIN_NAMESPACE(commons) + +using namespace std; + +UNUSED static void +st_read(st_netfd_t fd, void *buf, size_t len) +{ + checkeqnneg(st_read_fully(fd, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); +} + +template<typename T> +void +st_read(st_netfd_t fd, T &x) +{ + st_read(fd, &x, sizeof x); +} + +UNUSED static void +st_write(st_netfd_t fd, const void *buf, size_t len) +{ + checkeqnneg(st_write(fd, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); +} + +template<typename T> +void +st_write(st_netfd_t fd, const T &x) +{ + st_write(fd, &x, sizeof x); +} + +END_NAMESPACE + +#endif Added: cpp-commons/trunk/src/commons/st/reader.h =================================================================== --- cpp-commons/trunk/src/commons/st/reader.h (rev 0) +++ cpp-commons/trunk/src/commons/st/reader.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -0,0 +1,64 @@ +#ifndef COMMONS_ST_READER_H +#define COMMONS_ST_READER_H + +#include <commons/check.h> +#include <commons/streamreader.h> +#include <commons/utility.h> +#include <st.h> + +BEGIN_NAMESPACE(commons) + +using namespace boost; +using namespace std; + +class st_read_fn +{ +private: + st_netfd_t fd_; + st_utime_t to_; +public: + st_read_fn(st_netfd_t fd, st_utime_t to = ST_UTIME_NO_TIMEOUT) + : fd_(fd), to_(to) {} + size_t operator()(char *buf, size_t len) { + return size_t(checknnegerr(st_read(fd_, buf, len, to_))); + } +}; + +class st_read_fully_fn +{ +private: + st_netfd_t fd_; + st_utime_t to_; +public: + st_read_fully_fn(st_netfd_t fd, st_utime_t to = ST_UTIME_NO_TIMEOUT) + : fd_(fd), to_(to) {} + void operator()(char *buf, size_t len) { + checkeqnneg(st_read_fully(fd_, buf, len, to_), ssize_t(len)); + } +}; + +class st_reader +{ + EXPAND(stream_reader) +private: + stream_reader r_; +public: + st_reader(st_netfd_t fd, char *buf, size_t len) : + r_(st_read_fn(fd), st_read_fully_fn(fd), buf, len) {} + size_t unread() { return r_.unread(); } + size_t rem() { return r_.rem(); } + sized_array<char> &buf() { return r_.buf(); } + void reset_range(char *start, char *end) { r_.reset_range(start, end); } + void reset() { r_.reset(); } + char *start() { return r_.start(); } + char *end() { return r_.end(); } + bool accum(size_t req) { return r_.accum(req); } + void skip(size_t req) { r_.skip(req); } + managed_array<char> read(size_t req) { return r_.read(req); } + template<typename T> T read() { return r_.read<T>(); } + void shift() { r_.shift(); } +}; + +END_NAMESPACE + +#endif Added: cpp-commons/trunk/src/commons/st/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/st/sockets.h (rev 0) +++ cpp-commons/trunk/src/commons/st/sockets.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -0,0 +1,81 @@ +#ifndef COMMONS_ST_SOCKETS_H +#define COMMONS_ST_SOCKETS_H + +#include <commons/closing.h> +#include <commons/sockets.h> +#include <commons/utility.h> +#include <st.h> +#include <stx.h> + +BEGIN_NAMESPACE(commons) + +struct stfd_closer { + static void apply(st_netfd_t fd) { check0x(st_netfd_close(fd)); } +}; + +typedef closing<st_netfd_t, stfd_closer> st_closing; + +/** + * Connect to a TCP socket address. + * \param[in] host An IP address. + * \param[in] port The destination port. + * \param[in] timeout The timeout for the connect operation. + */ +UNUSED static st_netfd_t +st_tcp_connect(in_addr host, uint16_t port, st_utime_t timeout) +{ + // Create remote socket address. + sockaddr_in sa = make_sockaddr(host, port); + + // Create the socket. + st_closing s(checkpass(st_netfd_open_socket(tcp_socket(true)))); + + // Connect. + check0x(st_connect(s.get(), reinterpret_cast<sockaddr*>(&sa), sizeof sa, timeout)); + return s.release(); +} + +/** + * Connect to a TCP socket address. + * \param[in] host Either an IP address or hostname. + * \param[in] port The destination port. + * \param[in] timeout The timeout for each of the DNS lookup and the connect + * operation. + * \todo Create variants that take and/or return sockaddr_in's. + */ +UNUSED static st_netfd_t +st_tcp_connect(const char *host, uint16_t port, st_utime_t timeout) +{ + in_addr ipaddr; + + // First try to parse as IP address. Note: inet_addr() is obsolete. Note: + // inet_aton returns 0 if address is invalid. + if (inet_aton(host, &ipaddr) == 0) { + // Then look up by hostname. + check0x(stx_dns_getaddr(host, &ipaddr, timeout)); + } + + return st_tcp_connect(ipaddr, port, timeout); +} + +/** + * Create a listener st_netfd_t. + * \param[in] port The port to listen on. + * \return The st_netfd_t. + */ +UNUSED static st_netfd_t +st_tcp_listen(uint16_t port) +{ + int sfd = tcp_listen(port); + try { + // Create a net file descriptor around a listener socket. + return checkpass(st_netfd_open_socket(sfd)); + } catch (...) { + close(sfd); + throw; + } +} + +END_NAMESPACE + +#endif Deleted: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-03-24 00:10:13 UTC (rev 1327) +++ cpp-commons/trunk/src/commons/st/st.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -1,480 +0,0 @@ -#ifndef COMMONS_ST_ST_H -#define COMMONS_ST_ST_H - -#include <algorithm> -#include <boost/foreach.hpp> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include <commons/array.h> -#include <commons/assert.h> -#include <commons/delegates.h> -#include <commons/nullptr.h> -#include <commons/streamreader.h> -#include <commons/sockets.h> -#include <commons/utility.h> -#include <exception> -#include <map> -#include <queue> -#include <set> -#include <sstream> -#include <st.h> -#include <stx.h> -#include <utility> - -#define foreach BOOST_FOREACH -#define shared_ptr boost::shared_ptr - -namespace commons -{ - using namespace boost; - using namespace std; - - enum { default_stack_size = 65536 }; - - struct stfd_closer { - static void apply(st_netfd_t fd) { check0x(st_netfd_close(fd)); } - }; - - typedef closing<st_netfd_t, stfd_closer> st_closing; - - /** - * RAII to acquire and release a st_mutex_t. Non-copyable. - */ - class st_lock - { - NONCOPYABLE(st_lock) - public: - st_lock(st_mutex_t mx) : mx_(mx) { check0x(st_mutex_lock(mx)); } - ~st_lock() { check0x(st_mutex_unlock(mx_)); } - private: - st_mutex_t mx_; - }; - - UNUSED static void - st_read(st_netfd_t fd, void *buf, size_t len) - { - checkeqnneg(st_read_fully(fd, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); - } - - template<typename T> - void - st_read(st_netfd_t fd, T &x) - { - st_read(fd, &x, sizeof x); - } - - UNUSED static void - st_write(st_netfd_t fd, const void *buf, size_t len) - { - checkeqnneg(st_write(fd, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); - } - - template<typename T> - void - st_write(st_netfd_t fd, const T &x) - { - st_write(fd, &x, sizeof x); - } - - - /** - * 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 a pointer? - */ - UNUSED static st_thread_t - st_spawn(const fn& f) - { - return st_thread_create(&run_function0_null, - new fn(f), - true, - default_stack_size); - } - - UNUSED static void - st_join(st_thread_t t) - { - check0x(st_thread_join(t, nullptr)); - } - - /** - * Connect to a TCP socket address. - * \param[in] host An IP address. - * \param[in] port The destination port. - * \param[in] timeout The timeout for the connect operation. - */ - UNUSED static st_netfd_t - st_tcp_connect(in_addr host, uint16_t port, st_utime_t timeout) - { - // Create remote socket address. - sockaddr_in sa = make_sockaddr(host, port); - - // Create the socket. - st_closing s(checkpass(st_netfd_open_socket(tcp_socket(true)))); - - // Connect. - check0x(st_connect(s.get(), reinterpret_cast<sockaddr*>(&sa), sizeof sa, timeout)); - return s.release(); - } - - /** - * Connect to a TCP socket address. - * \param[in] host Either an IP address or hostname. - * \param[in] port The destination port. - * \param[in] timeout The timeout for each of the DNS lookup and the connect - * operation. - * \todo Create variants that take and/or return sockaddr_in's. - */ - UNUSED static st_netfd_t - st_tcp_connect(const char *host, uint16_t port, st_utime_t timeout) - { - in_addr ipaddr; - - // First try to parse as IP address. Note: inet_addr() is obsolete. Note: - // inet_aton returns 0 if address is invalid. - if (inet_aton(host, &ipaddr) == 0) { - // Then look up by hostname. - check0x(stx_dns_getaddr(host, &ipaddr, timeout)); - } - - return st_tcp_connect(ipaddr, port, timeout); - } - - /** - * Create a listener st_netfd_t. - * \param[in] port The port to listen on. - * \return The st_netfd_t. - */ - UNUSED static st_netfd_t - st_tcp_listen(uint16_t port) - { - int sfd = tcp_listen(port); - try { - // Create a net file descriptor around a listener socket. - return checkpass(st_netfd_open_socket(sfd)); - } catch (...) { - close(sfd); - throw; - } - } - - /** - * Wraps st_cond_* errno-functions with exceptions and cleans up on - * destruction. - */ - class st_cond - { - NONCOPYABLE(st_cond) - public: - st_cond() : c(checkerr(st_cond_new())) {} - ~st_cond() { check0x(st_cond_destroy(c)); } - void wait() { check0x(st_cond_wait(c)); } - void wait(st_utime_t t) { check0x(st_cond_timedwait(c, t)); } - void signal() { st_cond_signal(c); } - void bcast() { st_cond_broadcast(c); } - private: - st_cond_t c; - }; - - /** - * Synchronized boolean. - */ - class st_bool - { - public: - st_bool(bool init = false) : c(), b(init) {} - void set() { b = true; c.bcast(); } - void reset() { b = false; c.bcast(); } - void waitset() { if (!b) c.wait(); } - void waitreset() { if (b) c.wait(); } - operator bool() { return b; } - private: - st_cond c; - bool b; - }; - - UNUSED static void toggle(st_bool& b) { if (b) b.reset(); else b.set(); } - - /** - * Wraps st_mutex_* errno-functions with exceptions and cleans up on - * destruction. - */ - class st_mutex - { - NONCOPYABLE(st_mutex) - public: - st_mutex() : m(checkerr(st_mutex_new())) {} - ~st_mutex() { check0x(st_mutex_destroy(m)); } - void lock() { check0x(st_mutex_lock(m)); } - bool trylock() { - int res = st_mutex_trylock(m); - if (res == 0) return true; - else if (errno == EBUSY) return false; - else check0x(res); - } - void unlock() { check0x(st_mutex_unlock(m)); } - private: - st_mutex_t m; - }; - - /** - * An unbounded FIFO queue. ST threads can wait on this until elements have - * been pushed in (resulting in a waking signal). - */ - template <typename T> - class st_channel - { - public: - template<typename U> void push(U &&x) { - q_.push(forward<U>(x)); - empty_.signal(); - } - T take() { - while (q_.empty()) { - empty_.wait(); - } - T x = move(front()); - q_.pop(); - return x; - } - const T& front() const { return q_.front(); } - T& front() { return q_.front(); } - bool empty() const { return q_.empty(); } - void pop() { q_.pop(); } - void clear() { while (!q_.empty()) q_.pop(); } - const std::queue<T> &queue() const { return q_; } - private: - std::queue<T> q_; - st_cond empty_; - }; - - /** - * An unbounded FIFO multi-cast channel, i.e. publish-subscribe. - */ - template <typename T> - class st_multichannel - { - public: - void push(const T &x) { - foreach (shared_ptr<st_channel<T> > q, qs) { - q->push(x); - } - } - st_channel<T> &subscribe() { - shared_ptr<st_channel<T> > q(new st_channel<T>); - qs.push_back(q); - return *q; - } - private: - vector<shared_ptr<st_channel<T> > > qs; - }; - - /** - * A hub is a single point to signal to wake up a set of threads. Threads - * join the hub before calling a blocking operation if they want to make - * themselves interruptible on this hub. - */ - class st_intr_hub - { - public: - virtual void insert(st_thread_t t) = 0; - virtual void erase(st_thread_t t) = 0; - virtual ~st_intr_hub() {}; - }; - - /** - * The simplest hub, which only interrupts those who are currently joined in - * the hub (like a condition variable broadcast). - */ - class st_intr_cond : public st_intr_hub - { - public: - virtual ~st_intr_cond() {} - void insert(st_thread_t t) { threads.insert(t); } - void erase(st_thread_t t) { threads.erase(t); } - void signal() { - foreach (st_thread_t t, threads) { - st_thread_interrupt(t); - } - threads.clear(); - } - private: - std::set<st_thread_t> threads; - }; - - /** - * Like st_intr_cond, but a bool instead, so there's state; newly joining - * threads may immediately be interrupted. Interruption occurs when this is - * set to true. - */ - class st_intr_bool : public st_intr_hub - { - public: - void insert(st_thread_t t) { - if (b) st_thread_interrupt(t); - else threads.insert(t); - } - void erase(st_thread_t t) { threads.erase(t); } - void set() { - b = true; - foreach (st_thread_t t, threads) { - st_thread_interrupt(t); - } - threads.clear(); - } - void reset() { - // If b is true, then any threads that join are immediately - // interrupted, so the set must be empty. - ASSERT(!b || threads.empty()); - b = false; - } - operator bool() const { return b; } - private: - std::set<st_thread_t> threads; - bool b; - }; - - /** - * RAII for making the current thread interruptible on a certain hub. - */ - class st_intr - { - public: - st_intr(st_intr_hub &hub) : hub_(hub) { hub.insert(st_thread_self()); } - ~st_intr() { hub_.erase(st_thread_self()); } - private: - st_intr_hub &hub_; - }; - - class st_group_join_exception : public std::exception - { - public: - 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, std::exception> p; - foreach (p p, th2ex_) { - ss << (first ? "" : ", ") << p.first << " -> " << p.second.what(); - first = false; - } - s = ss.str(); - } - return s.c_str(); - } - private: - map<st_thread_t, std::exception> th2ex_; - mutable string s; - }; - - /** - * RAII for joining on a single thread. - */ - class st_joining - { - NONCOPYABLE(st_joining) - public: - st_joining(st_thread_t t) : t_(t) {} - ~st_joining() { if (t_ != nullptr) st_join(t_); } - private: - st_thread_t t_; - }; - - /** - * RAII for joining on all contained threads. Warning: st_join may throw - * exceptions. - */ - class st_thread_group - { - public: - ~st_thread_group() { - map<st_thread_t, std::exception> th2ex; - foreach (st_thread_t t, ts) { - try { st_join(t); } - catch (std::exception &ex) { th2ex[t] = ex; } - } - if (!th2ex.empty()) throw st_group_join_exception(th2ex); - } - void insert(st_thread_t t) { ts.insert(t); } - private: - std::set<st_thread_t> ts; - }; - -#if 0 -/// XXX - int count = 0; - size_t glen = 0; - - class st_read_fn - { - private: - st_netfd_t fd_; - st_utime_t to_; - public: - st_read_fn(st_netfd_t fd, st_utime_t to = ST_UTIME_NO_TIMEOUT) - : fd_(fd), to_(to) {} - size_t operator()(char *buf, size_t len) { - size_t x = size_t(checknnegerr(st_read(fd_, buf, len, to_))); - glen += x; - if ((++count & 0xf) == 0xf) - cout << "count " << count << " len " << len << " read " << x << " glen " << glen << endl; - return x; - // return size_t(checknnegerr(st_read(fd_, buf, len, to_))); - } - }; -#else - class st_read_fn - { - private: - st_netfd_t fd_; - st_utime_t to_; - public: - st_read_fn(st_netfd_t fd, st_utime_t to = ST_UTIME_NO_TIMEOUT) - : fd_(fd), to_(to) {} - size_t operator()(char *buf, size_t len) { - return size_t(checknnegerr(st_read(fd_, buf, len, to_))); - } - }; -#endif - - class st_read_fully_fn - { - private: - st_netfd_t fd_; - st_utime_t to_; - public: - st_read_fully_fn(st_netfd_t fd, st_utime_t to = ST_UTIME_NO_TIMEOUT) - : fd_(fd), to_(to) {} - void operator()(char *buf, size_t len) { - checkeqnneg(st_read_fully(fd_, buf, len, to_), ssize_t(len)); - } - }; - - class st_reader - { - EXPAND(stream_reader) - private: - stream_reader r_; - public: - st_reader(st_netfd_t fd, char *buf, size_t len) : - r_(st_read_fn(fd), st_read_fully_fn(fd), buf, len) {} - size_t unread() { return r_.unread(); } - size_t rem() { return r_.rem(); } - sized_array<char> &buf() { return r_.buf(); } - void reset_range(char *start, char *end) { r_.reset_range(start, end); } - void reset() { r_.reset(); } - char *start() { return r_.start(); } - char *end() { return r_.end(); } - bool accum(size_t req) { return r_.accum(req); } - void skip(size_t req) { r_.skip(req); } - managed_array<char> read(size_t req) { return r_.read(req); } - template<typename T> T read() { return r_.read<T>(); } - void shift() { r_.shift(); } - }; - -} - -#endif Added: cpp-commons/trunk/src/commons/st/sync.h =================================================================== --- cpp-commons/trunk/src/commons/st/sync.h (rev 0) +++ cpp-commons/trunk/src/commons/st/sync.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -0,0 +1,84 @@ +#ifndef COMMONS_ST_SYNC_H +#define COMMONS_ST_SYNC_H + +#include <commons/check.h> +#include <commons/utility.h> +#include <st.h> + +BEGIN_NAMESPACE(commons) + +/** + * RAII to acquire and release a st_mutex_t. Non-copyable. + */ +class st_lock +{ + NONCOPYABLE(st_lock) + public: + st_lock(st_mutex_t mx) : mx_(mx) { check0x(st_mutex_lock(mx)); } + ~st_lock() { check0x(st_mutex_unlock(mx_)); } + private: + st_mutex_t mx_; +}; + +/** + * Wraps st_cond_* errno-functions with exceptions and cleans up on + * destruction. + */ +class st_cond +{ + NONCOPYABLE(st_cond) + public: + st_cond() : c(checkerr(st_cond_new())) {} + ~st_cond() { check0x(st_cond_destroy(c)); } + void wait() { check0x(st_cond_wait(c)); } + void wait(st_utime_t t) { check0x(st_cond_timedwait(c, t)); } + void signal() { st_cond_signal(c); } + void bcast() { st_cond_broadcast(c); } + private: + st_cond_t c; +}; + +/** + * Synchronized boolean. + */ +class st_bool +{ + public: + st_bool(bool init = false) : c(), b(init) {} + void set() { b = true; c.bcast(); } + void reset() { b = false; c.bcast(); } + void waitset() { if (!b) c.wait(); } + void waitreset() { if (b) c.wait(); } + operator bool() { return b; } + private: + st_cond c; + bool b; +}; + +UNUSED static void toggle(st_bool& b) { if (b) b.reset(); else b.set(); } + +/** + * Wraps st_mutex_* errno-functions with exceptions and cleans up on + * destruction. + */ +class st_mutex +{ + NONCOPYABLE(st_mutex) + public: + st_mutex() : m(checkerr(st_mutex_new())) {} + ~st_mutex() { check0x(st_mutex_destroy(m)); } + void lock() { check0x(st_mutex_lock(m)); } + bool trylock() { + int res = st_mutex_trylock(m); + if (res == 0) return true; + else if (errno == EBUSY) return false; + else check0x(res); + } + void unlock() { check0x(st_mutex_unlock(m)); } + private: + st_mutex_t m; +}; + +END_NAMESPACE + +#endif Added: cpp-commons/trunk/src/commons/st/threads.h =================================================================== --- cpp-commons/trunk/src/commons/st/threads.h (rev 0) +++ cpp-commons/trunk/src/commons/st/threads.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -0,0 +1,98 @@ +#ifndef COMMONS_ST_THREADS_H +#define COMMONS_ST_THREADS_H + +#include <commons/utility.h> +#include <commons/delegates.h> +#include <boost/foreach.hpp> +#include <map> +#include <set> +#include <st.h> + +#define foreach BOOST_FOREACH + +BEGIN_NAMESPACE(commons) + +using namespace std; + +enum { default_stack_size = 65536 }; + +/** + * 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 a pointer? + */ +UNUSED static st_thread_t +st_spawn(const fn& f) +{ + return st_thread_create(&run_function0_null, + new fn(f), + true, + default_stack_size); +} + +UNUSED static void +st_join(st_thread_t t) +{ + check0x(st_thread_join(t, nullptr)); +} + +class st_group_join_exception : public std::exception +{ + public: + 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, std::exception> p; + foreach (p p, th2ex_) { + ss << (first ? "" : ", ") << p.first << " -> " << p.second.what(); + first = false; + } + s = ss.str(); + } + return s.c_str(); + } + private: + map<st_thread_t, std::exception> th2ex_; + mutable string s; +}; + +/** + * RAII for joining on a single thread. + */ +class st_joining +{ + NONCOPYABLE(st_joining) + public: + st_joining(st_thread_t t) : t_(t) {} + ~st_joining() { if (t_ != nullptr) st_join(t_); } + private: + st_thread_t t_; +}; + +/** + * RAII for joining on all contained threads. Warning: st_join may throw + * exceptions. + */ +class st_thread_group +{ + public: + ~st_thread_group() { + map<st_thread_t, std::exception> th2ex; + foreach (st_thread_t t, ts) { + try { st_join(t); } + catch (std::exception &ex) { th2ex[t] = ex; } + } + if (!th2ex.empty()) throw st_group_join_exception(th2ex); + } + void insert(st_thread_t t) { ts.insert(t); } + private: + set<st_thread_t> ts; +}; + +END_NAMESPACE + +#endif Modified: cpp-commons/trunk/src/commons/streamwriter.h =================================================================== --- cpp-commons/trunk/src/commons/streamwriter.h 2009-03-24 00:10:13 UTC (rev 1327) +++ cpp-commons/trunk/src/commons/streamwriter.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -7,6 +7,7 @@ #include <cstring> #include <iostream> #include <iomanip> +#include <arpa/inet.h> namespace commons { @@ -22,7 +23,7 @@ char *unsent_; char *mark_; char *p_; - boost::function<void(void*, size_t)> flushcb; + boost::function<void(const void*, size_t)> flushcb; char *reserve(size_t n, char *p) { if (p + n > a_.end()) { // check that the reserved space will fit @@ -43,7 +44,7 @@ *reinterpret_cast<T*>(reserve(sizeof x, p)) = x; } public: - stream_writer(boost::function<void(void*, size_t)> flushcb, char *a, size_t buf_size) : + stream_writer(boost::function<void(const void*, size_t)> flushcb, char *a, size_t buf_size) : a_(a, buf_size), unsent_(a_.get()), mark_(unsent_ + sizeof(uint32_t)), p_(mark_), flushcb(flushcb) {} sized_array<char> &buf() { return a_; } Modified: cpp-commons/trunk/src/commons/utility.h =================================================================== --- cpp-commons/trunk/src/commons/utility.h 2009-03-24 00:10:13 UTC (rev 1327) +++ cpp-commons/trunk/src/commons/utility.h 2009-03-24 06:10:14 UTC (rev 1328) @@ -17,4 +17,7 @@ #define UNUSED __attribute__((unused)) +/** Useful for temporarily causing a variable to be "used." */ +#define USE(x) static_cast<void>(x) + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-07 01:26:04
|
Revision: 1369 http://assorted.svn.sourceforge.net/assorted/?rev=1369&view=rev Author: yangzhang Date: 2009-05-07 01:25:59 +0000 (Thu, 07 May 2009) Log Message: ----------- - major change to versioned_heap to place free bits inline in the pages - added formatting (format_array), crypto, atomic - extended concurrent_queue - fixed const-ness of array, sized_array - added write_file and made functions static/unused - enhanced the deque, but currently in a broken state - added alignof, clr_bit, set_bit_mut, clr_bit_mut, clear_bits_above, clear_bits_below Modified Paths: -------------- cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/deque.h cpp-commons/trunk/src/commons/files.h cpp-commons/trunk/src/commons/memory.h cpp-commons/trunk/src/commons/squeue.h cpp-commons/trunk/src/commons/versioned_heap.h Added Paths: ----------- cpp-commons/trunk/src/commons/atomic.h cpp-commons/trunk/src/commons/crypto.h cpp-commons/trunk/src/commons/formatting.h Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-05-05 21:24:40 UTC (rev 1368) +++ cpp-commons/trunk/src/commons/array.h 2009-05-07 01:25:59 UTC (rev 1369) @@ -32,10 +32,8 @@ T *get() const { return p_; } T *begin() const { return p_; } T *end() const { return p_ + n_; } - const T &operator[](size_t i) const { return p_[i]; } - T &operator[](size_t i) { return p_[i]; } - const T &at(size_t i) const { ASSERT(i < n_); return p_[i]; } - T &at(size_t i) { ASSERT(i < n_); return p_[i]; } + T &operator[](size_t i) const { return p_[i]; } + T &at(size_t i) const { ASSERT(i < n_); return p_[i]; } void reset(T *p, size_t n) { p_ = p; n_ = n; } private: T *p_; @@ -69,17 +67,14 @@ } return *this; } - operator const T*() const { return p_.get(); } - operator T*() { return p_.get(); } + operator T*() const { return p_.get(); } size_t size() const { return n_; } T *get() const { return p_.get(); } T *release() { return p_.release(); } T *begin() const { return p_.get(); } T *end() const { return this->get() + n_; } - const T &at(size_t i) const { ASSERT(i < n_); return p_[i]; } - T &at(size_t i) { ASSERT(i < n_); return p_[i]; } - const T &operator[](size_t i) const { return p_[i]; } - T &operator[](size_t i) { return p_[i]; } + T &at(size_t i) const { ASSERT(i < n_); return p_[i]; } + T &operator[](size_t i) const { return p_[i]; } void reset(T *p, size_t n) { p_.reset(p); n_ = n; } private: unique_ptr<T[]> p_; Added: cpp-commons/trunk/src/commons/atomic.h =================================================================== --- cpp-commons/trunk/src/commons/atomic.h (rev 0) +++ cpp-commons/trunk/src/commons/atomic.h 2009-05-07 01:25:59 UTC (rev 1369) @@ -0,0 +1,30 @@ +#ifndef COMMONS_ATOMIC_H +#define COMMONS_ATOMIC_H + +#include <boost/thread/mutex.hpp> + +namespace commons +{ + using namespace boost; + + template<typename T> + class atomic + { + private: + T x_; + mutex m_; + public: + atomic() {} + template<typename U> atomic(const U &x) : x_(x) {} + T get() { + mutex::scoped_lock lock(m_); + return x_; + } + void set(const T &x) { + mutex::scoped_lock lock(m_); + x_ = x; + } + }; +} + +#endif Added: cpp-commons/trunk/src/commons/crypto.h =================================================================== --- cpp-commons/trunk/src/commons/crypto.h (rev 0) +++ cpp-commons/trunk/src/commons/crypto.h 2009-05-07 01:25:59 UTC (rev 1369) @@ -0,0 +1,25 @@ +#ifndef COMMONS_CRYPTO_H +#define COMMONS_CRYPTO_H + +#include <openssl/sha.h> + +namespace commons { + + struct sha1md { + unsigned char md[SHA_DIGEST_LENGTH]; + }; + + UNUSED static sha1md + sha1(const char *data, size_t len) + { + sha1md md; + SHA_CTX c; + SHA1_Init(&c); + SHA1_Update(&c, data, len); + SHA1_Final(md.md, &c); + return md; + } + +} + +#endif Modified: cpp-commons/trunk/src/commons/deque.h =================================================================== --- cpp-commons/trunk/src/commons/deque.h 2009-05-05 21:24:40 UTC (rev 1368) +++ cpp-commons/trunk/src/commons/deque.h 2009-05-07 01:25:59 UTC (rev 1369) @@ -20,27 +20,70 @@ class deque { private: + class chunk { public: - chunk() : xs(node_size) {} - private: + chunk(size_t node_size) { xs.reserve(node_size); } vector<T> xs; }; list<chunk> chunks; size_t node_size; + public: + + class iterator + { + private: + typename list<chunk>::iterator c_; + size_t pos_; + public: + typedef forward_iterator_tag iterator_category; + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef value_type *pointer; + typedef value_type &reference; + iterator(const typename list<chunk>::iterator &c, size_t pos) : + c_(c), pos_(pos) {} + T &operator*() { return c_->xs[pos_]; } + T &operator->() { return c_->xs[pos_]; } + T &operator++() { + if (pos_ == c_->xs.size()) { + pos_ = 0; + ++c_; + } + return c_->xs[++pos_]; + } + T &operator++(int) { + T &x = *(*this); + ++(*this); + return x; + } + + bool operator==(const iterator &that) const { + return c_ == that.c_ && pos_ == that.pos_; + } + bool operator!=(const iterator &that) const { + return !(*this == that); + } + }; + + typedef iterator const_iterator; + deque(size_t node_size = 8192) : node_size(node_size) {} void push_back(const T& x) { - chunk& last = chunks.back(); - if (last.xs.size() == last.xs.capacity()) { - chunks.push_back(chunk()); + if (chunks.empty() || + chunks.back().xs.size() == chunks.back().xs.capacity()) { + chunks.push_back(chunk(node_size)); } - last.push_back(x); + chunks.back().xs.push_back(x); } + + iterator begin() { return iterator(chunks.begin(), 0); } + iterator end() { return iterator(chunks.end(), 0); } }; } Modified: cpp-commons/trunk/src/commons/files.h =================================================================== --- cpp-commons/trunk/src/commons/files.h 2009-05-05 21:24:40 UTC (rev 1368) +++ cpp-commons/trunk/src/commons/files.h 2009-05-07 01:25:59 UTC (rev 1369) @@ -32,7 +32,7 @@ /** * Get the size of a file in bytes. */ - off_t file_size(const char *path) + UNUSED static off_t file_size(const char *path) { struct stat s; check0x(stat(path, &s)); @@ -42,7 +42,7 @@ /** * Get the size of a file in bytes. */ - off_t file_size(int fd) + UNUSED static off_t file_size(int fd) { struct stat s; check0x(fstat(fd, &s)); @@ -52,7 +52,7 @@ /** * Read in a whole file as a string. */ - void read_file_as_string ( const string & name, string & out ) { + UNUSED static void read_file_as_string ( const string & name, string & out ) { ifstream in ( name.c_str() ); if (in.fail()) throw file_not_found_exception( name ); out = string ( istreambuf_iterator<char> ( in ), istreambuf_iterator<char>() ); @@ -61,7 +61,7 @@ /** * Read in a whole file as a vector of chars. */ - void read_file_as_vector ( const string & name, vector<char> & out ) { + UNUSED static void read_file_as_vector ( const string & name, vector<char> & out ) { ifstream in ( name.c_str() ); if ( in.fail() ) throw file_not_found_exception( name ); out = vector<char> ( istreambuf_iterator<char> ( in ), istreambuf_iterator<char>() ); @@ -70,21 +70,38 @@ /** * Read in a whole file as an array. */ - array<char> read_file_as_array(const char *path) + UNUSED static array<char> read_file_as_array(const char *path) { closingfd fd(checknnegerr(open(path, O_RDONLY))); array<char> buf(file_size(fd)); - checkeqnneg(read(fd, buf, buf.size()), static_cast<ssize_t>(buf.size())); + checkeqnneg(read(fd, buf, buf.size()), ssize_t(buf.size())); return buf; } /** + * Write a whole array to disk. + */ + UNUSED static void write_file(const char *path, const char *buf, size_t len) + { + closingfd fd(checknnegerr(creat(path, 0644))); + checkeqnneg(write(fd, buf, len), ssize_t(len)); + } + + /** + * Write a whole array to disk. + */ + UNUSED static void write_file(const char *path, const array<char> &buf) + { + write_file(path, buf, buf.size()); + } + + /** * Load an entire file directly into buf and also give us the length of the * 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? */ - char * + UNUSED static char * load_file(const char *path, size_t & len, unsigned int ncpus) { struct stat sb; Added: cpp-commons/trunk/src/commons/formatting.h =================================================================== --- cpp-commons/trunk/src/commons/formatting.h (rev 0) +++ cpp-commons/trunk/src/commons/formatting.h 2009-05-07 01:25:59 UTC (rev 1369) @@ -0,0 +1,40 @@ +#ifndef COMMONS_FORMATTING_H +#define COMMONS_FORMATTING_H + +#include <string> +#include <ostream> +#include <iomanip> +#include <commons/array.h> + +namespace commons { + + using namespace std; + + // TODO: change to standard ostream<< + + UNUSED static ostream & + format_array(ostream &out, const char *buf, size_t len) + { + for (size_t i = 0; i < len; ++i) { + out << hex << setfill('0') << setw(2) << buf[i] << len; + } + return out; + } + + UNUSED static ostream & + format_array(ostream &out, const array<char> arr) + { + return format_array(out, arr, arr.size()); + } + + UNUSED static string + format_array_as_string(const char *buf, size_t len) + { + stringstream ss; + format_array(ss, buf, len); + return ss.str(); + } + +} + +#endif Modified: cpp-commons/trunk/src/commons/memory.h =================================================================== --- cpp-commons/trunk/src/commons/memory.h 2009-05-05 21:24:40 UTC (rev 1368) +++ cpp-commons/trunk/src/commons/memory.h 2009-05-07 01:25:59 UTC (rev 1369) @@ -2,11 +2,16 @@ #define COMMONS_MEMORY_H #include <cstring> // for size_t +#include <limits> #include <commons/utility.h> // for UNUSED +#define alignof __alignof__ // gcc + namespace commons { + using namespace std; + /** * Copy a datum directly to a memory location. Useful for serializing small * data (e.g. ints). Faster than memcpy. @@ -40,7 +45,8 @@ template<typename T> void write(const T &x) { memput(p_, x); p_ += sizeof(T); } /** Get the current value of the pointer. */ - void *ptr() const { return p_; } + char *ptr() const { return p_; } + char *&ptr() { return p_; } /** Skip n bytes. */ void skip(size_t n) { p_ += n; } }; @@ -57,13 +63,16 @@ 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_; } + char *readptr(size_t n) { char *p = p_; p_ += n; return p; } + char *ptr() const { return p_; } + char *&ptr() { return p_; } void skip(size_t n) { p_ += n; } }; - /** Round `value` up to the nearest multiple of `unit` and return this - * factor. */ + /** + * Return `ceil(value / factor)`. Round `value` up to the nearest multiple + * of `unit` and return this factor. + */ template<typename T> T whole_units(T value, T unit) { return (value + unit - 1) / unit; @@ -85,12 +94,31 @@ return x | (1U << bit); } - /** Note: there exists a setbit macro in /usr/include/sys/param.h */ template<typename T> - T set_bit(T x, size_t bit, T val) { - return x | (val << bit); + T clr_bit(T x, size_t bit) { + return x & ~(1U << bit); } + template<typename T> + void set_bit_mut(T &x, size_t bit) { + x |= 1U << bit; + } + + template<typename T> + void clr_bit_mut(T &x, size_t bit) { + x &= ~(1U << bit); + } + + template<typename T> + T clear_bits_below(T x, size_t nbits) { + return x & (~T(0) << nbits); + } + + template<typename T> + T clear_bits_above(T x, size_t nbits) { + return x & (~T(0) >> (numeric_limits<T>::digits - nbits)); + } + } #endif Modified: cpp-commons/trunk/src/commons/squeue.h =================================================================== --- cpp-commons/trunk/src/commons/squeue.h 2009-05-05 21:24:40 UTC (rev 1368) +++ cpp-commons/trunk/src/commons/squeue.h 2009-05-07 01:25:59 UTC (rev 1369) @@ -19,6 +19,18 @@ condition_variable c_; public: + /** + * Push x onto queue iff queue.size() <= n. + */ + template<typename U> void push_cond(U &&x, size_t n) + { + mutex::scoped_lock lock(m_); + if (q_.size() <= n) + q_.push(forward<U>(x)); + lock.unlock(); + c_.notify_one(); + } + template<typename U> void push(U &&x) { mutex::scoped_lock lock(m_); @@ -27,6 +39,12 @@ c_.notify_one(); } + size_t size() const + { + mutex::scoped_lock lock(m_); + return q_.size(); + } + bool empty() const { mutex::scoped_lock lock(m_); Modified: cpp-commons/trunk/src/commons/versioned_heap.h =================================================================== --- cpp-commons/trunk/src/commons/versioned_heap.h 2009-05-05 21:24:40 UTC (rev 1368) +++ cpp-commons/trunk/src/commons/versioned_heap.h 2009-05-07 01:25:59 UTC (rev 1369) @@ -5,7 +5,10 @@ #include <cstdlib> #include <vector> #include <boost/foreach.hpp> +#include <deque> #include <commons/memory.h> +#include <commons/nullptr.h> +#include <boost/pending/lowest_bit.hpp> #define foreach BOOST_FOREACH namespace commons @@ -13,67 +16,241 @@ using namespace std; + class simple_bitset + { + private: + typedef uint32_t Block; + Block words[0]; + static const size_t bits_per_block = numeric_limits<Block>::digits; + public: + /** Initialize all bits. */ + simple_bitset(size_t nwords, Block value = ~Block(0)) { + for (size_t word = 0; word < nwords; ++word) + words[word] = value; + } + /** Find the first bit. */ + size_t find_first(size_t nwords) { + for (size_t word = 0; word < nwords; ++word) + if (words[word] != 0) + return word * bits_per_block + lowest_bit(words[word]); + return size_t(-1); + } + /** Which word contains bit `i`? */ + static size_t bit2word(size_t i) { return i / bits_per_block; } + /** Which bit within the word is bit `i`? */ + static size_t bit2bit(size_t i) { return i & (bits_per_block - 1); } + /** Set the i-th bit. */ + void set(size_t i) { set_bit_mut(words[bit2word(i)], bit2bit(i)); } + /** Clear the i-th bit. */ + void clr(size_t i) { clr_bit_mut(words[bit2word(i)], bit2bit(i)); }; + /** Get the i-th bit. */ + bool get(size_t i) { return (words[bit2word(i)] >> bit2bit(i)) & 1; } + }; + + template<typename T, typename V = int> class versioned_heap; + /** + * Calculates the number of elements we can pack into a page based on the + * freemap size and the size and alignment of the value type. + */ + template<typename T> + void compute_layout(size_t pgsz, size_t &pgcnt, + size_t &values_offset, size_t &freemap_words) + { + typedef typename commons::versioned_heap<T>::hdr hdr; + // TODO The following is correct. + // + // Memory layout diagram: + // + // [header][freemap ] [value 0]... + // [word 0][word 1][word 2][word 3] + // [align 0][align 1][align 2][align 3][align 4]... + // + // TODO The following is incorrect. + // + // Memory layout diagram: + // + // [header][freemap ] [value 0]... + // [word 0][word 1][word 2] + // [align 0][align 1][align 2][align 3]... + // [freemap bytes by align ] + // + // Calculate the maximum possible amount of space we can reserve for the + // freemap based on the alignof(T). This is also the + // + // Let's call each unit of alignof(T) bytes an _align. + // + // Then the formula is: + // + // naligns * alignment + naligns * 8 * alignment * sizeof(T) <= pgsz + // + // Solve for naligns: + // + // naligns = pgsz / (alignment + 8 * alignment * sizeof(T)) + UNUSED size_t a = alignof(T), b = sizeof(T); + + // TODO: use simple_bitset instead and address the following: + // warning: invalid access to non-static data member `CNeoIOBlock::fPB' of NULL object + // warning: (perhaps the `offsetof' macro was used incorrectly) + struct foo { hdr h; uint32_t fm; }; + size_t freemap_offset = offsetof(foo, fm); + size_t freemap_aligns_by_alignment = + (pgsz - freemap_offset) / (alignof(T) + 8 * alignof(T) * sizeof(T)); + + // Try to increase the space by 1 alignment if possible, since the last + // alignment might have sent the space required for actual objects over the + // limit. + if (freemap_offset + + (freemap_aligns_by_alignment + 1) * alignof(T) + + freemap_aligns_by_alignment * 8 * alignof(T) * sizeof(T) < pgsz) + ++freemap_aligns_by_alignment; + + size_t freemap_bytes_by_alignment = + max(sizeof(uint32_t), freemap_aligns_by_alignment * alignof(T)); + values_offset = freemap_offset + freemap_bytes_by_alignment; + + // Now see how many uint32_t's we can fit into this space. Our freemap + // implementation only uses whole uint32_t's for efficiency. This will + // yield the exact length of the freemap. + + freemap_words = freemap_bytes_by_alignment / sizeof(uint32_t); + size_t freemap_bytes = freemap_words * sizeof(uint32_t); + + // Now we know how much space remains for the number of elements. + + pgcnt = ( pgsz - freemap_offset - freemap_bytes ) / sizeof(T); + } + + /** * A simple object memory pool that places things into pages that are tagged * with a version number. */ - template<typename T, typename VersionType = int> + template<typename T, typename VersionType> class versioned_heap { public: typedef VersionType version_type; typedef T value_type; struct hdr { + // Version number of this page. version_type version; - uint32_t index; + // Index. Defines ordering in pages_. Used for + // serialization. + size_t index; + // Slightly tricky semantics. next_free == nullptr if not in free list + // *or* if it's the last node in the free list. + hdr *next_free; + // Whether this page is memory-managed by the heap, or if it's + // externally managed. Deserialized pages are externally managed, in + // order to reduce the amount of memory copies when deserializing. bool managed; }; + + class iterator + { + private: + versioned_heap &h_; + typename deque<char*>::iterator page_; + size_t pos_; + + /** + * Advance to next valid entry and return it. + */ + T *advance() { + do { + if (++pos_ == h_.pgcnt()) { + pos_ = 0; + ++page_; + if (page_ == h_.pages().end()) + return nullptr; + } + } while (h_.freemapof(*page_).get(pos_)); + return h_.firstof(*page_) + pos_; + } + + public: + iterator(versioned_heap &h) : + h_(h), page_(h.pages_.begin()), pos_(0) + { + // If the first slot is invalid, advance to first valid slot. + if (h_.freemapof(*page_).get(pos_)) + advance(); + } + + /** Return current. */ + T *cur() { + return page_ == h_.pages().end() ? + nullptr : h_.firstof(*page_) + pos_; + } + + /** Return current and advance to next. */ + T *next() { + T *ret = cur(); + if (ret != nullptr) advance(); + return ret; + } + }; + versioned_heap(size_t pgsz = 131072) : - last_i_(0), pgsz_(pgsz), pgcnt_((pgsz - sizeof(hdr)) / sizeof(T)) {} + first_free_(nullptr), + last_free_(nullptr), + pgsz_(pgsz) + { + compute_layout<T>(pgsz, pgcnt_, values_offset_, freemap_words_); + } /** Frees all pages, without destroying the objects. */ ~versioned_heap() { foreach (char *page, pages_) if (hdrof(page).managed) ::free(page); } - char *alloc() { - for (size_t counter = 1; counter <= freemap_.size(); ++counter) { - size_t i = (last_i_ + counter) % freemap_.size(); - if (freemap_[i]) { - freemap_[i] = false; - char *pos = pages_[i / pgcnt_] + sizeof(hdr) + - (i % pgcnt_) * sizeof(T); - ++hdrof(pos).version; - last_i_ = i; + + T *alloc() { + while (first_free_ != nullptr) { + // Find the first free slot. + simple_bitset &freemap = freemapof(first_free_); + size_t i = freemap.find_first(freemap_words_); + if (i < pgcnt_) { + freemap.clr(i); + T *pos = firstof(first_free_) + i; + // Touch the page. + ++first_free_->version; return pos; } + // Pop this page off the front of the free list. + hdr *old = first_free_; + first_free_ = first_free_->next_free; + old->next_free = nullptr; } + char *page; posix_memalign(reinterpret_cast<void**>(&page), pgsz_, pgsz_); hdr &h = *reinterpret_cast<hdr*>(page); h.version = 0; - h.index = uint32_t(pages_.size()); + h.index = pages_.size(); + h.next_free = nullptr; h.managed = true; + first_free_ = last_free_ = &h; pages_.push_back(page); - freemap_.resize(freemap_.size() + pgcnt_, true); - freemap_[freemap_.size() - pgcnt_] = false; - return page + sizeof(hdr); + (new (&freemapof(page)) simple_bitset(freemap_words_))->clr(0); + return firstof(page); } + T &construct() { - char *buf = alloc(); + T *buf = alloc(); try { return *new (buf) T; } catch (...) { free(buf); throw; } } // TODO: replace with code gen template<typename A0> T &construct(const A0 &a0) { - char *buf = alloc(); + T *buf = alloc(); try { return *new (buf) T(a0); } catch (...) { free(buf); throw; } } template<typename A0, typename A1> T &construct(const A0 &a0, const A1 &a1) { - char *buf = alloc(); + T *buf = alloc(); try { return *new (buf) T(a0, a1); } catch (...) { free(buf); throw; } } @@ -81,9 +258,19 @@ hdr &h = hdrof(p); if (version == 0) ++h.version; else h.version = version; - char *px = reinterpret_cast<char*>(p); - char *p0 = reinterpret_cast<char*>(&h + 1); - freemap_[h.index * pgcnt_ + (px - p0) / sizeof(T)] = true; + T *px = reinterpret_cast<T*>(p); + T *p0 = firstof(&h); + freemapof(&h).set(px - p0); + + // If this page is not in the free list, then add it to the free list. + if (h.next_free == nullptr && last_free_ != &h) { + h.next_free = first_free_; + // If the free list is empty, initialize it. + if (first_free_ == nullptr) { + last_free_ = &h; + } + first_free_ = &h; + } } void destroy(T &x, version_type version = 0) { x.~T(); @@ -93,23 +280,38 @@ void touch(T &p, version_type version) { hdrof(&p).version = version; } size_t pgcnt() const { return pgcnt_; } size_t pgsz() const { return pgsz_; } - const vector<char*> &pages() const { return pages_; } + const deque<char*> &pages() const { return pages_; } + + // + // Page structure accessors. + // + /** Pronounced "header of". */ - const hdr &hdrof(void *p) const { + const hdr &hdrof(const void *p) const { return *reinterpret_cast<hdr*>(uintptr_t(p) & ~(pgsz_ - 1)); } hdr &hdrof(void *p) { return *reinterpret_cast<hdr*>(uintptr_t(p) & ~(pgsz_ - 1)); } + // TODO: use simple_bitset instead and address the following: + // warning: invalid access to non-static data member `CNeoIOBlock::fPB' of NULL object + // warning: (perhaps the `offsetof' macro was used incorrectly) + struct foo { hdr h; uint32_t fm; }; + simple_bitset &freemapof(void *page) { + return *reinterpret_cast<simple_bitset*>(reinterpret_cast<char*>(page) + offsetof(foo, fm)); + } + T *firstof(void *p) { + return reinterpret_cast<T*>(reinterpret_cast<char*>(p) + + values_offset_); + } /** * Calculate the required space for serializing the metadata. */ size_t metasize() const { - return sizeof last_i_ + sizeof pgsz_ + sizeof pgcnt_ + - sizeof freemap_.size() + - nbits2nints(freemap_.size()) * sizeof(uint32_t) + - sizeof datasize(*this); + return sizeof pgsz_ + + sizeof(size_t) + sizeof(size_t) + // first_free_, last_free_ + sizeof datasize(*this); } /** @@ -120,71 +322,79 @@ } /** - * Serializes metadata and data to out buffer. + * Serializes metadata to buffer. */ - void ser(void *meta, void *data) const { + void sermeta(void *meta) const { raw_writer w(meta); - - // Serialize metadata. - w.write(last_i_); + w.write(ptr2ind(first_free_)); + w.write(ptr2ind(last_free_)); w.write(pgsz_); - w.write(pgcnt_); + w.write(datasize(*this)); + } - // Serialize freemap. - w.write(freemap_.size()); - size_t freesize = nbits2nints(freemap_.size()); - for (size_t i = 0; i < freesize; ++i) { - uint32_t val = 0; - for (size_t j = 0; j < 32 && 32 * i + j < freemap_.size(); ++j) { - val = set_bit(val, j, uint32_t(freemap_[32 * i + j])); - } - w.write(val); - } - - // Serialize data. - w.write(datasize(*this)); + /** + * Serializes metadata and data to out buffer. + */ + void ser(void *meta, void *data) const { + sermeta(meta); serdata(*this, data); } /** - * Deserializes a heap in-place. + * Deserialize a heap in place. */ void deser(void *meta, void *data) { + size_t datasize = desermeta(meta, data); + deserdata(datasize, data); + } + + /** + * Iterator. + */ + iterator begin() { return iterator(*this); } + + private: + hdr *first_free_; + hdr *last_free_; + size_t pgsz_; + size_t pgcnt_; + size_t values_offset_; + size_t freemap_words_; + deque<char*> pages_; + + /** + * Deserializes a heap in-place, returning the length of the serialized + * data. + */ + size_t desermeta(void *meta, void *data) { raw_reader r(meta); // Deserialize metadata. - r.read(last_i_); + r.read(reinterpret_cast<size_t&>(first_free_)); + r.read(reinterpret_cast<size_t&>(last_free_)); r.read(pgsz_); - r.read(pgcnt_); + char *p0 = reinterpret_cast<char*>(data); + ind2ptr_mut(first_free_, p0, pgsz_); + ind2ptr_mut(last_free_, p0, pgsz_); + compute_layout<T>(pgsz_, pgcnt_, values_offset_, freemap_words_); - // Deserialize freemap. - size_t nbits; - r.read(nbits); - size_t nints = nbits2nints(nbits); - for (size_t i = 0; i < nints; ++i) { - uint32_t val; - r.read(val); - for (size_t j = 0; j < nbits && 32 * i + j < nbits; ++j) { - freemap_.push_back(get_bit(val, j)); - } - } + // Deserialize data. + return r.read<size_t>(); + } - // Deserialize data. - size_t datasize; - r.read(datasize); + /** + * Deserialize a heap in place. + */ + void deserdata(size_t len, void *data) { + pages_.clear(); char *p0 = reinterpret_cast<char*>(data); - for (char *p = p0; p < p0 + datasize; p += pgsz_) { + for (char *p = p0; p < p0 + len; p += pgsz_) { hdrof(p).managed = false; pages_.push_back(p); + ind2ptr_mut(hdrof(p).next_free, p0, pgsz_); } } - private: - size_t last_i_; - size_t pgsz_; - size_t pgcnt_; - vector<bool> freemap_; - vector<char*> pages_; }; /** @@ -201,15 +411,41 @@ * (see datasize). */ template<typename T> - void serdata(const versioned_heap<T> &h, void *out) + void serdata(const versioned_heap<T> &heap, void *out) { char *p = reinterpret_cast<char*>(out); - foreach (void *page, h.pages()) { - memcpy(p, page, h.pgsz()); - p += h.pgsz(); + size_t i = 0; + foreach (void *page, heap.pages()) { + memcpy(p, page, heap.pgsz()); + typedef typename versioned_heap<T>::hdr hdr; + hdr &h = *reinterpret_cast<hdr*>(p); + assert(i == h.index); + ptr2ind_mut(h.next_free); + p += heap.pgsz(); + ++i; } } + template<typename T> + size_t ptr2ind(T *p) { + return p == nullptr ? size_t(-1) : p->index; + } + + template<typename T> + void ptr2ind_mut(T *&p) { + p = reinterpret_cast<T*>(ptr2ind(p)); + } + + template<typename T> + T *ind2ptr(size_t i, char *pages, size_t pgsz) { + return reinterpret_cast<T*>(i == size_t(-1) ? nullptr : pages + pgsz * i); + } + + template<typename T> + void ind2ptr_mut(T *&p, char *pages, size_t pgsz) { + p = ind2ptr<T>(reinterpret_cast<size_t>(p), pages, pgsz); + } + } #undef foreach This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-05-11 21:46:32
|
Revision: 1404 http://assorted.svn.sourceforge.net/assorted/?rev=1404&view=rev Author: yangzhang Date: 2009-05-11 21:46:03 +0000 (Mon, 11 May 2009) Log Message: ----------- fixed some build warnings Modified Paths: -------------- cpp-commons/trunk/src/commons/files.h cpp-commons/trunk/src/commons/versioned_heap.h Modified: cpp-commons/trunk/src/commons/files.h =================================================================== --- cpp-commons/trunk/src/commons/files.h 2009-05-08 10:43:41 UTC (rev 1403) +++ cpp-commons/trunk/src/commons/files.h 2009-05-11 21:46:03 UTC (rev 1404) @@ -108,7 +108,8 @@ closingfd fd(checknnegerr(open(path, O_RDONLY))); check0x(fstat(fd, &sb)); - check(sb.st_size <= 0xffffffff); + // TODO why waaas this herre? + // check(sb.st_size <= 0xffffffff); // TODO Why don't we need (static) cast here? Isn't this a lossy cast? len = sb.st_size; Modified: cpp-commons/trunk/src/commons/versioned_heap.h =================================================================== --- cpp-commons/trunk/src/commons/versioned_heap.h 2009-05-08 10:43:41 UTC (rev 1403) +++ cpp-commons/trunk/src/commons/versioned_heap.h 2009-05-11 21:46:03 UTC (rev 1404) @@ -224,7 +224,7 @@ } char *page; - posix_memalign(reinterpret_cast<void**>(&page), pgsz_, pgsz_); + check0x(posix_memalign(reinterpret_cast<void**>(&page), pgsz_, pgsz_)); hdr &h = *reinterpret_cast<hdr*>(page); h.version = 0; h.index = pages_.size(); @@ -370,8 +370,15 @@ raw_reader r(meta); // Deserialize metadata. - r.read(reinterpret_cast<size_t&>(first_free_)); - r.read(reinterpret_cast<size_t&>(last_free_)); + size_t first_free, last_free; + r.read(first_free); + r.read(last_free); + first_free_ = reinterpret_cast<hdr*>(first_free); + last_free_ = reinterpret_cast<hdr*>(last_free); + // TODO why do next 2 lines this give me this warning? + // error: dereferencing type-punned pointer will break strict-aliasing rules + //r.read(reinterpret_cast<size_t&>(first_free_)); + //r.read(reinterpret_cast<size_t&>(last_free_)); r.read(pgsz_); char *p0 = reinterpret_cast<char*>(data); ind2ptr_mut(first_free_, p0, pgsz_); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-10-15 08:26:20
|
Revision: 1493 http://assorted.svn.sourceforge.net/assorted/?rev=1493&view=rev Author: yangzhang Date: 2009-10-15 08:26:09 +0000 (Thu, 15 Oct 2009) Log Message: ----------- added windows support; added addr2name, name2addr, checkptr Modified Paths: -------------- cpp-commons/trunk/src/commons/check.h cpp-commons/trunk/src/commons/closing.h cpp-commons/trunk/src/commons/die.h cpp-commons/trunk/src/commons/sockets.h Added Paths: ----------- cpp-commons/trunk/src/commons/win.h Modified: cpp-commons/trunk/src/commons/check.h =================================================================== --- cpp-commons/trunk/src/commons/check.h 2009-10-14 18:10:19 UTC (rev 1492) +++ cpp-commons/trunk/src/commons/check.h 2009-10-15 08:26:09 UTC (rev 1493) @@ -5,6 +5,10 @@ #include <sstream> #include <string> #include <commons/die.h> +#include <commons/utility.h> +#include <commons/win.h> +#include <commons/nullptr.h> +#include <boost/noncopyable.hpp> #include <boost/lexical_cast.hpp> // TODO: rename: @@ -28,6 +32,13 @@ namespace commons { +#ifdef WIN32 +#define wvsnprintf(buf, len, fmt, args) \ + { USE(buf); USE(len); USE(fmt); USE(args); } +// TODO get this to build! +// #define vsnprintf(buf, len, fmt, args) vsnprintf_s(buf, len, _TRUNCATE, fmt, args) +#endif + enum { buflen = 4096 }; // TODO: deal with va args @@ -44,7 +55,7 @@ virtual ~check_exception() throw() {} virtual const char *what() const throw() { return name.c_str(); } private: - const string name; + string name; }; __attribute__((format(printf, 4, 0))) inline static void @@ -85,6 +96,13 @@ } template<typename T> inline T + _checkptr(T x, const char *file, int line) + { + _check(x != nullptr, file, line); + return x; + } + + template<typename T> inline T _checknneg(T x, const char *file, int line) { if (x < 0) { @@ -177,8 +195,10 @@ * use as a guard against expected failures (such as checking return codes). * This is a macro for two reasons: (1) the file and line, and (2) the lazy * evaluation of msg. + * + * check(result, "bad result %d", result) */ -#define check(cond, msg...) _check(cond, __FILE__, __LINE__, ## msg) +#define check(cond, ...) commons::_check(cond, __FILE__, __LINE__, ## __VA_ARGS__) /** * Same as check(), but additionally returns the value that was passed in. The @@ -187,53 +207,58 @@ * return value is non-zero or not false). This is suitable for small, * copyable pieces of data, such as integers, file descriptors, pointers, etc. */ -#define checkpass(expr, msg...) _checkpass(expr, __FILE__, __LINE__, ## msg) +#define checkpass(expr, ...) commons::_checkpass(expr, __FILE__, __LINE__, ## __VA_ARGS__) /** + * Check that a pointer is not NULL. + */ +#define checkptr(expr, ...) commons::_checkptr(expr, __FILE__, __LINE__, ## __VA_ARGS__) + +/** * Same as checkpass(), but includes the strerror message in the exception. */ -#define checkerr(expr) _checkerr(expr, __FILE__, __LINE__) +#define checkerr(expr) commons::_checkerr(expr, __FILE__, __LINE__) /** * Checks that the value is non-negative. */ -#define checknneg(expr, msg...) _checknneg(expr, __FILE__, __LINE__, ## msg) +#define checknneg(expr, ...) commons::_checknneg(expr, __FILE__, __LINE__, ## __VA_ARGS__) /** * Same as checknneg, but include the strerror in the exception. */ -#define checknnegerr(expr) _checknnegerr(expr, __FILE__, __LINE__) +#define checknnegerr(expr) commons::_checknnegerr(expr, __FILE__, __LINE__) /** * Checks that the value is 0. Same as check0(), but throws an error rather * than return. Also clears the errno on error. The resulting exception * includes the strerror(). */ -#define check0x(expr, msg...) _check0(expr, __FILE__, __LINE__, ## msg) +#define check0x(expr, ...) commons::_check0(expr, __FILE__, __LINE__, ## __VA_ARGS__) /** * Checks that the values are not equal. The exception will include both * values, as formatted by ostream <<. */ -#define checkneq(l, r, msg...) _checkneq(l, r, __FILE__, __LINE__, ## msg) +#define checkneq(l, r, ...) commons::_checkneq(l, r, __FILE__, __LINE__, ## __VA_ARGS__) /** * Checks that the values are equal. The exception will include both values, * as formatted by ostream <<. */ -#define checkeq(l, r, msg...) _checkeq(l, r, __FILE__, __LINE__, ## msg) +#define checkeq(l, r, ...) commons::_checkeq(l, r, __FILE__, __LINE__, ## __VA_ARGS__) /** * Like checkeq, but if the left value is negative, then interpret that as a * sign of error, and include the errorstr in the exception message. */ -#define checkeqnneg(l, r, msg...) \ - _checkeqnneg(l, r, __FILE__, __LINE__, ## msg) +#define checkeqnneg(l, r, ...) \ + commons::_checkeqnneg(l, r, __FILE__, __LINE__, ## __VA_ARGS__) #if 0 #define checkmsg(cond, msg) \ bool b__ = cond; \ - if (!b__) _check(b__, (msg), __FILE__, __LINE__) + if (!b__) commons::_check(b__, (msg), __FILE__, __LINE__) #define checkmsgf(cond, msg...) \ do { \ @@ -241,7 +266,7 @@ if (!b__) { \ char s__[4096]; \ snprintf(s, msg); \ - _check(b__, s__, __FILE__, __LINE__); \ + commons::_check(b__, s__, __FILE__, __LINE__); \ } \ } while (0) #endif @@ -261,10 +286,10 @@ /** * Checks that the value is true or non-zero, otherwise dies (calls die()). */ -#define checkdie(expr, msg...) \ +#define checkdie(expr, ...) \ do { \ if (!expr) { \ - die(msg); \ + die(__VA_ARGS__); \ } \ } while (0) Modified: cpp-commons/trunk/src/commons/closing.h =================================================================== --- cpp-commons/trunk/src/commons/closing.h 2009-10-14 18:10:19 UTC (rev 1492) +++ cpp-commons/trunk/src/commons/closing.h 2009-10-15 08:26:09 UTC (rev 1493) @@ -4,15 +4,18 @@ #include <boost/utility.hpp> #include <commons/check.h> #include <commons/utility.h> +#include <commons/win.h> +#include <cstdio> namespace commons { using namespace boost; + using namespace std; // void checked_close(int &fd) { check0x(close(fd)); } - struct fd_closer { static void apply(int fd) { check0x(close(fd)); } }; + struct fd_closer { static void apply(fd_t fd) { check0x(close(fd)); } }; template<typename T, typename Closer> class closing @@ -29,7 +32,7 @@ bool scoped; }; - typedef closing<int, fd_closer> closingfd; + typedef closing<fd_t, fd_closer> closingfd; } Modified: cpp-commons/trunk/src/commons/die.h =================================================================== --- cpp-commons/trunk/src/commons/die.h 2009-10-14 18:10:19 UTC (rev 1492) +++ cpp-commons/trunk/src/commons/die.h 2009-10-15 08:26:09 UTC (rev 1493) @@ -1,6 +1,7 @@ #ifndef COMMONS_DIE_H #define COMMONS_DIE_H +#include <commons/win.h> #include <cerrno> #include <cstdio> #include <cstdarg> @@ -15,6 +16,8 @@ * * TODO: move into C Commons. */ +//#pragma warning(push) TODO why doesn't this work? +#pragma warning(disable: 4505) __attribute__((format(printf, 1, 2),unused)) static void die(const char *format, ...) { @@ -27,6 +30,7 @@ fprintf(stderr, ": %s\n", errstr); exit(1); } +//#pragma warning(pop) } Modified: cpp-commons/trunk/src/commons/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/sockets.h 2009-10-14 18:10:19 UTC (rev 1492) +++ cpp-commons/trunk/src/commons/sockets.h 2009-10-15 08:26:09 UTC (rev 1493) @@ -1,6 +1,9 @@ #ifndef COMMONS_SOCKETS_H #define COMMONS_SOCKETS_H +#ifdef WIN32 +#include <winsock2.h> +#else #include <arpa/inet.h> #include <netdb.h> #include <netinet/in.h> @@ -9,6 +12,7 @@ #include <sys/types.h> #include <fcntl.h> #include <unistd.h> +#endif #include <commons/check.h> #include <commons/closing.h> @@ -17,6 +21,19 @@ namespace commons { +#ifdef WIN32 + typedef SOCKET socket_t; + + int inet_aton(const char *cp, struct in_addr *inp) { + uint32_t a = inet_addr(cp); + if (a == INADDR_NONE) return 0; + inp->S_un.S_addr = a; + return 1; + } +#else + typedef fd_t socket_t; +#endif + /** * Work-around for the -Wold-style-cast-unsafe FD_* macros (see select(2)). */ @@ -26,26 +43,35 @@ /** * Work-around for the -Wold-style-cast-unsafe INADDR_ANY */ +#ifndef WIN32 const in_addr_t inaddr_any = in_addr_t(0); +#else +#define inaddr_any INADDR_ANY +#endif /** * Make a TCP socket non-blocking. */ - inline int - set_non_blocking(int fd) + inline socket_t + set_non_blocking(socket_t fd) { +#ifndef WIN32 checknnegerr(fcntl(fd, F_SETFL, O_NONBLOCK | checknnegerr(fcntl(fd, F_GETFL, 0)))); +#else + unsigned long one = 1; + checknnegerr(ioctlsocket(fd, FIONBIO, &one)); +#endif return fd; } /** * Create a TCP socket. */ - inline int + inline socket_t tcp_socket(bool nb) { - int fd = checknnegerr(socket(PF_INET, SOCK_STREAM, 0)); + socket_t fd = checknnegerr(socket(PF_INET, SOCK_STREAM, 0)); // Make our socket non-blocking if desired. if (nb) set_non_blocking(fd); return fd; @@ -84,7 +110,7 @@ // First try to interpret host as a dot-notation string. if (!inet_aton(host, reinterpret_cast<in_addr*>(&a.sin_addr.s_addr))) { // Now try to resolve the hostname. - hostent *res = checkpass(gethostbyname(host)); + hostent *res = checkptr(gethostbyname(host)); memcpy(&a.sin_addr, res->h_addr_list[0], res->h_length); } } @@ -101,6 +127,16 @@ } /** + * Initialize an inet addres. + */ + inline void + sockaddr_init(sockaddr_in &a, uint32_t host, uint16_t port) + { + sockaddr_init(a, port); + a.sin_addr.s_addr = host; + } + + /** * Construct an inet address. */ template <typename T> @@ -112,18 +148,28 @@ return a; } + void close_socket(socket_t s) { +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + } + struct socket_closer { static void apply(socket_t s) { close_socket(s); } }; + typedef closing<socket_t, socket_closer> closing_socket; + /** * Create a server socket bound to localhost, with SO_REUSEADDR enabled. * \param[in] port The port to listen on. * \param[in] nb Whether the socket should be non-blocking. * \return The server socket. */ - UNUSED static int + UNUSED static socket_t server_socket(uint16_t port, bool nb = false) { // Create the socket. - closingfd c(tcp_socket(nb)); - int fd = c.get(); + closing_socket c(tcp_socket(nb)); + socket_t fd = c.get(); // Configure the socket. int n = 1; @@ -145,17 +191,17 @@ * \param[in] nb Whether the socket should be non-blocking. * \return The listener socket. */ - UNUSED static int + UNUSED static socket_t tcp_listen(uint16_t port, bool nb = false) { - int fd = server_socket(port, nb); + socket_t fd = server_socket(port, nb); try { // SOMAXCONN is the kernel's limit on the maximum number of socket // connections. check0x(listen(fd, SOMAXCONN)); return fd; } catch (...) { - close(fd); + close_socket(fd); throw; } } @@ -163,15 +209,61 @@ /** * Connect to a TCP socket. */ - UNUSED static int - tcp_connect(const char *host, uint16_t port) + template<typename T> + UNUSED static socket_t + tcp_connect(T host, uint16_t port) { - closingfd c(tcp_socket(false)); + closing_socket c(tcp_socket(false)); sockaddr_in a = make_sockaddr(host, port); check0x(connect(c.get(), reinterpret_cast<sockaddr*>(&a), sizeof a)); return c.release(); } +#if defined(WIN32) && defined(UNICODE) +#define getnameinfo GetNameInfoW +#define getaddrinfo GetAddrInfoW +#define addrinfo ADDRINFOW +#define freeaddrinfo FreeAddrInfoW +#endif + + /** + * T is a string or wstring. + */ + template<typename T> + sockaddr_in + addr2name(const sockaddr_in sa) + { + enum { sz = 1024 }; + wchar_t buf[sz]; + check0x(getnameinfo(reinterpret_cast<const sockaddr*>(&sa), sizeof sa, + buf, sz, // output hostname + nullptr, 0, // service + 0)); // flags + return sa; + } + + /** + * Get IPv4 address for hostname. T is a string or wstring. + */ + template<typename T> + in_addr + name2addr(const T *name) + { + addrinfo *ai, hints = {0}; + in_addr addr; + hints.ai_family = AF_INET; // use AF_UNSPEC for "any" + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + check0x(getaddrinfo(name, // hostname + L"1", // service + &hints, // flags + &ai)); // output addrinfo + // just take the first one; ignore everything but in_addr + addr = reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_addr; + freeaddrinfo(ai); + return addr; + } + } #endif Added: cpp-commons/trunk/src/commons/win.h =================================================================== --- cpp-commons/trunk/src/commons/win.h (rev 0) +++ cpp-commons/trunk/src/commons/win.h 2009-10-15 08:26:09 UTC (rev 1493) @@ -0,0 +1,17 @@ +#ifndef COMMONS_WIN_H +#define COMMONS_WIN_H + +#ifdef WIN32 +# define NONWIN(x) +# define __attribute__(x) +typedef HANDLE fd_t; +int close(fd_t fd) { return CloseHandle(fd) ? 0 : -1; } +typedef UINT16 uint16_t; +typedef UINT32 uint32_t; +void bzero(void *s, size_t n) { memset(s, 0, n); } +#else +# define NONWIN(x) x +typedef int fd_t; +#endif + +#endif Property changes on: cpp-commons/trunk/src/commons/win.h ___________________________________________________________________ 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-11-09 04:18:55
|
Revision: 1511 http://assorted.svn.sourceforge.net/assorted/?rev=1511&view=rev Author: yangzhang Date: 2009-11-09 04:18:43 +0000 (Mon, 09 Nov 2009) Log Message: ----------- - added resolver.h, functions.h, cxx0x.h - added socket-related data structure converters - added hexfmt - added to_string, to_wstring for windows code page/wide char conversions - added to_utf8, to_utf16 converters - fixed stream formatter for vectors - conditional (non-WIN32) compilation of unique_ptr, array, files.h - more overloads in files.h - removed executable properties on files Modified Paths: -------------- cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/files.h cpp-commons/trunk/src/commons/sockets.h cpp-commons/trunk/src/commons/streams.h cpp-commons/trunk/src/commons/strings.h cpp-commons/trunk/src/commons/unique_ptr.h Added Paths: ----------- cpp-commons/trunk/src/commons/cxx0x.h cpp-commons/trunk/src/commons/functions.h cpp-commons/trunk/src/commons/resolver.h Property Changed: ---------------- cpp-commons/trunk/src/commons/win.h Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-11-08 18:27:35 UTC (rev 1510) +++ cpp-commons/trunk/src/commons/array.h 2009-11-09 04:18:43 UTC (rev 1511) @@ -40,6 +40,20 @@ size_t n_; }; + // TODO: try just specifying a single templated function + /** + * Swap two arrays. + */ + template<typename T> + void + inline swap(sized_array<T> &a, sized_array<T> &b) + { + std::swap(a.p_, b.p_); + swap(a.n_, b.n_); + } + +#ifdef COMMONS_CXX0X + // TODO: rename /** * A thin wrapper around arrays. Like a fixed-size vector. Unlike array @@ -92,19 +106,7 @@ swap(a.n_, b.n_); } - // TODO: try just specifying a single templated function /** - * Swap two arrays. - */ - template<typename T> - void - inline swap(sized_array<T> &a, sized_array<T> &b) - { - std::swap(a.p_, b.p_); - swap(a.n_, b.n_); - } - - /** * Conditionally-scoped, move-able, release-able, un-sized array. */ template<typename T> @@ -128,6 +130,8 @@ bool scoped_; }; +#endif + /** * Checks if a pointer is in an array. */ Added: cpp-commons/trunk/src/commons/cxx0x.h =================================================================== --- cpp-commons/trunk/src/commons/cxx0x.h (rev 0) +++ cpp-commons/trunk/src/commons/cxx0x.h 2009-11-09 04:18:43 UTC (rev 1511) @@ -0,0 +1,8 @@ +#ifndef COMMONS_CXX0X_H +#define COMMONS_CXX0X_H + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#define COMMONS_CXX0X +#endif + +#endif Modified: cpp-commons/trunk/src/commons/files.h =================================================================== --- cpp-commons/trunk/src/commons/files.h 2009-11-08 18:27:35 UTC (rev 1510) +++ cpp-commons/trunk/src/commons/files.h 2009-11-09 04:18:43 UTC (rev 1511) @@ -1,6 +1,7 @@ #ifndef COMMONS_FILES_H #define COMMONS_FILES_H +#include <cstdio> #include <exception> #include <fstream> #include <iostream> @@ -9,7 +10,9 @@ #include <sys/types.h> #include <sys/stat.h> +#ifndef WIN32 #include <unistd.h> +#endif #include <fcntl.h> #include <commons/array.h> @@ -21,10 +24,10 @@ using namespace std; - class file_not_found_exception : std::exception { + class file_open_exception : std::exception { public: - file_not_found_exception(const string & name) : name(name) {} - virtual ~file_not_found_exception() throw() {} + file_open_exception(const string & name) : name(name) {} + virtual ~file_open_exception() throw() {} private: const string name; }; @@ -52,25 +55,37 @@ /** * Read in a whole file as a string. */ - UNUSED static void read_file_as_string ( const string & name, string & out ) { - ifstream in ( name.c_str() ); - if (in.fail()) throw file_not_found_exception( name ); - out = string ( istreambuf_iterator<char> ( in ), istreambuf_iterator<char>() ); + inline void read_file_as_string(const char * name, string & out ) { + ifstream in ( name ); + if (in.fail()) throw file_open_exception( name ); + out.assign(istreambuf_iterator<char>(in), istreambuf_iterator<char>()); } /** + * Read in a whole file as a string. + */ + inline string read_file_as_string ( const char * name ) + { + string s; + read_file_as_string(name, s); + return s; + } + + /** * Read in a whole file as a vector of chars. */ - UNUSED static void read_file_as_vector ( const string & name, vector<char> & out ) { - ifstream in ( name.c_str() ); - if ( in.fail() ) throw file_not_found_exception( name ); - out = vector<char> ( istreambuf_iterator<char> ( in ), istreambuf_iterator<char>() ); + inline void read_file_as_vector(const char * name, vector<char> & out) { + ifstream in ( name ); + if ( in.fail() ) throw file_open_exception( name ); + out.assign(istreambuf_iterator<char>(in), istreambuf_iterator<char>()); } +#ifndef WIN32 + /** * Read in a whole file as an array. */ - UNUSED static array<char> read_file_as_array(const char *path) + inline array<char> read_file_as_array(const char *path) { closingfd fd(checknnegerr(open(path, O_RDONLY))); array<char> buf(file_size(fd)); @@ -78,7 +93,7 @@ return buf; } - UNUSED static void write_file(int fd, const void *buf, size_t len) + inline void write_file(int fd, const void *buf, size_t len) { checkeqnneg(write(fd, buf, len), ssize_t(len)); } @@ -86,7 +101,7 @@ /** * Write a whole array to disk. */ - UNUSED static void write_file(const char *path, const void *buf, size_t len) + inline void write_file(const char *path, const void *buf, size_t len) { closingfd fd(checknnegerr(creat(path, 0644))); write_file(fd, buf, len); @@ -95,7 +110,7 @@ /** * Write a whole array to disk. */ - UNUSED static void write_file(const char *path, const array<char> &buf) + inline void write_file(const char *path, const array<char> &buf) { write_file(path, buf, buf.size()); } @@ -106,7 +121,7 @@ * TODO this probably isn't very safe, since we're demoting an off_t to a * size_t. Is there a healthier approach? */ - UNUSED static char * + inline char * load_file(const char *path, size_t & len, unsigned int ncpus) { struct stat sb; @@ -148,6 +163,8 @@ errno = 0; } +#endif + } #endif Added: cpp-commons/trunk/src/commons/functions.h =================================================================== --- cpp-commons/trunk/src/commons/functions.h (rev 0) +++ cpp-commons/trunk/src/commons/functions.h 2009-11-09 04:18:43 UTC (rev 1511) @@ -0,0 +1,23 @@ +#ifndef COMMONS_FUNCTIONS_H +#define COMMONS_FUNCTIONS_H + +#include <boost/bind.hpp> +#include <boost/function.hpp> + +namespace commons +{ + + using boost::bind; + using boost::function; + + template<typename C, typename A, typename B> + function<C(A)> compose(function<C(A)> f, function<A(B)> g) + { return bind(f, bind(g, _1)); } + + template<typename B, typename A> + function<B> operator*(function<B> f, function<A> g) + { return compose(f, g); } + +} + +#endif Added: cpp-commons/trunk/src/commons/resolver.h =================================================================== --- cpp-commons/trunk/src/commons/resolver.h (rev 0) +++ cpp-commons/trunk/src/commons/resolver.h 2009-11-09 04:18:43 UTC (rev 1511) @@ -0,0 +1,39 @@ +#ifndef RESOLVER_H +#define RESOLVER_H + +#include <commons/sockets.h> +#include <commons/strings.h> +#include <Poco/Net/DNS.h> + +/** + * Convenience functions for resolving hostnames. + */ + +namespace commons +{ + + using namespace Poco::Net; + + /** Get the hostname's IPv4 address as an int in network byte order. */ + inline uint32_t name2nl(DNS &dns, const string &name) { + return ipaddr2nl(*reinterpret_cast<const in_addr*>(dns.resolveOne(name).addr())); + } + + /** Get the hostname's IPv4 address as an int in network byte order. */ + inline uint32_t name2nl(DNS &dns, const wstring &name) { + return name2nl(dns, to_string(name)); + } + + /** Get the hostname's IPv4 address as an int in host byte order. */ + inline uint32_t name2hl(DNS &dns, const string &name) { + return ipaddr2hl(*reinterpret_cast<const in_addr*>(dns.resolveOne(name).addr())); + } + + /** Get the hostname's IPv4 address as an int in host byte order. */ + inline uint32_t name2hl(DNS &dns, const wstring &name) { + return name2hl(dns, to_string(name)); + } + +} + +#endif Modified: cpp-commons/trunk/src/commons/sockets.h =================================================================== --- cpp-commons/trunk/src/commons/sockets.h 2009-11-08 18:27:35 UTC (rev 1510) +++ cpp-commons/trunk/src/commons/sockets.h 2009-11-09 04:18:43 UTC (rev 1511) @@ -3,6 +3,7 @@ #ifdef WIN32 #include <winsock2.h> +#include <ws2tcpip.h> #else #include <arpa/inet.h> #include <netdb.h> @@ -24,7 +25,7 @@ #ifdef WIN32 typedef SOCKET socket_t; - int inet_aton(const char *cp, struct in_addr *inp) { + inline int inet_aton(const char *cp, struct in_addr *inp) { uint32_t a = inet_addr(cp); if (a == INADDR_NONE) return 0; inp->S_un.S_addr = a; @@ -148,7 +149,7 @@ return a; } - void close_socket(socket_t s) { + inline void close_socket(socket_t s) { #ifdef WIN32 closesocket(s); #else @@ -219,35 +220,55 @@ return c.release(); } +#if 0 #if defined(WIN32) && defined(UNICODE) #define getnameinfo GetNameInfoW #define getaddrinfo GetAddrInfoW #define addrinfo ADDRINFOW #define freeaddrinfo FreeAddrInfoW #endif +#endif +#if 0 /** - * T is a string or wstring. + * Resolve a sockaddr's IP address to its hostname. */ - template<typename T> - sockaddr_in - addr2name(const sockaddr_in sa) + inline string + sockaddr2hostname(const sockaddr_in &sa) { - enum { sz = 1024 }; - wchar_t buf[sz]; + char hostbuf[NI_MAXHOST]; check0x(getnameinfo(reinterpret_cast<const sockaddr*>(&sa), sizeof sa, - buf, sz, // output hostname + hostbuf, NI_MAXHOST, // output hostname nullptr, 0, // service 0)); // flags - return sa; + return string(buf); } /** + * Resolve an IP address to its hostname. + */ + inline string + ipaddr2hostname(const in_addr &ip) + { + sockaddr_in sa = { AF_INET, 0, ip }; + return sockaddr2hostname(sa); + } + + /** + * Convert an IP addr to a string. + */ + inline string + ipaddr2str(const in_addr &ip) + { + inet_ntop(); + } + + /** * Get IPv4 address for hostname. T is a string or wstring. */ template<typename T> in_addr - name2addr(const T *name) + name2ipaddr(const T *name) { addrinfo *ai, hints = {0}; in_addr addr; @@ -263,7 +284,16 @@ freeaddrinfo(ai); return addr; } +#endif + /** Get the IPv4 address as an int in network byte order. */ + inline uint32_t ipaddr2nl(const in_addr &a) + { return IFWIN32(a.S_un.S_addr, a.s_addr); } + + /** Get the IPv4 address as an int in host byte order. */ + inline uint32_t ipaddr2hl(const in_addr &a) + { return ntohl(ipaddr2nl(a)); } + } #endif Modified: cpp-commons/trunk/src/commons/streams.h =================================================================== --- cpp-commons/trunk/src/commons/streams.h 2009-11-08 18:27:35 UTC (rev 1510) +++ cpp-commons/trunk/src/commons/streams.h 2009-11-09 04:18:43 UTC (rev 1511) @@ -1,24 +1,76 @@ #ifndef COMMONS_STREAMS_H #define COMMONS_STREAMS_H +#include <iomanip> +#include <limits> #include <ostream> +#include <string> #include <vector> -namespace commons { +#include <boost/foreach.hpp> +#include <boost/io/ios_state.hpp> +#include <commons/strings.h> + +namespace commons { namespace formatters { + using namespace std; + using boost::io::ios_flags_saver; - // Pretty-prints a vector of ostreamables. - template <typename T> - ostream& operator<<(ostream& out, const vector<T> &v) { - out << "["; - if (!v.empty()) { - for (typename vector<T>::size_type i = 0; i < v.size() - 1; i++) - out << v[i] << ", "; - out << v.back(); + /** + * Pretty-prints a vector of ostreamables. + */ + template<typename T> + ostream &operator<<(ostream &o, const vector<T> &v) + { + bool first = true; + o << "["; + BOOST_FOREACH (const T &x, v) { + o << (first ? "" : ", ") << x; + first = false; + } + return o << "]"; + } + + /** + * Allow wstrings to be printed to ostreams. + */ + inline ostream &operator<<(ostream &o, const wstring &s) + { return o << to_string(s); } + + /** + * Allow strings to be printed to wostreams. + */ + inline wostream &operator<<(wostream &o, const string &s) + { return o << to_wstring(s); } + + /** + * Wrapper around integral types that enables pretty printing as hex numbers. + */ + template<typename T> + class hexfmt_t + { + public: + hexfmt_t(T x) : x_(x) {} + friend wostream &operator<<(wostream &o, hexfmt_t x) { + ios_flags_saver s(o); + return o << setfill('0') << setw(2 * sizeof(T)) << hex << x.x_; } - return out << "]"; + friend ostream &operator<<(ostream &o, hexfmt_t x) { + ios_flags_saver s(o); + return o << setfill('0') << setw(2 * sizeof(T)) << hex << x.x_; + } + private: + T x_; + }; + + /** + * Convenience constructor wrapper for hexfmt_t. + */ + template<typename T> hexfmt_t<T> hexfmt(T x) { + return hexfmt_t<T>(x); } -} +} } + #endif Modified: cpp-commons/trunk/src/commons/strings.h =================================================================== --- cpp-commons/trunk/src/commons/strings.h 2009-11-08 18:27:35 UTC (rev 1510) +++ cpp-commons/trunk/src/commons/strings.h 2009-11-09 04:18:43 UTC (rev 1511) @@ -3,9 +3,16 @@ #ifndef COMMONS_STRINGS_H #define COMMONS_STRINGS_H +#include <Poco/UnicodeConverter.h> + +#ifndef __cplusplus #include <strings.h> +#else +#include <cstring> +#endif #include <commons/check.h> +#include <commons/nullptr.h> namespace commons { @@ -42,44 +49,10 @@ struct eqstr { bool operator()(const char* s1, const char* s2) const - { - return strcmp(s1, s2) == 0; - } + { return strcmp(s1, s2) == 0; } }; /** - * Look for a substring, but without null-termination conventions. - * - * TODO: remove or fix - */ - inline char * - unsafe_strstr(char *p, const char *, const char *lim) - { - if (lim == 0) { - while (true) { - for (; !(*p == '\0' && *(p+1) == '\0'); p++) {} - return p; - } - } else { - check(p < lim); - while (true) { - for (; !(*p == '\0' && *(p+1) == '\0') && p < lim; p++) {} - if (p == lim) return NULL; - return p; - } - } - } - - /** - * Look for a substring, but without null-termination conventions. - */ - inline const char* - unsafe_strstr(const char *p, const char *q, const char *lim) - { - return unsafe_strstr(const_cast<char*>(p), q, lim); - } - - /** * "Touch" the entire memory region. Useful for ensuring that some piece of * memory is "warmed up." Visits each character. Note that this might be * optimized out if the caller doesn't meaningfully use the (mostly @@ -133,6 +106,115 @@ // return NULL; // } + /** + * Convert UTF-16 to UTF-8. + */ + inline string to_utf8(const wstring &w) { + string s; + Poco::UnicodeConverter::toUTF8(w, s); + return s; + } + + /** + * Convert UTF-8 to UTF-16. + */ + inline wstring to_utf16(const string &s) { + wstring w; + Poco::UnicodeConverter::toUTF16(s, w); + return w; + } + + /** + * Throw-away stream for easily building strings. + * + * \code + * throw msg_exception(tmpstream() << "error " << errcode() << endl); + * \endcode + */ + class tmpstream : public ostringstream { + public: + operator string() const { return str(); } + operator const char *() const { return str().c_str(); } + + template<typename T> + tmpstream &operator <<(const T &x) { + *static_cast<ostringstream*>(this) << x; + return *this; + } + }; + } +#ifdef WIN32 + +#include <windows.h> +#include <string> + +namespace commons { namespace win { + + using std::string; + using std::wstring; + + // TODO return unique_ptr + + /** + * Transcode to system default ANSI code page using WideCharToMultiByte. + */ + inline char* + to_chars(const wchar_t *w) + { + char *s; + int wlen = ::wcslen(w); + int slen = ::WideCharToMultiByte(CP_ACP, 0, w, wlen, 0, 0, nullptr, nullptr); + if (slen > 0) { + s = new char[slen + 1]; + ::WideCharToMultiByte(CP_ACP, 0, w, wlen, s, slen, nullptr, nullptr); + s[slen] = 0; + } + + return s; + } + + /** + * Transcode to system default ANSI code page using WideCharToMultiByte. + */ + inline string + to_string(const wstring &w) + { + char *p = to_chars(w.c_str()); + string s(p); + delete[] p; + return s; + } + + + /** + * Transcode from system default ANSI code page using MultiByteToWideChar. + */ + inline wchar_t * + to_wchars(const char *s) + { + int len = ::strlen(s); + wchar_t *w = new wchar_t[len + 1]; + ::MultiByteToWideChar(CP_ACP, 0, s, len, w, len + 1); + return w; + } + + + /** + * Transcode from system default ANSI code page using MultiByteToWideChar. + */ + inline wstring + to_wstring(const string &s) + { + wchar_t *p = to_wchars(s.c_str()); + wstring w(p); + delete[] p; + return w; + } + +} } + #endif + +#endif Modified: cpp-commons/trunk/src/commons/unique_ptr.h =================================================================== --- cpp-commons/trunk/src/commons/unique_ptr.h 2009-11-08 18:27:35 UTC (rev 1510) +++ cpp-commons/trunk/src/commons/unique_ptr.h 2009-11-09 04:18:43 UTC (rev 1511) @@ -35,6 +35,10 @@ #ifndef _UNIQUE_PTR_H #define _UNIQUE_PTR_H 1 +#include <commons/cxx0x.h> + +#ifdef COMMONS_CXX0X + #ifndef __GXX_EXPERIMENTAL_CXX0X__ # include <c++0x_warning.h> #endif @@ -456,4 +460,6 @@ _GLIBCXX_END_NAMESPACE +#endif // COMMONS_CXX0X + #endif /* _UNIQUE_PTR_H */ Property changes on: cpp-commons/trunk/src/commons/win.h ___________________________________________________________________ Deleted: svn:executable - * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |