assorted-commits Mailing List for Assorted projects (Page 28)
Brought to you by:
yangzhang
You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(9) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(86) |
Feb
(265) |
Mar
(96) |
Apr
(47) |
May
(136) |
Jun
(28) |
Jul
(57) |
Aug
(42) |
Sep
(20) |
Oct
(67) |
Nov
(37) |
Dec
(34) |
2009 |
Jan
(39) |
Feb
(85) |
Mar
(96) |
Apr
(24) |
May
(82) |
Jun
(13) |
Jul
(10) |
Aug
(8) |
Sep
(2) |
Oct
(20) |
Nov
(31) |
Dec
(17) |
2010 |
Jan
(16) |
Feb
(11) |
Mar
(17) |
Apr
(53) |
May
(31) |
Jun
(13) |
Jul
(3) |
Aug
(6) |
Sep
(11) |
Oct
(4) |
Nov
(17) |
Dec
(17) |
2011 |
Jan
(3) |
Feb
(19) |
Mar
(5) |
Apr
(17) |
May
(3) |
Jun
(4) |
Jul
(14) |
Aug
(3) |
Sep
(2) |
Oct
(1) |
Nov
(3) |
Dec
(2) |
2012 |
Jan
(3) |
Feb
(7) |
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
(4) |
Aug
(5) |
Sep
(2) |
Oct
(3) |
Nov
|
Dec
|
2013 |
Jan
|
Feb
|
Mar
(9) |
Apr
(5) |
May
|
Jun
(2) |
Jul
(1) |
Aug
(10) |
Sep
(1) |
Oct
(2) |
Nov
|
Dec
|
2014 |
Jan
(1) |
Feb
(3) |
Mar
(3) |
Apr
(1) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
2016 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2017 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(5) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
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-23 04:49:57
|
Revision: 1226 http://assorted.svn.sourceforge.net/assorted/?rev=1226&view=rev Author: yangzhang Date: 2009-02-23 04:49:55 +0000 (Mon, 23 Feb 2009) Log Message: ----------- - removed USE_PB/PB - simplified setup-ydb - further tweaked warnings - added TODO Modified Paths: -------------- ydb/trunk/README ydb/trunk/src/Makefile ydb/trunk/tools/test.bash Modified: ydb/trunk/README =================================================================== --- ydb/trunk/README 2009-02-23 04:37:33 UTC (rev 1225) +++ ydb/trunk/README 2009-02-23 04:49:55 UTC (rev 1226) @@ -410,6 +410,8 @@ - TODO async (threaded) wal - TODO 0-node 0-copy (don't need to use threads, just process each batch immed) +- TODO see how p2 compares with ydb + - DONE google dense hash map - big improvement, again not in the direction we'd like - 0: 550K Modified: ydb/trunk/src/Makefile =================================================================== --- ydb/trunk/src/Makefile 2009-02-23 04:37:33 UTC (rev 1225) +++ ydb/trunk/src/Makefile 2009-02-23 04:49:55 UTC (rev 1226) @@ -33,9 +33,6 @@ else OPT := -g3 endif -ifneq ($(PB),) - PB := -DUSE_PB -endif # CXX := $(WTF) ag++ -k --Xcompiler # $(CXX) CXX := $(WTF) $(CXX) LDFLAGS := -pthread $(GPROF) @@ -55,7 +52,6 @@ -Winit-self \ -Wswitch-enum \ -Wunused \ - -Wstrict-overflow \ -Wfloat-equal \ -Wundef \ -Wunsafe-loop-optimizations \ @@ -71,22 +67,23 @@ -Wmissing-format-attribute \ -Wpacked \ -Wredundant-decls \ - -Winline \ -Winvalid-pch \ -Wlong-long \ -Wvolatile-register-var \ -std=gnu++0x \ - $(PB) \ $(CXXFLAGS) - # -Wmissing-noreturn \ - # -Weffc++ \ - # -pedantic \ - # -Wshadow \ - # -Wswitch-default \ - # -Wpadded \ - # -Wunreachable-code \ - # -Wstack-protector \ + # \ + -Wmissing-noreturn \ + -Weffc++ \ + -pedantic \ + -Wshadow \ + -Wswitch-default \ + -Wpadded \ + -Wunreachable-code \ + -Wstack-protector \ + -Wstrict-overflow \ + -Winline \ PBCXXFLAGS := $(OPT) -Wall -Werror $(GPROF) Modified: ydb/trunk/tools/test.bash =================================================================== --- ydb/trunk/tools/test.bash 2009-02-23 04:37:33 UTC (rev 1225) +++ ydb/trunk/tools/test.bash 2009-02-23 04:49:55 UTC (rev 1226) @@ -181,26 +181,15 @@ toast --quiet arm 'http://google-sparsehash.googlecode.com/files/sparsehash-1.4.tar.gz' } -node-setup-ydb-1() { +node-setup-ydb() { check-remote - if [[ ! -L ~/ydb ]] - then ln -s ~/work/assorted/ydb/trunk ~/ydb - fi - if [[ ! -L ~/ccom ]] - then ln -s ~/work/assorted/cpp-commons/trunk ~/ccom - fi -} - -node-setup-ydb-2() { - check-remote cd ~/ccom/ ./setup.bash -d -p ~/.local/pkg/cpp-commons refresh-local cd ~/ydb/src make clean - # PB=1 PPROF=1 OPT=1 make WTF= PPROF=1 OPT=1 make WTF= - # PPROF=1 OPT=1 make WTF= p2 + PPROF=1 OPT=1 make WTF= p2 } init-setup() { @@ -240,13 +229,13 @@ } setup-ydb() { - parremote node-setup-ydb-1 - rm -rf /tmp/{ydb,ccom}-src/ - svn export ~/ydb/src /tmp/ydb-src/ - svn export ~/ccom/src /tmp/ccom-src/ - parscp -r /tmp/ydb-src/* ^:ydb/src/ - parscp -r /tmp/ccom-src/* ^:ccom/src/ - parremote node-setup-ydb-2 + parssh mkdir -p ydb/ ccom/ + rm -rf /tmp/{ydb,ccom}-export/ + svn export ~/work/assorted/ydb/trunk/ /tmp/ydb-export/ + svn export ~/work/assorted/cpp-commons/trunk/ /tmp/ccom-export/ + parscp -r /tmp/ydb-export/* ^:ydb/ + parscp -r /tmp/ccom-export/* ^:ccom/ + parremote node-setup-ydb } setup-stperf() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-23 04:37:38
|
Revision: 1225 http://assorted.svn.sourceforge.net/assorted/?rev=1225&view=rev Author: yangzhang Date: 2009-02-23 04:37:33 +0000 (Mon, 23 Feb 2009) Log Message: ----------- dos2unix Modified Paths: -------------- clamp/trunk/doc/index.html clamp/trunk/doc/readme.txt clamp/trunk/src/CodeGen.cc clamp/trunk/src/CodeGen.hh clamp/trunk/src/Makefile clamp/trunk/src/clamp.y clamp/trunk/src/clamp_support.cc clamp/trunk/src/clamp_support.hh clamp/trunk/src/clamplex.h clamp/trunk/src/clamplex.lex clamp/trunk/src/curry.clamp clamp/trunk/src/eg.clamp clamp/trunk/src/home_page_examples.clamp clamp/trunk/src/test.clamp Modified: clamp/trunk/doc/index.html =================================================================== --- clamp/trunk/doc/index.html 2009-02-23 02:47:54 UTC (rev 1224) +++ clamp/trunk/doc/index.html 2009-02-23 04:37:33 UTC (rev 1225) @@ -1,489 +1,489 @@ -<html> -<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> -<meta name="Author" content="Raoul Gough"> - -<title>Project page for clamp - the C++ lambda preprocessor</title> - -<!-- $Id: index.html,v 1.14 2003/09/30 22:04:44 Raoul Exp $ --> - -<STYLE> -<!-- - -font.terminal { - font-family: arial, sans-serif; - font-weight: normal; - text-align: left; - vertical-align: top; -} - -font.nonterminal { - font-family: arial, sans-serif; - font-weight: normal; - font-style: italic; - text-align: left; - vertical-align: top; -} - -font.code { - font-family: courier, monotype; - font-weight: normal; - text-align: left; - vertical-align: middle; -} - ---> -</STYLE> - - -<body> - -<table width="100%"> - <tr> - <td colspan=2> -<a name="intro"> -<h1> -C++ lambda preprocessor -</h1> - </td> - </tr> - <tr> - <td bgcolor="lightblue" valign="top"> - <font size="-1"> - -<b> -Directory -</b> -<br> -<a href="#why">Why clamp?</a><br> -<a href="#detail">What it does</a><br> -<a href="#internal">How it works</a><br> -<a href="#grammar">Grammar</a><br> -<a href="#porting">Portability</a><br> -<a href="#contact">Contact info</a><br> -<a href="clamp_053_src.tar.gz">Source download</a> -<a href="clamp_053_exe.tar.gz">Windows executable</a> -<a href="../index.html">Author's home page</a> - - </font> - </td> - <td> - -The C++ lambda preprocessor (clamp) converts C++ code containing -lambda expressions into ordinary C++ code. Here's a simple example: - -<p> -<font class="code"> -vector<int> v;<br> -// ... <br> -std::for_each (v.begin(), v.end()<br> - - - , <b>lambda</b> (int &p) {<br> - - - if (p == 5) p = 0;<br> - - - } ); -</font> - -<p> -This example uses the standard algorithm <font -class="code">for_each</font> to apply an anonymous function to each -element of a vector. The anonymous function accepts an integer -parameter by reference, and resets the value to zero if it is -currently five (a simple, but not very useful example). The -preprocessor replaces the entire lambda expression in its output, so -that the C++ compiler ends up seeing something like the following: - -<p> -<font class="code"> -std::for_each (v.begin(), v.end()<br> - - , lambda_generator_1<void, int &>::generate () ); -</font> - -<p> -The exact nature of the template <font -class="code">lambda_generator_1</font> is beyond the scope of this -introduction, except to say that its <font -class="code">generate()</font> member function returns a function -object by value. The function object has, in this case, a member -function <font class="code">void operator()(int &)</font> -which <font class="code">for_each</font> applies to each element of -the vector. Some people would probably prefer to use the standard -<font class="code">transform</font> algorithm for this example, as in: - -<p> -<font class="code"> -std::transform (v.begin(), v.end(), v.begin()<br> - - - , lambda int (int p) {<br> - - - return (p == 5) ? 0 : p;<br> - - - } ); -</font> - -<p> -This example shows an anonymous function that returns a value, in this -case int. Rather than hard-wiring a value into the function body, it -is also possible to include contextual information in the function -object. For instance: - -<p> -<font class="code"> -void reset (std::vector<int> &v, int val) {<br> - -std::transform (v.begin(), v.end(), v.begin()<br> - - - , lambda int (int p) {<br> - - - return (p == <b>__ctx</b>(val)) ? 0 : p;<br> - - - } );<br> -} -</font> - -<p> -The <font class="code">__ctx</font> expression is an example of -context information bound by value. The clamp preprocessor also -supports reference semantics for contextual information via <font -class="code">__ref</font> expressions. For example: - -<p> -<font class="code"> -int sum = 0;<br> -std::for_each (v.begin(), v.end()<br> - - -, lambda (int p) { <b>__ref</b>(sum) += p; });<br> -</font> - -<p> -This, of course, calculates the sum of elements in the vector. - -<p> -Getting into some more complicated examples, it is possible to name -the type of the function object generated by a lambda expression by -simply omitting the function body. You have to do this, for instance, -if you want to use an anonymous function generated by a lambda -expression as a function parameter or return value. For example, the -type of the expression from the previous example: - -<p> -<font class="code"> -lambda (int p) { __ref(sum) += p; } -</font> - -<p> -can be referred to in the code as "<font class="code">lambda (int &) -(int)</font>". The first pair of brackets contains the context binding -(or closure) parameters, and the second pair contains the function -parameters. The closure parameter list is optional for context-less -functions, as is the return type for functions returning <font -class="code">void</font>, such as this one. Putting all of that -together, here's a templated function that returns a function object: - -<p> -<font class="code"> -template<typename T><br> -lambda bool (T) (const T &)<br> -match (const T &target) {<br> - return lambda bool (const T &candidate) {<br> - return candidate == __ctx(target);<br> - };<br> -}<br> -<p> -// Use a generated comparison object<br> -std::vector<int>::iterator<br> - i = find_if (v.begin(), v.end(), match (7));<br> -</font> -<p> -This <font class="code">find_if</font> example returns an iterator to -the first 7 in the vector (or <font class="code">v.end()</font>, if -none) using an instantiation of the <font class="code">match</font> -template with an <font class="code">int</font> parameter. For a vector -of strings, you could do the following: - -<p> -<font class="code"> -std::vector<std::string>::iterator<br> - i = find_if (v.begin(), v.end()<br> - - -, match (std::string("hello")));<br> -</font> - -<h2> -<a name="why"> -Why a preprocessor? -</h2> - -I wrote the preprocessor just for fun. There doesn't seem to be any -way to achieve real lambda expressions in pure C++, since it won't let -you insert a function definition in the middle of an expression. The -limits of what pure C++ allows are pretty well exhausted by the <a -href="http://www.boost.org/libs/lambda/doc/">boost lambda library</a>. - -<p> -Lambda expressions simplify some coding tasks, so it would be nice to -have them in C++. In the time it takes you to extract that one-liner -into a named function, I bet you could write <i>two</i> lambda -expressions for sure. Not to mention cases which require a named class -that contains context information. - -<h2> -<a name="detail"> -What it does -</h2> -<p> - -clamp scans its input for lambda expressions, passing any plain C++ -through unchanged. When it encounters a lambda expression, it extracts -the function body into a separate file. It also generates a class -template with a suitable <font class="code">operator()</font> and -(where necessary) member variables to store any context binding. This -class template also goes into a separate file. The whole lambda -expression is then replaced in the output by a single constructor -call, which creates an object of the templated class. - -<p> -The first line of the output is always a #include directive, which -drags in the generated templates and (indirectly) the function bodies. -The generated templates do not refer explicitly to any types used in -the original lambda expressions, which is how it can be included -before any user code. The actual types are only bound at the point of -use. Because of this, the clamp parser doesn't have to know what scope -a lambda expression appears in, or where the required types are -defined. This also makes including lambda expressions in templated -code a breeze, since the type binding is done within the template -scope where the expression was originally used. - -<h2> -<a name="internal"> -How it works -</h2> -<p> - -<p> -The clamp preprocessor consists of a lexical analyser (lexer) written -in flex, a parser written in bison and a code generator in plain C++. - -<p> -The clamp parser mostly tries to ignore everything in the input file, -letting the lexer copy input to output. When the lexer encounters the -<font class="code">lambda</font> keyword, it enters a different mode -("start condition" in flex terminology) in which is behaves like a -normal lexer and supplies tokens to the parser. The parser does some -messy stuff redirecting output and resetting the lexer mode as -necessary. - -<p> -Note: clamp is actually pretty dumb. It performs purely syntactic -transformations on the input, without really understanding scope, -types or variables. This will no doubt result in some incomprehensible -errors from the C++ compiler if something goes wrong. This is also the -reason that clamp requires the <font class="code">__ctx</font> and -<font class="code">__ref</font> keywords, since it wouldn't otherwise -be able to tell that an expression relies on surrounding context -information. - -<h2> -<a name="grammar"> -Grammar -</h2> -<p> -clamp introduces three keywords: <font -class="code">lambda, __ctx</font> and <font class="code">__ref</font>. -The parser recognises more or less the following grammar: - -<p> -<font size="-1"> - -<font class="nonterminal"> -lambda-expression: -<br> -lambda-decl -lambda-body<sub>opt</sub> -</font> - -<p> -<font class="nonterminal"> -lambda-decl: -<br> -</font> -<font class="terminal"> -lambda -</font> -<font class="nonterminal"> -return-type<sub>opt</sub> -param-list<sub>opt</sub> -param-list -</font> - -<p> -<font class="nonterminal"> -return-type: -<br> -type-id -</font> - -<p> -<font class="nonterminal"> -param-list: -<br> -</font> -<font class="terminal"> -( ) -</font> -<font class="nonterminal"> -<br> -</font> -<font class="terminal"> -( -</font> -<font class="nonterminal"> -parameter -</font> -<font class="terminal"> -) -</font> -<font class="nonterminal"> -<br> -</font> -<font class="terminal"> -( -</font> -<font class="nonterminal"> -parameter -</font> -<font class="terminal"> -, -</font> -<font class="nonterminal"> -... -</font> -<font class="terminal"> -) -</font> - -<p> -<font class="nonterminal"> -parameter: -<br> -type-id -identifier<sub>opt</sub> -initialiser<sub>opt</sub> -</font> - -<p> -<font class="nonterminal"> -initialiser: -<br> - - -</font> -<font class="terminal"> -= -</font> -<font class="nonterminal"> -expression -</font> - -<p> -<font class="nonterminal"> -lambda-body: -<br> - - -</font> -<font class="terminal"> -{ -</font> -<font class="nonterminal"> -statement<sub>opt</sub> ... -</font> -<font class="terminal"> -} -</font> - -<p> - -</font> - -where <font class="nonterminal">statement</font> represents any valid C++ -statement, possibly making use of the following extended expressions: - -<font size="-1"> -<p> -<font class="nonterminal"> -extended-expression: -<br> -lambda-expression -<br> -</font> -<font class="terminal"> -__ctx ( -</font> -<font class="nonterminal"> -expression -</font> -<font class="terminal"> -) -</font> -<font class="nonterminal"> -<br> -</font> -<font class="terminal"> -__ref ( -</font> -<font class="nonterminal"> -expression -</font> -<font class="terminal"> -) -</font> - -</font> - -<h2> -<a name="porting"> -Portability -</h2> -I wrote clamp using the following tools: g++ 2.95.3-5 with -boost 1.25.1, flex 2.5.4, bision 1.28 and -gnu make 3.79.1, all under Cygwin on Windows 2000. The -preprocessor builds successfully with g++ 3.1, but the code that it -generates causes an internal compiler error when taking the address of -a member function. This is probably fixed in later versions of g++. - -<p> -The preprocessor itself <i>might</i> build with yacc and/or -traditional Unix make (maybe) with any reasonable C++ compiler. The -lexer probably won't compile with plain lex, because (according to the -flex manual), lex doesn't support exclusive start conditions. - -<a name="contact"> -<h2> -Contact information -</h2> -This page and clamp itself are Copyright (C) 2002, 2003 by Raoul Gough -and may be used and distributed free of charge. Please send any -clamp-related comments to <a -href="mailto:Rao...@ya...">Rao...@ya...</a>. It -might be a good idea to include the word "clamp" in the subject line, -because that email address attracts a bit of spam. - - </td> - </tr> -</table> - -</body> +<html> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<meta name="Author" content="Raoul Gough"> + +<title>Project page for clamp - the C++ lambda preprocessor</title> + +<!-- $Id: index.html,v 1.14 2003/09/30 22:04:44 Raoul Exp $ --> + +<STYLE> +<!-- + +font.terminal { + font-family: arial, sans-serif; + font-weight: normal; + text-align: left; + vertical-align: top; +} + +font.nonterminal { + font-family: arial, sans-serif; + font-weight: normal; + font-style: italic; + text-align: left; + vertical-align: top; +} + +font.code { + font-family: courier, monotype; + font-weight: normal; + text-align: left; + vertical-align: middle; +} + +--> +</STYLE> + + +<body> + +<table width="100%"> + <tr> + <td colspan=2> +<a name="intro"> +<h1> +C++ lambda preprocessor +</h1> + </td> + </tr> + <tr> + <td bgcolor="lightblue" valign="top"> + <font size="-1"> + +<b> +Directory +</b> +<br> +<a href="#why">Why clamp?</a><br> +<a href="#detail">What it does</a><br> +<a href="#internal">How it works</a><br> +<a href="#grammar">Grammar</a><br> +<a href="#porting">Portability</a><br> +<a href="#contact">Contact info</a><br> +<a href="clamp_053_src.tar.gz">Source download</a> +<a href="clamp_053_exe.tar.gz">Windows executable</a> +<a href="../index.html">Author's home page</a> + + </font> + </td> + <td> + +The C++ lambda preprocessor (clamp) converts C++ code containing +lambda expressions into ordinary C++ code. Here's a simple example: + +<p> +<font class="code"> +vector<int> v;<br> +// ... <br> +std::for_each (v.begin(), v.end()<br> + + + , <b>lambda</b> (int &p) {<br> + + + if (p == 5) p = 0;<br> + + + } ); +</font> + +<p> +This example uses the standard algorithm <font +class="code">for_each</font> to apply an anonymous function to each +element of a vector. The anonymous function accepts an integer +parameter by reference, and resets the value to zero if it is +currently five (a simple, but not very useful example). The +preprocessor replaces the entire lambda expression in its output, so +that the C++ compiler ends up seeing something like the following: + +<p> +<font class="code"> +std::for_each (v.begin(), v.end()<br> + + , lambda_generator_1<void, int &>::generate () ); +</font> + +<p> +The exact nature of the template <font +class="code">lambda_generator_1</font> is beyond the scope of this +introduction, except to say that its <font +class="code">generate()</font> member function returns a function +object by value. The function object has, in this case, a member +function <font class="code">void operator()(int &)</font> +which <font class="code">for_each</font> applies to each element of +the vector. Some people would probably prefer to use the standard +<font class="code">transform</font> algorithm for this example, as in: + +<p> +<font class="code"> +std::transform (v.begin(), v.end(), v.begin()<br> + + + , lambda int (int p) {<br> + + + return (p == 5) ? 0 : p;<br> + + + } ); +</font> + +<p> +This example shows an anonymous function that returns a value, in this +case int. Rather than hard-wiring a value into the function body, it +is also possible to include contextual information in the function +object. For instance: + +<p> +<font class="code"> +void reset (std::vector<int> &v, int val) {<br> + +std::transform (v.begin(), v.end(), v.begin()<br> + + + , lambda int (int p) {<br> + + + return (p == <b>__ctx</b>(val)) ? 0 : p;<br> + + + } );<br> +} +</font> + +<p> +The <font class="code">__ctx</font> expression is an example of +context information bound by value. The clamp preprocessor also +supports reference semantics for contextual information via <font +class="code">__ref</font> expressions. For example: + +<p> +<font class="code"> +int sum = 0;<br> +std::for_each (v.begin(), v.end()<br> + + +, lambda (int p) { <b>__ref</b>(sum) += p; });<br> +</font> + +<p> +This, of course, calculates the sum of elements in the vector. + +<p> +Getting into some more complicated examples, it is possible to name +the type of the function object generated by a lambda expression by +simply omitting the function body. You have to do this, for instance, +if you want to use an anonymous function generated by a lambda +expression as a function parameter or return value. For example, the +type of the expression from the previous example: + +<p> +<font class="code"> +lambda (int p) { __ref(sum) += p; } +</font> + +<p> +can be referred to in the code as "<font class="code">lambda (int &) +(int)</font>". The first pair of brackets contains the context binding +(or closure) parameters, and the second pair contains the function +parameters. The closure parameter list is optional for context-less +functions, as is the return type for functions returning <font +class="code">void</font>, such as this one. Putting all of that +together, here's a templated function that returns a function object: + +<p> +<font class="code"> +template<typename T><br> +lambda bool (T) (const T &)<br> +match (const T &target) {<br> + return lambda bool (const T &candidate) {<br> + return candidate == __ctx(target);<br> + };<br> +}<br> +<p> +// Use a generated comparison object<br> +std::vector<int>::iterator<br> + i = find_if (v.begin(), v.end(), match (7));<br> +</font> +<p> +This <font class="code">find_if</font> example returns an iterator to +the first 7 in the vector (or <font class="code">v.end()</font>, if +none) using an instantiation of the <font class="code">match</font> +template with an <font class="code">int</font> parameter. For a vector +of strings, you could do the following: + +<p> +<font class="code"> +std::vector<std::string>::iterator<br> + i = find_if (v.begin(), v.end()<br> + + +, match (std::string("hello")));<br> +</font> + +<h2> +<a name="why"> +Why a preprocessor? +</h2> + +I wrote the preprocessor just for fun. There doesn't seem to be any +way to achieve real lambda expressions in pure C++, since it won't let +you insert a function definition in the middle of an expression. The +limits of what pure C++ allows are pretty well exhausted by the <a +href="http://www.boost.org/libs/lambda/doc/">boost lambda library</a>. + +<p> +Lambda expressions simplify some coding tasks, so it would be nice to +have them in C++. In the time it takes you to extract that one-liner +into a named function, I bet you could write <i>two</i> lambda +expressions for sure. Not to mention cases which require a named class +that contains context information. + +<h2> +<a name="detail"> +What it does +</h2> +<p> + +clamp scans its input for lambda expressions, passing any plain C++ +through unchanged. When it encounters a lambda expression, it extracts +the function body into a separate file. It also generates a class +template with a suitable <font class="code">operator()</font> and +(where necessary) member variables to store any context binding. This +class template also goes into a separate file. The whole lambda +expression is then replaced in the output by a single constructor +call, which creates an object of the templated class. + +<p> +The first line of the output is always a #include directive, which +drags in the generated templates and (indirectly) the function bodies. +The generated templates do not refer explicitly to any types used in +the original lambda expressions, which is how it can be included +before any user code. The actual types are only bound at the point of +use. Because of this, the clamp parser doesn't have to know what scope +a lambda expression appears in, or where the required types are +defined. This also makes including lambda expressions in templated +code a breeze, since the type binding is done within the template +scope where the expression was originally used. + +<h2> +<a name="internal"> +How it works +</h2> +<p> + +<p> +The clamp preprocessor consists of a lexical analyser (lexer) written +in flex, a parser written in bison and a code generator in plain C++. + +<p> +The clamp parser mostly tries to ignore everything in the input file, +letting the lexer copy input to output. When the lexer encounters the +<font class="code">lambda</font> keyword, it enters a different mode +("start condition" in flex terminology) in which is behaves like a +normal lexer and supplies tokens to the parser. The parser does some +messy stuff redirecting output and resetting the lexer mode as +necessary. + +<p> +Note: clamp is actually pretty dumb. It performs purely syntactic +transformations on the input, without really understanding scope, +types or variables. This will no doubt result in some incomprehensible +errors from the C++ compiler if something goes wrong. This is also the +reason that clamp requires the <font class="code">__ctx</font> and +<font class="code">__ref</font> keywords, since it wouldn't otherwise +be able to tell that an expression relies on surrounding context +information. + +<h2> +<a name="grammar"> +Grammar +</h2> +<p> +clamp introduces three keywords: <font +class="code">lambda, __ctx</font> and <font class="code">__ref</font>. +The parser recognises more or less the following grammar: + +<p> +<font size="-1"> + +<font class="nonterminal"> +lambda-expression: +<br> +lambda-decl +lambda-body<sub>opt</sub> +</font> + +<p> +<font class="nonterminal"> +lambda-decl: +<br> +</font> +<font class="terminal"> +lambda +</font> +<font class="nonterminal"> +return-type<sub>opt</sub> +param-list<sub>opt</sub> +param-list +</font> + +<p> +<font class="nonterminal"> +return-type: +<br> +type-id +</font> + +<p> +<font class="nonterminal"> +param-list: +<br> +</font> +<font class="terminal"> +( ) +</font> +<font class="nonterminal"> +<br> +</font> +<font class="terminal"> +( +</font> +<font class="nonterminal"> +parameter +</font> +<font class="terminal"> +) +</font> +<font class="nonterminal"> +<br> +</font> +<font class="terminal"> +( +</font> +<font class="nonterminal"> +parameter +</font> +<font class="terminal"> +, +</font> +<font class="nonterminal"> +... +</font> +<font class="terminal"> +) +</font> + +<p> +<font class="nonterminal"> +parameter: +<br> +type-id +identifier<sub>opt</sub> +initialiser<sub>opt</sub> +</font> + +<p> +<font class="nonterminal"> +initialiser: +<br> + + +</font> +<font class="terminal"> += +</font> +<font class="nonterminal"> +expression +</font> + +<p> +<font class="nonterminal"> +lambda-body: +<br> + + +</font> +<font class="terminal"> +{ +</font> +<font class="nonterminal"> +statement<sub>opt</sub> ... +</font> +<font class="terminal"> +} +</font> + +<p> + +</font> + +where <font class="nonterminal">statement</font> represents any valid C++ +statement, possibly making use of the following extended expressions: + +<font size="-1"> +<p> +<font class="nonterminal"> +extended-expression: +<br> +lambda-expression +<br> +</font> +<font class="terminal"> +__ctx ( +</font> +<font class="nonterminal"> +expression +</font> +<font class="terminal"> +) +</font> +<font class="nonterminal"> +<br> +</font> +<font class="terminal"> +__ref ( +</font> +<font class="nonterminal"> +expression +</font> +<font class="terminal"> +) +</font> + +</font> + +<h2> +<a name="porting"> +Portability +</h2> +I wrote clamp using the following tools: g++ 2.95.3-5 with +boost 1.25.1, flex 2.5.4, bision 1.28 and +gnu make 3.79.1, all under Cygwin on Windows 2000. The +preprocessor builds successfully with g++ 3.1, but the code that it +generates causes an internal compiler error when taking the address of +a member function. This is probably fixed in later versions of g++. + +<p> +The preprocessor itself <i>might</i> build with yacc and/or +traditional Unix make (maybe) with any reasonable C++ compiler. The +lexer probably won't compile with plain lex, because (according to the +flex manual), lex doesn't support exclusive start conditions. + +<a name="contact"> +<h2> +Contact information +</h2> +This page and clamp itself are Copyright (C) 2002, 2003 by Raoul Gough +and may be used and distributed free of charge. Please send any +clamp-related comments to <a +href="mailto:Rao...@ya...">Rao...@ya...</a>. It +might be a good idea to include the word "clamp" in the subject line, +because that email address attracts a bit of spam. + + </td> + </tr> +</table> + +</body> </html> \ No newline at end of file Modified: clamp/trunk/doc/readme.txt =================================================================== --- clamp/trunk/doc/readme.txt 2009-02-23 02:47:54 UTC (rev 1224) +++ clamp/trunk/doc/readme.txt 2009-02-23 04:37:33 UTC (rev 1225) @@ -1,19 +1,19 @@ - -clamp release 0.53 -================== - -clamp is Copyright (c) 2002, 2003 by Raoul M. Gough and licensed for -use and distribution without fee. Please refer to the disclaimer and -license details in the source code. - -To compile the clamp preprocessor, you will need to have the boost -smart_ptr library installed. Also requires bison (although yacc might -work) and flex. You can also download a pre-built windows executable -from the web site where you got this tarball. The supplied make file -works under GNU make, and should be able to build executables directly -from .clamp input files. You might have to adjust the compiler defines -at the top of the makefile to suit your system (e.g. add a suitable -I -to the CXXFLAGS). - -Limited help is provided in index.html. Please send any comments or -requests to Rao...@ya... + +clamp release 0.53 +================== + +clamp is Copyright (c) 2002, 2003 by Raoul M. Gough and licensed for +use and distribution without fee. Please refer to the disclaimer and +license details in the source code. + +To compile the clamp preprocessor, you will need to have the boost +smart_ptr library installed. Also requires bison (although yacc might +work) and flex. You can also download a pre-built windows executable +from the web site where you got this tarball. The supplied make file +works under GNU make, and should be able to build executables directly +from .clamp input files. You might have to adjust the compiler defines +at the top of the makefile to suit your system (e.g. add a suitable -I +to the CXXFLAGS). + +Limited help is provided in index.html. Please send any comments or +requests to Rao...@ya... Modified: clamp/trunk/src/CodeGen.cc =================================================================== --- clamp/trunk/src/CodeGen.cc 2009-02-23 02:47:54 UTC (rev 1224) +++ clamp/trunk/src/CodeGen.cc 2009-02-23 04:37:33 UTC (rev 1225) @@ -1,862 +1,862 @@ -// -*- mode:c++ -*- -// -// Module CodeGen.cc -// -// Copyright (c) 2002, 2003 Raoul M. Gough -// -// This material is provided "as is", with absolutely no warranty expressed -// or implied. Any use is at your own risk. -// -// Permission to use or copy this software for any purpose is hereby granted -// without fee, provided the above notices are retained on all copies. -// Permission to modify the code and to distribute modified code is granted, -// provided the above notices are retained, and a notice that the code was -// modified is included with the above copyright notice. -// -// History -// ======= -// 2002/ 2/11 rmg File creation -// - -#include "CodeGen.hh" - -#include <climits> -#include <sstream> -#include <cassert> -#include <iostream> - -extern const char *clamp_parser_rcsid; -const char *clamp_codegen_rcsid = "$Id: CodeGen.cc,v 1.20 2003/09/30 22:43:05 Raoul Exp $"; - -using namespace std; - -namespace -{ - using namespace clamp; - - unsigned count (paramListT *pListp) - { - if (pListp) - { - return pListp->size(); - } - - else - { - return 0; - } - } - - void initList (std::ostream &strm, paramListT *pListp, bool first = true) - { - if (pListp) - { - for (paramListT::const_iterator iter = pListp->begin() - ; iter != pListp->end() - ; ++iter) - { - if (iter->get()->initialiser.get()) - { - if (!first) - { - strm << ", "; - } - - strm << *iter->get()->initialiser; - - first = false; - } - - else if (iter->get()->type.get()) - { - if (!first) - { - strm << ", "; - } - - // Default initialize - strm << "(" << *iter->get()->type << ")0"; - - first = false; - } - } - } - } - - void typeList (std::ostream &strm, paramListT *pListp, bool first = true) - { - if (pListp) - { - for (paramListT::const_iterator iter = pListp->begin() - ; iter != pListp->end() - ; ++iter) - { - if (iter->get()->type.get()) - { - if (!first) - { - strm << ", "; - } - - strm << *iter->get()->type; - - first = false; - } - } - } - } -} - -namespace clamp -{ - //////////////////////////////////////////////////////////////////////// - // Constructors - //////////////////////////////////////////////////////////////////////// - - CodeGen::CodeGen () - : mStack () - , mLambdaCount (0) - , mImplStream ("lambda_impl.clamp_h") - , mLambdaMap () - , mGeneratorStream () - { - } - - CodeGen::LambdaContext::LambdaContext (FILE *f - , int b - , std::auto_ptr<lambdaT> lamp) - : mPrevFile (f) - , mOpenBracePos (b) - , mLamp (lamp.release()) - , mLambdaNumber (++sContextCount) - { - } - - CodeGen::LambdaGroup::LambdaGroup () - : mLambdaList () - , mImplStream (new stringstream) - { - } - - void implTemplateName (ostream &strm, int ccount, int pcount) - { - strm - << "lambda_template_" - << ccount - << "_" - << pcount; - } - - void tList (ostream &strm, int start, int end, bool first = true) - { - for (int count = start; count <= end; ++count) - { - if (!first) - { - strm << ", "; - } - - strm << "T" << count; - - first = false; - } - } - - void implFunctionVar (ostream &strm, int ccount, int pcount, const char *n) - { - strm << "T1 ("; - - if (ccount > 0) - { - // Implementation via pointer to member function - implTemplateName (strm, ccount, pcount); - strm << "::"; - } - // else implementation via pointer to ordinary function - - strm << "*" << n << ") ("; - tList (strm, 2 + ccount, 1 + ccount + pcount); - strm << ")"; - } - - void implInstance (ostream &strm, lambdaT const &lam) - { - unsigned ccount = count (lam.context.get()); - unsigned pcount = count (lam.params.get()); - - implTemplateName (strm, ccount, pcount); - - strm - << "<" - << *lam.ret_type; - - typeList (strm, lam.context.get(), false); - typeList (strm, lam.params.get(), false); - - strm << "> "; - } - - std::auto_ptr<stringT> CodeGen::lambdaTypeName (std::auto_ptr<lambdaT> lamp) - { - lambdaGroup (count (lamp->context.get()), count (lamp->params.get())); - // Make sure we've recorded the existance of this lambda group - - std::ostringstream temp; - - implInstance (temp, *lamp); - - return std::auto_ptr<stringT> (new stringT (temp.str())); - } - - void CodeGen::lambdaType (FILE *outFile, std::auto_ptr<lambdaT> lamp) - { - fprintf (outFile, "%s", lambdaTypeName (lamp)->c_str()); - } - - bool CodeGen::braceMatch (int pos) - { - return (!mStack.empty()) && (mStack.top().mOpenBracePos == pos); - } - - std::string contextVarExpression (paramT const &ctxParam) - { - std::stringstream result; - - result << "mContext" << ctxParam.ctx_param_num; - - return result.str(); - } - - int CodeGen::LambdaContext::sContextCount = 0; - - stringT bodyFileName (int count) - { - char name[PATH_MAX]; - sprintf (name, "lambda_body_%d.clamp_h", count); - return stringT (name); - } - - void explicitConstructor (ostream &strm, int id, const lambdaT &lam) - { - if (lam.onHeap) - { - strm << "new "; - } - - implInstance (strm, lam); - strm << "(&"; - implInstance (strm, lam); - strm << "::fn" << id; - initList (strm, lam.context.get(), false); - strm << ")"; - } - - void typenameList (ostream &strm - , unsigned start - , unsigned end - , bool first = true) - { - for (unsigned count = start; count <= end; ++count) - { - if (!first) - { - strm << ", "; - } - - strm << "typename T" << count; - - first = false; - } - } - - void implTemplateDecl (ostream &strm, unsigned templateParams) - { - strm - << "template <"; - - typenameList (strm, 1, templateParams); - - strm << ">"; - } - - void startExplicitImpl (ostream &strm, unsigned ccount, unsigned pcount) - { - implTemplateDecl (strm, ccount + pcount + 1); - - strm << "\nstruct "; - - implTemplateName (strm, ccount, pcount); - - strm << "\n{\n "; - - implFunctionVar (strm, ccount, pcount, "mFn"); - - strm << ";"; - - for (unsigned count = 1; count <= ccount; ++count) - { - strm << "\n T" << count + 1 << " mContext" << count << ";"; - } - - strm << "\n\n typedef T1 result_type;"; - - for (unsigned count = 1; count <= ccount; ++count) - { - strm - << "\n typedef T" << count + 1 - << " context_type_" << count - << ";"; - } - - for (unsigned count = 1; count <= pcount; ++count) - { - strm - << "\n typedef T" << count + ccount + 1 - << " argument_type_" << count - << ";"; - } - - // Additional typedefs in special cases for standard binder compatability - if (pcount == 1) - { - strm - << "\n typedef T" << ccount + 2 - << " argument_type;"; - } - - else if (pcount == 2) - { - strm - << "\n typedef T" << ccount + 2 - << " first_argument_type;\n typedef T" << ccount + 3 - << " second_argument_type;"; - } - - strm << "\n\n // Constructor\n "; - - implTemplateName (strm, ccount, pcount); - - strm << " ("; - - implFunctionVar (strm, ccount, pcount, "fn"); - - for (unsigned count = 1; count <= ccount; ++count) - { - strm << ", T" << count + 1 << " c" << count; - } - - strm << ")\n : mFn (fn)"; - - for (unsigned count = 1; count <= ccount; ++count) - { - strm << "\n , mContext" << count << " (c" << count << ")"; - } - - strm - << "\n { }\n" - << "\n // Forwarding function" - << "\n T1 operator() ("; - - for (unsigned count = 1; count <= pcount; ++count) - { - if (count != 1) - { - strm << ", "; - } - - strm << "T" << count + ccount + 1 << " p" << count; - } - - strm << ")\n {\n return ("; - - if (ccount > 0) - { - // Have closure parameters - use pointer to member syntax - strm << "this->"; - } - // else static function - - strm << "*mFn)("; - - for (unsigned count = 1; count <= pcount; ++count) - { - if (count != 1) - { - strm << ", "; - } - - strm << "p" << count; - } - - strm << ");\n }\n"; - } - - void declareMemberFn (ostream &strm - , int id - , unsigned ccount - , unsigned pcount) - { - strm << "\n "; - - if (ccount == 0) - { - strm << "static "; - } - - strm << "T1 fn" << id << " ("; - - tList (strm, 2 + ccount, 1 + ccount + pcount); - - strm << ");\n"; - } - - void defineMemberFn (ostream &strm - , int id - , unsigned ccount - , unsigned pcount - , const lambdaT &lam) - { - implTemplateDecl (strm, ccount + pcount + 1); - - strm << "\nT1 "; - - implTemplateName (strm, ccount, pcount); - - strm << "<"; - - tList (strm, 1, 1 + ccount + pcount); - - strm << ">::fn" << id << " ("; - - if (lam.params.get()) - { - unsigned count = 1; - - for (paramListT::const_iterator iter = lam.params->begin() - ; iter != lam.params->end() - ; ++iter) - { - if (count != 1) - { - strm << ", "; - } - - strm << "T" << count + ccount + 1; - - const stringT *name = iter->get()->name.get(); - - if (name) - { - strm - << " " << *name; - } - - ++count; - } - } - - strm << ")\n{"; - - if (lam.explicitContext && lam.context.get()) - { - // Context parameters require renaming - unsigned count = 1; - - for (paramListT::const_iterator iter = lam.context->begin() - ; iter != lam.context->end() - ; ++iter) - { - const stringT *name = iter->get()->name.get(); - - if (name) - { - strm - << "\n#define " << *name - << " mContext" - << count; - } - - ++count; - } - } - - strm - << "\n#include \"" - << bodyFileName (id) - << "\""; - - if (lam.explicitContext && lam.context.get()) - { - unsigned count = 1; - - for (paramListT::const_iterator iter = lam.context->begin() - ; iter != lam.context->end() - ; ++iter) - { - const stringT *name = iter->get()->name.get(); - - if (name) - { - strm - << "\n#undef " << *name; - } - - ++count; - } - } - - strm << "\n}\n"; - } - - void implicitConstructor (ostream &strm, int id, const lambdaT &lam) - { - strm - << "lambda_generator_" - << id - << "<" - << *lam.ret_type; - - typeList (strm, lam.params.get(), false); - - strm << ">::generate ("; - - initList (strm, lam.context.get()); - - strm <<")"; - } - - void implicitTemplateInstance (ostream &strm - , const lambdaT &lam - , unsigned ccount - , unsigned pcount) - { - implTemplateName (strm, ccount, pcount); - - strm << " <T1"; - - if (ccount) - { - paramListT::const_iterator iter = lam.context->begin(); - - for (unsigned count = 1; count <= ccount; ++count) - { - strm << ", T" << count + 1; - - if ((*iter)->byReference) - { - strm << " &"; - } - - ++iter; - } - } - - tList (strm, 2 + ccount, 1 + ccount + pcount, false); - - strm << ">"; - } - - void writeGenerator (ostream &strm, int id, const lambdaT &lam) - { - unsigned ccount = count (lam.context.get()); - unsigned pcount = count (lam.params.get()); - - strm << "\ntemplate <"; - - typenameList (strm, 1, 1); - typenameList (strm, 2 + ccount, 1 + ccount + pcount, false); - - strm - << ">\nstruct lambda_generator_" << id - << "\n{"; - - if (ccount >= 1) - { - strm << "\n template <"; - - typenameList (strm, 2, 1 + ccount); - - strm << ">"; - } - - strm << "\n static "; - - implicitTemplateInstance (strm, lam, ccount, pcount); - - if (lam.onHeap) - { - strm << " *"; - } - - strm << "\n generate ("; - - if (ccount) - { - paramListT::const_iterator iter = lam.context->begin(); - - for (unsigned count = 1; count <= ccount; ++count) - { - if (count != 1) - { - strm << ", "; - } - - strm << "T" << count + 1 << " "; - - if ((*iter)->byReference) - { - strm << "&"; // Accept parameter by reference - } - - strm << "p" << count; - - ++iter; - } - } - - strm << ")\n {\n return "; - - if (lam.onHeap) - { - strm << "new "; - } - - implicitTemplateInstance (strm, lam, ccount, pcount); - - strm << " (&"; - implicitTemplateInstance (strm, lam, ccount, pcount); - strm << "::fn" << id; - - if (ccount) - { - unsigned count = 0; - - for (paramListT::const_iterator iter = lam.context->begin() - ; iter != lam.context->end() - ; ++iter) - { - ++count; - - strm << ", " << "p" << count; - } - } - - strm << ");\n }\n};\n"; - } - - struct MatchInitialiser - { - const stringT &mTarget; - bool mByRef; - - MatchInitialiser (const stringT &target - , bool byRef) - : mTarget (target) - , mByRef (byRef) - { - } - - bool operator() (const boost::shared_ptr<paramT> &pp) - { - return (mTarget == (*pp->initialiser)) && (mByRef == pp->byReference); - } - }; - - bool CodeGen::contextRef (FILE *outFile - , std::auto_ptr<stringT> strp - , bool byRef) - { - // Handles context by value and by reference - - lambdaT &lam (*mStack.top().mLamp); - - if (lam.explicitContext) - { - cerr - << "__ctx or __ref expression in lambda with explicit context\n"; - - return false; - } - - if (!lam.context.get()) - { - lam.context.reset (new paramListT); - } - - paramListT &context (*lam.context); - - paramListT::iterator param; - - param = std::find_if (context.begin() - , context.end() - , MatchInitialiser (*strp, byRef)); - - if (param == context.end()) - { - int ccount = context.size() + 1; - - char newName[128]; - - sprintf (newName, "mContext%d", ccount); - - char pseudoType[128]; - - sprintf (pseudoType, "T%d", ccount); - - boost::shared_ptr<paramT> - newParamPtr (new paramT (makestr(pseudoType) - , makestr (newName) - , strp.release() - , ccount - , byRef)); - - context.push_back (newParamPtr); - - param = context.end(); - --param; - } - - fprintf (outFile, "%s", contextVarExpression (**param).c_str()); - - return true; - } - - bool CodeGen::startLambda (FILE *&f - , int openBracePos - , std::auto_ptr<lambdaT> lamp) - { - mStack.push (LambdaContext (f, openBracePos, lamp)); - - string newName (bodyFileName (++mLambdaCount)); - - f = fopen (newName.c_str(), "w+"); - - if (!f) - { - cerr - << "Failed to create new body file " - << newName - << "\n"; - - f = mStack.top().mPrevFile; - mStack.pop (); - - return false; - } - - return true; - } - - CodeGen::LambdaMap::iterator CodeGen::lambdaGroup (int ccount, int pcount) - { - LambdaType typeId (ccount, pcount); - - LambdaMap::iterator mapIter = mLambdaMap.find (typeId); - - if (mapIter == mLambdaMap.end()) - { - pair<LambdaMap::iterator, bool> inserted - = mLambdaMap.insert (std::make_pair (typeId, LambdaGroup())); - - assert (inserted.second); - - mapIter = inserted.first; - - startExplicitImpl (*mapIter->second.mImplStream, ccount, pcount); - } - - return mapIter; - } - - bool CodeGen::endLambda (FILE *&f) - { - fprintf (f, "\n"); // Ensure newline termination - fclose (f); - f = mStack.top().mPrevFile; - - LambdaContext &ctx (mStack.top()); - - int ccount = count (ctx.mLamp->context.get()); - int pcount = count (ctx.mLamp->params.get()); - - LambdaMap::iterator mapIter = lambdaGroup (ccount, pcount); - - mapIter->second.mLambdaList.push_back (ctx); - - declareMemberFn (*mapIter->second.mImplStream - , ctx.mLambdaNumber - , ccount - , pcount); - - std::ostringstream temp; - - if (ctx.mLamp->explicitContext) - { - explicitConstructor (temp, ctx.mLambdaNumber, *ctx.mLamp); - } - - else - { - writeGenerator (mGeneratorStream, ctx.mLambdaNumber, *ctx.mLamp); - implicitConstructor (temp, ctx.mLambdaNumber, *ctx.mLamp); - } - - fprintf (f, "%s", temp.str().c_str()); - - mStack.pop(); - return true; - } - - void CodeGen::spitItOut () - { - mImplStream - << "//" - << "\n// clamp generated lambda templates" - << "\n// parser " << clamp_parser_rcsid - << "\n// code generator " << clamp_codegen_rcsid - << "\n//\n\n" - ; - - for (LambdaMap::const_iterator iter = mLambdaMap.begin() - ; iter != mLambdaMap.end() - ; ++iter) - { - mImplStream - << iter->second.mImplStream->rdbuf() - << "\nprivate:\n "; - - // Make the assignment operator private, since it wouldn't - // handle any reference member variables - - implTemplateName (mImplStream, iter->first.first, iter->first.second); - - mImplStream << " operator= ("; - - implTemplateName (mImplStream, iter->first.first, iter->first.second); - - mImplStream - << " const &);\n" - << "};\n"; - } - - mImplStream << "\n" << mGeneratorStream.str() << "\n"; - - for (LambdaMap::const_iterator group = mLambdaMap.begin() - ; group != mLambdaMap.end() - ; ++group) - { - const LambdaList &list (group->second.mLambdaList); - - for (LambdaList::const_iterator iter = list.begin() - ; iter != list.end() - ; ++iter) - { - defineMemberFn (mImplStream - , iter->mLambdaNumber - , group->first.first - , group->first.second - , *iter->mLamp); - } - } - } -} +// -*- mode:c++ -*- +// +// Module CodeGen.cc +// +// Copyright (c) 2002, 2003 Raoul M. Gough +// +// This material is provided "as is", with absolutely no warranty expressed +// or implied. Any use is at your own risk. +// +// Permission to use or copy this software for any purpose is hereby granted +// without fee, provided the above notices are retained on all copies. +// Permission to modify the code and to distribute modified code is granted, +// provided the above notices are retained, and a notice that the code was +// modified is included with the above copyright notice. +// +// History +// ======= +// 2002/ 2/11 rmg File creation +// + +#include "CodeGen.hh" + +#include <climits> +#include <sstream> +#include <cassert> +#include <iostream> + +extern const char *clamp_parser_rcsid; +const char *clamp_codegen_rcsid = "$Id: CodeGen.cc,v 1.20 2003/09/30 22:43:05 Raoul Exp $"; + +using namespace std; + +namespace +{ + using namespace clamp; + + unsigned count (paramListT *pListp) + { + if (pListp) + { + return pListp->size(); + } + + else + { + return 0; + } + } + + void initList (std::ostream &strm, paramListT *pListp, bool first = true) + { + if (pListp) + { + for (paramListT::const_iterator iter = pListp->begin() + ; iter != pListp->end() + ; ++iter) + { + if (iter->get()->initialiser.get()) + { + if (!first) + { + strm << ", "; + } + + strm << *iter->get()->initialiser; + + first = false; + } + + else if (iter->get()->type.get()) + { + if (!first) + { + strm << ", "; + } + + // Default initialize + strm << "(" << *iter->get()->type << ")0"; + + first = false; + } + } + } + } + + void typeList (std::ostream &strm, paramListT *pListp, bool first = true) + { + if (pListp) + { + for (paramListT::const_iterator iter = pListp->begin() + ; iter != pListp->end() + ; ++iter) + { + if (iter->get()->type.get()) + { + if (!first) + { + strm << ", "; + } + + strm << *iter->get()->type; + + first = false; + } + } + } + } +} + +namespace clamp +{ + //////////////////////////////////////////////////////////////////////// + // Constructors + //////////////////////////////////////////////////////////////////////// + + CodeGen::CodeGen () + : mStack () + , mLambdaCount (0) + , mImplStream ("lambda_impl.clamp_h") + , mLambdaMap () + , mGeneratorStream () + { + } + + CodeGen::LambdaContext::LambdaContext (FILE *f + , int b + , std::auto_ptr<lambdaT> lamp) + : mPrevFile (f) + , mOpenBracePos (b) + , mLamp (lamp.release()) + , mLambdaNumber (++sContextCount) + { + } + + CodeGen::LambdaGroup::LambdaGroup () + : mLambdaList () + , mImplStream (new stringstream) + { + } + + void implTemplateName (ostream &strm, int ccount, int pcount) + { + strm + << "lambda_template_" + << ccount + << "_" + << pcount; + } + + void tList (ostream &strm, int start, int end, bool first = true) + { + for (int count = start; count <= end; ++count) + { + if (!first) + { + strm << ", "; + } + + strm << "T" << count; + + first = false; + } + } + + void implFunctionVar (ostream &strm, int ccount, int pcount, const char *n) + { + strm << "T1 ("; + + if (ccount > 0) + { + // Implementation via pointer to member function + implTemplateName (strm, ccount, pcount); + strm << "::"; + } + // else implementation via pointer to ordinary function + + strm << "*" << n << ") ("; + tList (strm, 2 + ccount, 1 + ccount + pcount); + strm << ")"; + } + + void implInstance (ostream &strm, lambdaT const &lam) + { + unsigned ccount = count (lam.context.get()); + unsigned pcount = count (lam.params.get()); + + implTemplateName (strm, ccount, pcount); + + strm + << "<" + << *lam.ret_type; + + typeList (strm, lam.context.get(), false); + typeList (strm, lam.params.get(), false); + + strm << "> "; + } + + std::auto_ptr<stringT> CodeGen::lambdaTypeName (std::auto_ptr<lambdaT> lamp) + { + lambdaGroup (count (lamp->context.get()), count (lamp->params.get())); + // Make sure we've recorded the existance of this lambda group + + std::ostringstream temp; + + implInstance (temp, *lamp); + + return std::auto_ptr<stringT> (new stringT (temp.str())); + } + + void CodeGen::lambdaType (FILE *outFile, std::auto_ptr<lambdaT> lamp) + { + fprintf (outFile, "%s", lambdaTypeName (lamp)->c_str()); + } + + bool CodeGen::braceMatch (int pos) + { + return (!mStack.empty()) && (mStack.top().mOpenBracePos == pos); + } + + std::string contextVarExpression (paramT const &ctxParam) + { + std::stringstream result; + + result << "mContext" << ctxParam.ctx_param_num; + + return result.str(); + } + + int CodeGen::LambdaContext::sContextCount = 0; + + stringT bodyFileName (int count) + { + char name[PATH_MAX]; + sprintf (name, "lambda_body_%d.clamp_h", count); + return stringT (name); + } + + void explicitConstructor (ostream &strm, int id, const lambdaT &lam) + { + if (lam.onHeap) + { + strm << "new "; + } + + implInstance (strm, lam); + strm << "(&"; + implInstance (strm, lam); + strm << "::fn" << id; + initList (strm, lam.context.get(), false); + strm << ")"; + } + + void typenameList (ostream &strm + , unsigned start + , unsigned end + , bool first = true) + { + for (unsigned count = start; count <= end; ++count) + { + if (!first) + { + strm << ", "; + } + + strm << "typename T" << count; + + first = false; + } + } + + void implTemplateDecl (ostream &strm, unsigned templateParams) + { + strm + << "template <"; + + typenameList (strm, 1, templateParams); + + strm << ">"; + } + + void startExplicitImpl (ostream &strm, unsigned ccount, unsigned pcount) + { + implTemplateDecl (strm, ccount + pcount + 1); + + strm << "\nstruct "; + + implTemplateName (strm, ccount, pcount); + + strm << "\n{\n "; + + implFunctionVar (strm, ccount, pcount, "mFn"); + + strm << ";"; + + for (unsigned count = 1; count <= ccount; ++count) + { + strm << "\n T" << count + 1 << " mContext" << count << ";"; + } + + strm << "\n\n typedef T1 result_type;"; + + for (unsigned count = 1; count <= ccount; ++count) + { + strm + << "\n typedef T" << count + 1 + << " context_type_" << count + << ";"; + } + + for (unsigned count = 1; count <= pcount; ++count) + { + strm + << "\n typedef T" << count + ccount + 1 + << " argument_type_" << count + << ";"; + } + + // Additional typedefs in special cases for standard binder compatability + if (pcount == 1) + { + strm + << "\n typedef T" << ccount + 2 + << " argument_type;"; + } + + else if (pcount == 2) + { + strm + << "\n typedef T" << ccount + 2 + << " first_argument_type;\n typedef T" << ccount + 3 + << " second_argument_type;"; + } + + strm << "\n\n // Constructor\n "; + + implTemplateName (strm, ccount, pcount); + + strm << " ("; + + implFunctionVar (strm, ccount, pcount, "fn"); + + for (unsigned count = 1; count <= ccount; ++count) + { + strm << ", T" << count + 1 << " c" << count; + } + + strm << ")\n : mFn (fn)"; + + for (unsigned count = 1; count <= ccount; ++count) + { + strm << "\n , mContext" << count << " (c" << count << ")"; + } + + strm + << "\n { }\n" + << "\n // Forwarding function" + << "\n T1 operator() ("; + + for (unsigned count = 1; count <= pcount; ++count) + { + if (count != 1) + { + strm << ", "; + } + + strm << "T" << count + ccount + 1 << " p" << count; + } + + strm << ")\n {\n return ("; + + if (ccount > 0) + { + // Have closure parameters - use pointer to member syntax + strm << "this->"; + } + // else static function + + strm << "*mFn)("; + + for (unsigned count = 1; count <= pcount; ++count) + { + if (count != 1) + { + strm << ", "; + } + + strm << "p" << count; + } + + strm << ");\n }\n"; + } + + void declareMemberFn (ostream &strm + , int id + , unsigned ccount + , unsigned pcount) + { + strm << "\n "; + + if (ccount == 0) + { + strm << "static "; + } + + strm << "T1 fn" << id << " ("; + + tList (strm, 2 + ccount, 1 + ccount + pcount); + + strm << ");\n"; + } + + void defineMemberFn (ostream &strm + , int id + , unsigned ccount + , unsigned pcount + , const lambdaT &lam) + { + implTemplateDecl (strm, ccount + pcount + 1); + + strm << "\nT1 "; + + implTemplateName (strm, ccount, pcount); + + strm << "<"; + + tList (strm, 1, 1 + ccount + pcount); + + strm << ">::fn" << id << " ("; + + if (lam.params.get()) + { + unsigned count = 1; + + for (paramListT::const_iterator iter = lam.params->begin() + ; iter != lam.params->end() + ; ++iter) + { + if (count != 1) + { + strm << ", "; + } + + strm << "T" << count + ccount + 1; + + const stringT *name = iter->get()->name.get(); + + if (name) + { + strm + << " " << *name; + } + + ++count; + } + } + + strm << ")\n{"; + + if (lam.explicitContext && lam.context.get()) + { + // Context parameters require renaming + unsigned count = 1; + + for (paramListT::const_iterator iter = lam.context->begin() + ; iter != lam.context->end() + ; ++iter) + { + const stringT *name = iter->get()->name.get(); + + if (name) + { + strm + << "\n#define " << *name + << " mContext" + << count; + } + + ++count; + } + } + + strm + << "\n#include \"" + << bodyFileName (id) + << "\""; + + if (lam.explicitContext && lam.context.get()) + { + unsigned count = 1; + + for (paramListT::const_iterator iter = lam.context->begin() + ; iter != lam.context->end() + ; ++iter) + { + const stringT *name = iter->get()->name.get(); + + if (name) + { + strm + << "\n#undef " << *name; + } + + ++count; + } + } + + strm << "\n}\n"; + } + + void implicitConstructor (ostream &strm, int id, const lambdaT &lam) + { + strm + << "lambda_generator_" + << id + << "<" + << *lam.ret_type; + + typeList (strm, lam.params.get(), false); + + strm << ">::generate ("; + + initList (strm, lam.context.get()); + + strm <<")"; + } + + void implicitTemplateInstance (ostream &strm + , const lambdaT &lam + , unsigned ccount + , unsigned pcount) + { + implTemplateName (strm, ccount, pcount); + + strm ... [truncated message content] |
From: <yan...@us...> - 2009-02-23 02:48:07
|
Revision: 1224 http://assorted.svn.sourceforge.net/assorted/?rev=1224&view=rev Author: yangzhang Date: 2009-02-23 02:47:54 +0000 (Mon, 23 Feb 2009) Log Message: ----------- carrying clamp forward! Added Paths: ----------- clamp/ clamp/trunk/ clamp/trunk/doc/ clamp/trunk/doc/index.html clamp/trunk/doc/readme.txt clamp/trunk/src/ clamp/trunk/src/CodeGen.cc clamp/trunk/src/CodeGen.hh clamp/trunk/src/Makefile clamp/trunk/src/clamp.y clamp/trunk/src/clamp_support.cc clamp/trunk/src/clamp_support.hh clamp/trunk/src/clamplex.h clamp/trunk/src/clamplex.lex clamp/trunk/src/curry.clamp clamp/trunk/src/eg.clamp clamp/trunk/src/home_page_examples.clamp clamp/trunk/src/test.clamp Added: clamp/trunk/doc/index.html =================================================================== --- clamp/trunk/doc/index.html (rev 0) +++ clamp/trunk/doc/index.html 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,489 @@ +<html> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<meta name="Author" content="Raoul Gough"> + +<title>Project page for clamp - the C++ lambda preprocessor</title> + +<!-- $Id: index.html,v 1.14 2003/09/30 22:04:44 Raoul Exp $ --> + +<STYLE> +<!-- + +font.terminal { + font-family: arial, sans-serif; + font-weight: normal; + text-align: left; + vertical-align: top; +} + +font.nonterminal { + font-family: arial, sans-serif; + font-weight: normal; + font-style: italic; + text-align: left; + vertical-align: top; +} + +font.code { + font-family: courier, monotype; + font-weight: normal; + text-align: left; + vertical-align: middle; +} + +--> +</STYLE> + + +<body> + +<table width="100%"> + <tr> + <td colspan=2> +<a name="intro"> +<h1> +C++ lambda preprocessor +</h1> + </td> + </tr> + <tr> + <td bgcolor="lightblue" valign="top"> + <font size="-1"> + +<b> +Directory +</b> +<br> +<a href="#why">Why clamp?</a><br> +<a href="#detail">What it does</a><br> +<a href="#internal">How it works</a><br> +<a href="#grammar">Grammar</a><br> +<a href="#porting">Portability</a><br> +<a href="#contact">Contact info</a><br> +<a href="clamp_053_src.tar.gz">Source download</a> +<a href="clamp_053_exe.tar.gz">Windows executable</a> +<a href="../index.html">Author's home page</a> + + </font> + </td> + <td> + +The C++ lambda preprocessor (clamp) converts C++ code containing +lambda expressions into ordinary C++ code. Here's a simple example: + +<p> +<font class="code"> +vector<int> v;<br> +// ... <br> +std::for_each (v.begin(), v.end()<br> + + + , <b>lambda</b> (int &p) {<br> + + + if (p == 5) p = 0;<br> + + + } ); +</font> + +<p> +This example uses the standard algorithm <font +class="code">for_each</font> to apply an anonymous function to each +element of a vector. The anonymous function accepts an integer +parameter by reference, and resets the value to zero if it is +currently five (a simple, but not very useful example). The +preprocessor replaces the entire lambda expression in its output, so +that the C++ compiler ends up seeing something like the following: + +<p> +<font class="code"> +std::for_each (v.begin(), v.end()<br> + + , lambda_generator_1<void, int &>::generate () ); +</font> + +<p> +The exact nature of the template <font +class="code">lambda_generator_1</font> is beyond the scope of this +introduction, except to say that its <font +class="code">generate()</font> member function returns a function +object by value. The function object has, in this case, a member +function <font class="code">void operator()(int &)</font> +which <font class="code">for_each</font> applies to each element of +the vector. Some people would probably prefer to use the standard +<font class="code">transform</font> algorithm for this example, as in: + +<p> +<font class="code"> +std::transform (v.begin(), v.end(), v.begin()<br> + + + , lambda int (int p) {<br> + + + return (p == 5) ? 0 : p;<br> + + + } ); +</font> + +<p> +This example shows an anonymous function that returns a value, in this +case int. Rather than hard-wiring a value into the function body, it +is also possible to include contextual information in the function +object. For instance: + +<p> +<font class="code"> +void reset (std::vector<int> &v, int val) {<br> + +std::transform (v.begin(), v.end(), v.begin()<br> + + + , lambda int (int p) {<br> + + + return (p == <b>__ctx</b>(val)) ? 0 : p;<br> + + + } );<br> +} +</font> + +<p> +The <font class="code">__ctx</font> expression is an example of +context information bound by value. The clamp preprocessor also +supports reference semantics for contextual information via <font +class="code">__ref</font> expressions. For example: + +<p> +<font class="code"> +int sum = 0;<br> +std::for_each (v.begin(), v.end()<br> + + +, lambda (int p) { <b>__ref</b>(sum) += p; });<br> +</font> + +<p> +This, of course, calculates the sum of elements in the vector. + +<p> +Getting into some more complicated examples, it is possible to name +the type of the function object generated by a lambda expression by +simply omitting the function body. You have to do this, for instance, +if you want to use an anonymous function generated by a lambda +expression as a function parameter or return value. For example, the +type of the expression from the previous example: + +<p> +<font class="code"> +lambda (int p) { __ref(sum) += p; } +</font> + +<p> +can be referred to in the code as "<font class="code">lambda (int &) +(int)</font>". The first pair of brackets contains the context binding +(or closure) parameters, and the second pair contains the function +parameters. The closure parameter list is optional for context-less +functions, as is the return type for functions returning <font +class="code">void</font>, such as this one. Putting all of that +together, here's a templated function that returns a function object: + +<p> +<font class="code"> +template<typename T><br> +lambda bool (T) (const T &)<br> +match (const T &target) {<br> + return lambda bool (const T &candidate) {<br> + return candidate == __ctx(target);<br> + };<br> +}<br> +<p> +// Use a generated comparison object<br> +std::vector<int>::iterator<br> + i = find_if (v.begin(), v.end(), match (7));<br> +</font> +<p> +This <font class="code">find_if</font> example returns an iterator to +the first 7 in the vector (or <font class="code">v.end()</font>, if +none) using an instantiation of the <font class="code">match</font> +template with an <font class="code">int</font> parameter. For a vector +of strings, you could do the following: + +<p> +<font class="code"> +std::vector<std::string>::iterator<br> + i = find_if (v.begin(), v.end()<br> + + +, match (std::string("hello")));<br> +</font> + +<h2> +<a name="why"> +Why a preprocessor? +</h2> + +I wrote the preprocessor just for fun. There doesn't seem to be any +way to achieve real lambda expressions in pure C++, since it won't let +you insert a function definition in the middle of an expression. The +limits of what pure C++ allows are pretty well exhausted by the <a +href="http://www.boost.org/libs/lambda/doc/">boost lambda library</a>. + +<p> +Lambda expressions simplify some coding tasks, so it would be nice to +have them in C++. In the time it takes you to extract that one-liner +into a named function, I bet you could write <i>two</i> lambda +expressions for sure. Not to mention cases which require a named class +that contains context information. + +<h2> +<a name="detail"> +What it does +</h2> +<p> + +clamp scans its input for lambda expressions, passing any plain C++ +through unchanged. When it encounters a lambda expression, it extracts +the function body into a separate file. It also generates a class +template with a suitable <font class="code">operator()</font> and +(where necessary) member variables to store any context binding. This +class template also goes into a separate file. The whole lambda +expression is then replaced in the output by a single constructor +call, which creates an object of the templated class. + +<p> +The first line of the output is always a #include directive, which +drags in the generated templates and (indirectly) the function bodies. +The generated templates do not refer explicitly to any types used in +the original lambda expressions, which is how it can be included +before any user code. The actual types are only bound at the point of +use. Because of this, the clamp parser doesn't have to know what scope +a lambda expression appears in, or where the required types are +defined. This also makes including lambda expressions in templated +code a breeze, since the type binding is done within the template +scope where the expression was originally used. + +<h2> +<a name="internal"> +How it works +</h2> +<p> + +<p> +The clamp preprocessor consists of a lexical analyser (lexer) written +in flex, a parser written in bison and a code generator in plain C++. + +<p> +The clamp parser mostly tries to ignore everything in the input file, +letting the lexer copy input to output. When the lexer encounters the +<font class="code">lambda</font> keyword, it enters a different mode +("start condition" in flex terminology) in which is behaves like a +normal lexer and supplies tokens to the parser. The parser does some +messy stuff redirecting output and resetting the lexer mode as +necessary. + +<p> +Note: clamp is actually pretty dumb. It performs purely syntactic +transformations on the input, without really understanding scope, +types or variables. This will no doubt result in some incomprehensible +errors from the C++ compiler if something goes wrong. This is also the +reason that clamp requires the <font class="code">__ctx</font> and +<font class="code">__ref</font> keywords, since it wouldn't otherwise +be able to tell that an expression relies on surrounding context +information. + +<h2> +<a name="grammar"> +Grammar +</h2> +<p> +clamp introduces three keywords: <font +class="code">lambda, __ctx</font> and <font class="code">__ref</font>. +The parser recognises more or less the following grammar: + +<p> +<font size="-1"> + +<font class="nonterminal"> +lambda-expression: +<br> +lambda-decl +lambda-body<sub>opt</sub> +</font> + +<p> +<font class="nonterminal"> +lambda-decl: +<br> +</font> +<font class="terminal"> +lambda +</font> +<font class="nonterminal"> +return-type<sub>opt</sub> +param-list<sub>opt</sub> +param-list +</font> + +<p> +<font class="nonterminal"> +return-type: +<br> +type-id +</font> + +<p> +<font class="nonterminal"> +param-list: +<br> +</font> +<font class="terminal"> +( ) +</font> +<font class="nonterminal"> +<br> +</font> +<font class="terminal"> +( +</font> +<font class="nonterminal"> +parameter +</font> +<font class="terminal"> +) +</font> +<font class="nonterminal"> +<br> +</font> +<font class="terminal"> +( +</font> +<font class="nonterminal"> +parameter +</font> +<font class="terminal"> +, +</font> +<font class="nonterminal"> +... +</font> +<font class="terminal"> +) +</font> + +<p> +<font class="nonterminal"> +parameter: +<br> +type-id +identifier<sub>opt</sub> +initialiser<sub>opt</sub> +</font> + +<p> +<font class="nonterminal"> +initialiser: +<br> + + +</font> +<font class="terminal"> += +</font> +<font class="nonterminal"> +expression +</font> + +<p> +<font class="nonterminal"> +lambda-body: +<br> + + +</font> +<font class="terminal"> +{ +</font> +<font class="nonterminal"> +statement<sub>opt</sub> ... +</font> +<font class="terminal"> +} +</font> + +<p> + +</font> + +where <font class="nonterminal">statement</font> represents any valid C++ +statement, possibly making use of the following extended expressions: + +<font size="-1"> +<p> +<font class="nonterminal"> +extended-expression: +<br> +lambda-expression +<br> +</font> +<font class="terminal"> +__ctx ( +</font> +<font class="nonterminal"> +expression +</font> +<font class="terminal"> +) +</font> +<font class="nonterminal"> +<br> +</font> +<font class="terminal"> +__ref ( +</font> +<font class="nonterminal"> +expression +</font> +<font class="terminal"> +) +</font> + +</font> + +<h2> +<a name="porting"> +Portability +</h2> +I wrote clamp using the following tools: g++ 2.95.3-5 with +boost 1.25.1, flex 2.5.4, bision 1.28 and +gnu make 3.79.1, all under Cygwin on Windows 2000. The +preprocessor builds successfully with g++ 3.1, but the code that it +generates causes an internal compiler error when taking the address of +a member function. This is probably fixed in later versions of g++. + +<p> +The preprocessor itself <i>might</i> build with yacc and/or +traditional Unix make (maybe) with any reasonable C++ compiler. The +lexer probably won't compile with plain lex, because (according to the +flex manual), lex doesn't support exclusive start conditions. + +<a name="contact"> +<h2> +Contact information +</h2> +This page and clamp itself are Copyright (C) 2002, 2003 by Raoul Gough +and may be used and distributed free of charge. Please send any +clamp-related comments to <a +href="mailto:Rao...@ya...">Rao...@ya...</a>. It +might be a good idea to include the word "clamp" in the subject line, +because that email address attracts a bit of spam. + + </td> + </tr> +</table> + +</body> +</html> \ No newline at end of file Added: clamp/trunk/doc/readme.txt =================================================================== --- clamp/trunk/doc/readme.txt (rev 0) +++ clamp/trunk/doc/readme.txt 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,19 @@ + +clamp release 0.53 +================== + +clamp is Copyright (c) 2002, 2003 by Raoul M. Gough and licensed for +use and distribution without fee. Please refer to the disclaimer and +license details in the source code. + +To compile the clamp preprocessor, you will need to have the boost +smart_ptr library installed. Also requires bison (although yacc might +work) and flex. You can also download a pre-built windows executable +from the web site where you got this tarball. The supplied make file +works under GNU make, and should be able to build executables directly +from .clamp input files. You might have to adjust the compiler defines +at the top of the makefile to suit your system (e.g. add a suitable -I +to the CXXFLAGS). + +Limited help is provided in index.html. Please send any comments or +requests to Rao...@ya... Added: clamp/trunk/src/CodeGen.cc =================================================================== --- clamp/trunk/src/CodeGen.cc (rev 0) +++ clamp/trunk/src/CodeGen.cc 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,862 @@ +// -*- mode:c++ -*- +// +// Module CodeGen.cc +// +// Copyright (c) 2002, 2003 Raoul M. Gough +// +// This material is provided "as is", with absolutely no warranty expressed +// or implied. Any use is at your own risk. +// +// Permission to use or copy this software for any purpose is hereby granted +// without fee, provided the above notices are retained on all copies. +// Permission to modify the code and to distribute modified code is granted, +// provided the above notices are retained, and a notice that the code was +// modified is included with the above copyright notice. +// +// History +// ======= +// 2002/ 2/11 rmg File creation +// + +#include "CodeGen.hh" + +#include <climits> +#include <sstream> +#include <cassert> +#include <iostream> + +extern const char *clamp_parser_rcsid; +const char *clamp_codegen_rcsid = "$Id: CodeGen.cc,v 1.20 2003/09/30 22:43:05 Raoul Exp $"; + +using namespace std; + +namespace +{ + using namespace clamp; + + unsigned count (paramListT *pListp) + { + if (pListp) + { + return pListp->size(); + } + + else + { + return 0; + } + } + + void initList (std::ostream &strm, paramListT *pListp, bool first = true) + { + if (pListp) + { + for (paramListT::const_iterator iter = pListp->begin() + ; iter != pListp->end() + ; ++iter) + { + if (iter->get()->initialiser.get()) + { + if (!first) + { + strm << ", "; + } + + strm << *iter->get()->initialiser; + + first = false; + } + + else if (iter->get()->type.get()) + { + if (!first) + { + strm << ", "; + } + + // Default initialize + strm << "(" << *iter->get()->type << ")0"; + + first = false; + } + } + } + } + + void typeList (std::ostream &strm, paramListT *pListp, bool first = true) + { + if (pListp) + { + for (paramListT::const_iterator iter = pListp->begin() + ; iter != pListp->end() + ; ++iter) + { + if (iter->get()->type.get()) + { + if (!first) + { + strm << ", "; + } + + strm << *iter->get()->type; + + first = false; + } + } + } + } +} + +namespace clamp +{ + //////////////////////////////////////////////////////////////////////// + // Constructors + //////////////////////////////////////////////////////////////////////// + + CodeGen::CodeGen () + : mStack () + , mLambdaCount (0) + , mImplStream ("lambda_impl.clamp_h") + , mLambdaMap () + , mGeneratorStream () + { + } + + CodeGen::LambdaContext::LambdaContext (FILE *f + , int b + , std::auto_ptr<lambdaT> lamp) + : mPrevFile (f) + , mOpenBracePos (b) + , mLamp (lamp.release()) + , mLambdaNumber (++sContextCount) + { + } + + CodeGen::LambdaGroup::LambdaGroup () + : mLambdaList () + , mImplStream (new stringstream) + { + } + + void implTemplateName (ostream &strm, int ccount, int pcount) + { + strm + << "lambda_template_" + << ccount + << "_" + << pcount; + } + + void tList (ostream &strm, int start, int end, bool first = true) + { + for (int count = start; count <= end; ++count) + { + if (!first) + { + strm << ", "; + } + + strm << "T" << count; + + first = false; + } + } + + void implFunctionVar (ostream &strm, int ccount, int pcount, const char *n) + { + strm << "T1 ("; + + if (ccount > 0) + { + // Implementation via pointer to member function + implTemplateName (strm, ccount, pcount); + strm << "::"; + } + // else implementation via pointer to ordinary function + + strm << "*" << n << ") ("; + tList (strm, 2 + ccount, 1 + ccount + pcount); + strm << ")"; + } + + void implInstance (ostream &strm, lambdaT const &lam) + { + unsigned ccount = count (lam.context.get()); + unsigned pcount = count (lam.params.get()); + + implTemplateName (strm, ccount, pcount); + + strm + << "<" + << *lam.ret_type; + + typeList (strm, lam.context.get(), false); + typeList (strm, lam.params.get(), false); + + strm << "> "; + } + + std::auto_ptr<stringT> CodeGen::lambdaTypeName (std::auto_ptr<lambdaT> lamp) + { + lambdaGroup (count (lamp->context.get()), count (lamp->params.get())); + // Make sure we've recorded the existance of this lambda group + + std::ostringstream temp; + + implInstance (temp, *lamp); + + return std::auto_ptr<stringT> (new stringT (temp.str())); + } + + void CodeGen::lambdaType (FILE *outFile, std::auto_ptr<lambdaT> lamp) + { + fprintf (outFile, "%s", lambdaTypeName (lamp)->c_str()); + } + + bool CodeGen::braceMatch (int pos) + { + return (!mStack.empty()) && (mStack.top().mOpenBracePos == pos); + } + + std::string contextVarExpression (paramT const &ctxParam) + { + std::stringstream result; + + result << "mContext" << ctxParam.ctx_param_num; + + return result.str(); + } + + int CodeGen::LambdaContext::sContextCount = 0; + + stringT bodyFileName (int count) + { + char name[PATH_MAX]; + sprintf (name, "lambda_body_%d.clamp_h", count); + return stringT (name); + } + + void explicitConstructor (ostream &strm, int id, const lambdaT &lam) + { + if (lam.onHeap) + { + strm << "new "; + } + + implInstance (strm, lam); + strm << "(&"; + implInstance (strm, lam); + strm << "::fn" << id; + initList (strm, lam.context.get(), false); + strm << ")"; + } + + void typenameList (ostream &strm + , unsigned start + , unsigned end + , bool first = true) + { + for (unsigned count = start; count <= end; ++count) + { + if (!first) + { + strm << ", "; + } + + strm << "typename T" << count; + + first = false; + } + } + + void implTemplateDecl (ostream &strm, unsigned templateParams) + { + strm + << "template <"; + + typenameList (strm, 1, templateParams); + + strm << ">"; + } + + void startExplicitImpl (ostream &strm, unsigned ccount, unsigned pcount) + { + implTemplateDecl (strm, ccount + pcount + 1); + + strm << "\nstruct "; + + implTemplateName (strm, ccount, pcount); + + strm << "\n{\n "; + + implFunctionVar (strm, ccount, pcount, "mFn"); + + strm << ";"; + + for (unsigned count = 1; count <= ccount; ++count) + { + strm << "\n T" << count + 1 << " mContext" << count << ";"; + } + + strm << "\n\n typedef T1 result_type;"; + + for (unsigned count = 1; count <= ccount; ++count) + { + strm + << "\n typedef T" << count + 1 + << " context_type_" << count + << ";"; + } + + for (unsigned count = 1; count <= pcount; ++count) + { + strm + << "\n typedef T" << count + ccount + 1 + << " argument_type_" << count + << ";"; + } + + // Additional typedefs in special cases for standard binder compatability + if (pcount == 1) + { + strm + << "\n typedef T" << ccount + 2 + << " argument_type;"; + } + + else if (pcount == 2) + { + strm + << "\n typedef T" << ccount + 2 + << " first_argument_type;\n typedef T" << ccount + 3 + << " second_argument_type;"; + } + + strm << "\n\n // Constructor\n "; + + implTemplateName (strm, ccount, pcount); + + strm << " ("; + + implFunctionVar (strm, ccount, pcount, "fn"); + + for (unsigned count = 1; count <= ccount; ++count) + { + strm << ", T" << count + 1 << " c" << count; + } + + strm << ")\n : mFn (fn)"; + + for (unsigned count = 1; count <= ccount; ++count) + { + strm << "\n , mContext" << count << " (c" << count << ")"; + } + + strm + << "\n { }\n" + << "\n // Forwarding function" + << "\n T1 operator() ("; + + for (unsigned count = 1; count <= pcount; ++count) + { + if (count != 1) + { + strm << ", "; + } + + strm << "T" << count + ccount + 1 << " p" << count; + } + + strm << ")\n {\n return ("; + + if (ccount > 0) + { + // Have closure parameters - use pointer to member syntax + strm << "this->"; + } + // else static function + + strm << "*mFn)("; + + for (unsigned count = 1; count <= pcount; ++count) + { + if (count != 1) + { + strm << ", "; + } + + strm << "p" << count; + } + + strm << ");\n }\n"; + } + + void declareMemberFn (ostream &strm + , int id + , unsigned ccount + , unsigned pcount) + { + strm << "\n "; + + if (ccount == 0) + { + strm << "static "; + } + + strm << "T1 fn" << id << " ("; + + tList (strm, 2 + ccount, 1 + ccount + pcount); + + strm << ");\n"; + } + + void defineMemberFn (ostream &strm + , int id + , unsigned ccount + , unsigned pcount + , const lambdaT &lam) + { + implTemplateDecl (strm, ccount + pcount + 1); + + strm << "\nT1 "; + + implTemplateName (strm, ccount, pcount); + + strm << "<"; + + tList (strm, 1, 1 + ccount + pcount); + + strm << ">::fn" << id << " ("; + + if (lam.params.get()) + { + unsigned count = 1; + + for (paramListT::const_iterator iter = lam.params->begin() + ; iter != lam.params->end() + ; ++iter) + { + if (count != 1) + { + strm << ", "; + } + + strm << "T" << count + ccount + 1; + + const stringT *name = iter->get()->name.get(); + + if (name) + { + strm + << " " << *name; + } + + ++count; + } + } + + strm << ")\n{"; + + if (lam.explicitContext && lam.context.get()) + { + // Context parameters require renaming + unsigned count = 1; + + for (paramListT::const_iterator iter = lam.context->begin() + ; iter != lam.context->end() + ; ++iter) + { + const stringT *name = iter->get()->name.get(); + + if (name) + { + strm + << "\n#define " << *name + << " mContext" + << count; + } + + ++count; + } + } + + strm + << "\n#include \"" + << bodyFileName (id) + << "\""; + + if (lam.explicitContext && lam.context.get()) + { + unsigned count = 1; + + for (paramListT::const_iterator iter = lam.context->begin() + ; iter != lam.context->end() + ; ++iter) + { + const stringT *name = iter->get()->name.get(); + + if (name) + { + strm + << "\n#undef " << *name; + } + + ++count; + } + } + + strm << "\n}\n"; + } + + void implicitConstructor (ostream &strm, int id, const lambdaT &lam) + { + strm + << "lambda_generator_" + << id + << "<" + << *lam.ret_type; + + typeList (strm, lam.params.get(), false); + + strm << ">::generate ("; + + initList (strm, lam.context.get()); + + strm <<")"; + } + + void implicitTemplateInstance (ostream &strm + , const lambdaT &lam + , unsigned ccount + , unsigned pcount) + { + implTemplateName (strm, ccount, pcount); + + strm << " <T1"; + + if (ccount) + { + paramListT::const_iterator iter = lam.context->begin(); + + for (unsigned count = 1; count <= ccount; ++count) + { + strm << ", T" << count + 1; + + if ((*iter)->byReference) + { + strm << " &"; + } + + ++iter; + } + } + + tList (strm, 2 + ccount, 1 + ccount + pcount, false); + + strm << ">"; + } + + void writeGenerator (ostream &strm, int id, const lambdaT &lam) + { + unsigned ccount = count (lam.context.get()); + unsigned pcount = count (lam.params.get()); + + strm << "\ntemplate <"; + + typenameList (strm, 1, 1); + typenameList (strm, 2 + ccount, 1 + ccount + pcount, false); + + strm + << ">\nstruct lambda_generator_" << id + << "\n{"; + + if (ccount >= 1) + { + strm << "\n template <"; + + typenameList (strm, 2, 1 + ccount); + + strm << ">"; + } + + strm << "\n static "; + + implicitTemplateInstance (strm, lam, ccount, pcount); + + if (lam.onHeap) + { + strm << " *"; + } + + strm << "\n generate ("; + + if (ccount) + { + paramListT::const_iterator iter = lam.context->begin(); + + for (unsigned count = 1; count <= ccount; ++count) + { + if (count != 1) + { + strm << ", "; + } + + strm << "T" << count + 1 << " "; + + if ((*iter)->byReference) + { + strm << "&"; // Accept parameter by reference + } + + strm << "p" << count; + + ++iter; + } + } + + strm << ")\n {\n return "; + + if (lam.onHeap) + { + strm << "new "; + } + + implicitTemplateInstance (strm, lam, ccount, pcount); + + strm << " (&"; + implicitTemplateInstance (strm, lam, ccount, pcount); + strm << "::fn" << id; + + if (ccount) + { + unsigned count = 0; + + for (paramListT::const_iterator iter = lam.context->begin() + ; iter != lam.context->end() + ; ++iter) + { + ++count; + + strm << ", " << "p" << count; + } + } + + strm << ");\n }\n};\n"; + } + + struct MatchInitialiser + { + const stringT &mTarget; + bool mByRef; + + MatchInitialiser (const stringT &target + , bool byRef) + : mTarget (target) + , mByRef (byRef) + { + } + + bool operator() (const boost::shared_ptr<paramT> &pp) + { + return (mTarget == (*pp->initialiser)) && (mByRef == pp->byReference); + } + }; + + bool CodeGen::contextRef (FILE *outFile + , std::auto_ptr<stringT> strp + , bool byRef) + { + // Handles context by value and by reference + + lambdaT &lam (*mStack.top().mLamp); + + if (lam.explicitContext) + { + cerr + << "__ctx or __ref expression in lambda with explicit context\n"; + + return false; + } + + if (!lam.context.get()) + { + lam.context.reset (new paramListT); + } + + paramListT &context (*lam.context); + + paramListT::iterator param; + + param = std::find_if (context.begin() + , context.end() + , MatchInitialiser (*strp, byRef)); + + if (param == context.end()) + { + int ccount = context.size() + 1; + + char newName[128]; + + sprintf (newName, "mContext%d", ccount); + + char pseudoType[128]; + + sprintf (pseudoType, "T%d", ccount); + + boost::shared_ptr<paramT> + newParamPtr (new paramT (makestr(pseudoType) + , makestr (newName) + , strp.release() + , ccount + , byRef)); + + context.push_back (newParamPtr); + + param = context.end(); + --param; + } + + fprintf (outFile, "%s", contextVarExpression (**param).c_str()); + + return true; + } + + bool CodeGen::startLambda (FILE *&f + , int openBracePos + , std::auto_ptr<lambdaT> lamp) + { + mStack.push (LambdaContext (f, openBracePos, lamp)); + + string newName (bodyFileName (++mLambdaCount)); + + f = fopen (newName.c_str(), "w+"); + + if (!f) + { + cerr + << "Failed to create new body file " + << newName + << "\n"; + + f = mStack.top().mPrevFile; + mStack.pop (); + + return false; + } + + return true; + } + + CodeGen::LambdaMap::iterator CodeGen::lambdaGroup (int ccount, int pcount) + { + LambdaType typeId (ccount, pcount); + + LambdaMap::iterator mapIter = mLambdaMap.find (typeId); + + if (mapIter == mLambdaMap.end()) + { + pair<LambdaMap::iterator, bool> inserted + = mLambdaMap.insert (std::make_pair (typeId, LambdaGroup())); + + assert (inserted.second); + + mapIter = inserted.first; + + startExplicitImpl (*mapIter->second.mImplStream, ccount, pcount); + } + + return mapIter; + } + + bool CodeGen::endLambda (FILE *&f) + { + fprintf (f, "\n"); // Ensure newline termination + fclose (f); + f = mStack.top().mPrevFile; + + LambdaContext &ctx (mStack.top()); + + int ccount = count (ctx.mLamp->context.get()); + int pcount = count (ctx.mLamp->params.get()); + + LambdaMap::iterator mapIter = lambdaGroup (ccount, pcount); + + mapIter->second.mLambdaList.push_back (ctx); + + declareMemberFn (*mapIter->second.mImplStream + , ctx.mLambdaNumber + , ccount + , pcount); + + std::ostringstream temp; + + if (ctx.mLamp->explicitContext) + { + explicitConstructor (temp, ctx.mLambdaNumber, *ctx.mLamp); + } + + else + { + writeGenerator (mGeneratorStream, ctx.mLambdaNumber, *ctx.mLamp); + implicitConstructor (temp, ctx.mLambdaNumber, *ctx.mLamp); + } + + fprintf (f, "%s", temp.str().c_str()); + + mStack.pop(); + return true; + } + + void CodeGen::spitItOut () + { + mImplStream + << "//" + << "\n// clamp generated lambda templates" + << "\n// parser " << clamp_parser_rcsid + << "\n// code generator " << clamp_codegen_rcsid + << "\n//\n\n" + ; + + for (LambdaMap::const_iterator iter = mLambdaMap.begin() + ; iter != mLambdaMap.end() + ; ++iter) + { + mImplStream + << iter->second.mImplStream->rdbuf() + << "\nprivate:\n "; + + // Make the assignment operator private, since it wouldn't + // handle any reference member variables + + implTemplateName (mImplStream, iter->first.first, iter->first.second); + + mImplStream << " operator= ("; + + implTemplateName (mImplStream, iter->first.first, iter->first.second); + + mImplStream + << " const &);\n" + << "};\n"; + } + + mImplStream << "\n" << mGeneratorStream.str() << "\n"; + + for (LambdaMap::const_iterator group = mLambdaMap.begin() + ; group != mLambdaMap.end() + ; ++group) + { + const LambdaList &list (group->second.mLambdaList); + + for (LambdaList::const_iterator iter = list.begin() + ; iter != list.end() + ; ++iter) + { + defineMemberFn (mImplStream + , iter->mLambdaNumber + , group->first.first + , group->first.second + , *iter->mLamp); + } + } + } +} Added: clamp/trunk/src/CodeGen.hh =================================================================== --- clamp/trunk/src/CodeGen.hh (rev 0) +++ clamp/trunk/src/CodeGen.hh 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,110 @@ +// -*- mode:c++ -*- +// +// Header file CodeGen.hh +// +// Copyright (c) 2002 Raoul M. Gough +// +// This material is provided "as is", with absolutely no warranty expressed +// or implied. Any use is at your own risk. +// +// Permission to use or copy this software for any purpose is hereby granted +// without fee, provided the above notices are retained on all copies. +// Permission to modify the code and to distribute modified code is granted, +// provided the above notices are retained, and a notice that the code was +// modified is included with the above copyright notice. +// +// History +// ======= +// 2002/ 2/11 rmg File creation +// +// version: $Id: CodeGen.hh,v 1.9 2003/09/30 22:42:56 Raoul Exp $ +// + +#ifndef CodeGen_rmg_20020211_included +#define CodeGen_rmg_20020211_included + +#include "clamp_support.hh" + +#include <stdio.h> +#include <stack> +#include <memory> +#include <fstream> +#include <map> +#include <sstream> +#include "boost/smart_ptr.hpp" + +namespace clamp +{ + class CodeGen + { + public: + CodeGen (); + + public: + void lambdaType (FILE *, std::auto_ptr<lambdaT>); + std::auto_ptr<stringT> lambdaTypeName (std::auto_ptr<lambdaT>); + + public: + bool braceMatch (int pos); + bool startLambda (FILE *&, int openBracePos, std::auto_ptr<lambdaT>); + bool endLambda (FILE *&); + + public: + bool contextRef (FILE *, std::auto_ptr<stringT>, bool byRef = false); + + public: + void spitItOut (); + + private: + struct LambdaContext { + FILE *mPrevFile; + int mOpenBracePos; + boost::shared_ptr<lambdaT> mLamp; + int mLambdaNumber; + + static int sContextCount; + + LambdaContext (FILE *, int, std::auto_ptr<lambdaT>); + }; + + private: + std::stack<LambdaContext> mStack; + + private: + int mLambdaCount; + + private: + std::ofstream mImplStream; + + private: + // + // Store lambda expressions for deferred processing, grouping + // by context and parameter list size (i.e. ccount and pcount) + // + typedef std::pair<unsigned, unsigned> LambdaType; + typedef std::list<LambdaContext> LambdaList; + + struct LambdaGroup + { + // Lambda functions that share the same implementation template + LambdaList mLambdaList; + boost::shared_ptr<std::stringstream> mImplStream; + + LambdaGroup (); + }; + + typedef std::map<LambdaType, LambdaGroup> LambdaMap; + + LambdaMap mLambdaMap; + + private: + std::ostringstream mGeneratorStream; + + private: + LambdaMap::iterator lambdaGroup (int ccount, int pcount); + // Get the lambda group for the given number of parameters (starting + // a new group if necessary) + }; +} + +#endif // CodeGen_rmg_20020211_included Added: clamp/trunk/src/Makefile =================================================================== --- clamp/trunk/src/Makefile (rev 0) +++ clamp/trunk/src/Makefile 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,70 @@ +# -*- mode:makefile -*- +# +# GNU Makefile for clamp +# +# Copyright (c) 2002, 2003 Raoul M. Gough +# +# This material is provided "as is", with absolutely no warranty expressed +# or implied. Any use is at your own risk. +# +# Permission to use or copy this software for any purpose is hereby granted +# without fee, provided the above notices are retained on all copies. +# Permission to modify the code and to distribute modified code is granted, +# provided the above notices are retained, and a notice that the code was +# modified is included with the above copyright notice. +# +# History +# ======= +# 2002/ 2/ 6 rmg File creation +# +# version: $Id: Makefile,v 1.16.1.4 2003/09/30 22:10:19 Raoul Exp $ +# + +all: clamp test eg curry + +# +# You might have to uncomment and adjust some of the following bits and +# pieces, depending on your set-up: CXX, CC, LEX and -I ...boost... +# + +LEX := flex + +CXXFLAGS = -g -Wall -Wno-unused -I d:/CVS/boost/boost +# Use -Wno-unused because lex.yy.c contains some unused labels and functions + +LFLAGS = +YFLAGS = -v -d + +LDLIBS = -lstdc++ + +clamp.tab.h: clamp.cc + mv y.tab.h clamp.tab.h + +lex.yy.cc: clamplex.lex clamp.tab.h + $(LEX) $(LFLAGS) clamplex.lex + mv lex.yy.c lex.yy.cc + +clamplex.o: lex.yy.cc clamp.tab.h clamp_support.hh + $(COMPILE.cc) lex.yy.cc -o clamplex.o + +clamp_support.o: clamp_support.cc clamp_support.hh + +clamplex: clamplex.o + $(LINK.c) -o clamplex $? + +clamp.cc: clamp.y + $(YACC.y) $? + mv -f y.tab.c clamp.cc + +clamp.o: clamp.cc clamp_support.hh clamplex.h CodeGen.hh + +clamp: LDLIBS := $(LDLIBS) -lfl +clamp: clamp.o clamplex.o clamp_support.o CodeGen.o + +clean: + -rm *.o *.exe clamp.cc y.output clamp.tab.h lex.yy.cc lambda*.clamp_h + +.PRECIOUS: %.cc + +%.cc: %.clamp clamp + ./clamp <$< >$@ Added: clamp/trunk/src/clamp.y =================================================================== --- clamp/trunk/src/clamp.y (rev 0) +++ clamp/trunk/src/clamp.y 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,410 @@ +/* -*- mode:c -*- + * + * Bison module clamp.y + * + * Copyright (c) 2002, 2003 Raoul M. Gough + * + * This material is provided "as is", with absolutely no warranty expressed + * or implied. Any use is at your own risk. + * + * Permission to use or copy this software for any purpose is hereby granted + * without fee, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + * History + * ======= + * 2002/ 2/ 7 rmg File creation + * + * $Id: clamp.y,v 1.31 2003/09/30 22:06:25 Raoul Exp $ + */ + +%{ +#define YYDEBUG 1 + +#include "clamp_support.hh" +#include "clamplex.h" +#include "CodeGen.hh" + +#include <iostream> +#include <stdio.h> +#include <malloc.h> +#include <set> + + using namespace clamp; + + CodeGen *gGenPtr = 0; + + extern FILE *yyin; + + const char *clamp_parser_rcsid = "$Id: clamp.y,v 1.31 2003/09/30 22:06:25 Raoul Exp $"; + + %} + +%union { + int tokval; + stringT *strval; + paramListT *plist; + lambdaT *lambda; + bool flag; +} + +%token <tokval> TOK_LAMBDA +%token <tokval> TOK_NEW_LAMBDA +%token <tokval> TOK_CONTEXT +%token <tokval> TOK_CONTEXT_REF +%token <tokval> TOK_GENERIC +%token <tokval> TOK_WHITESPACE +%token <tokval> TOK_SCOPE + +%token <tokval> TOK_TYPE_KEYWORD +%token <tokval> TOK_TYPENAME +%token <tokval> TOK_CV_QUAL + +%type <strval> name genericexpr genericexpropt genericid simple_generic +%type <strval> typeid typeidopt basictype cvqualopt typename +%type <strval> name_opt indirect_sym +%type <plist> decls decl_list decl +%type <lambda> lambda_start lambda_type +%type <flag> ctxorref +/* no type for context, statements, lambda_def_start, lambda */ + +%expect 5 + +%% + +input: /* empty */ +| input lambda +; + +lambda: lambda_type { + gGenPtr->lambdaType (yyout, std::auto_ptr<lambdaT>($1)); + + // We read a lookahead token in lambda mode, and it wasn't + // a left brace - put the char back and let the lexer reprocess + // it in the INITIAL start condition + resume_initial = 1; + yyclearin; + lexer_reprocess_last (); +} +| lambda_def_start statements '}' { + if (!gGenPtr->endLambda (yyout)) + { + YYABORT; + } +} +; + +lambda_def_start: lambda_type '{' { + resume_initial = 1; + + if (!gGenPtr->startLambda (yyout, openbraces, std::auto_ptr<lambdaT>($1))) + { + YYABORT; + } +} +; + +lambda_type: lambda_start + | lambda_start '(' decls ')' { + if (plistInitialisers ($3)) + { + yywarning ("default parameters ignored"); + } + + $$ = shiftlambda ($1, $3); // Adjust to explicit-context lambda + } +; + +lambda_start: TOK_LAMBDA typeidopt '(' decls ')' { + $$ = makelambda (0, $2, 0, $4); // Assume implicit context variant +} +| TOK_NEW_LAMBDA typeidopt '(' decls ')' { + $$ = makelambda (0, $2, 0, $4, true); // Assume implicit context variant +} +; + +decls: /* empty */ { $$ = 0; } + | decl_list +; + +decl_list: decl + | decl_list ',' decl { + $$ = appendplist ($1, $3); +} +; + +decl: typeid name_opt { + $$ = makeplist ($1, $2, 0); +} + | typeid name_opt '=' genericexpr { + $$ = makeplist ($1, $2, $4); +} +; + +typeidopt: /* empty */ { $$ = makestr ("void"); } +| typeid +; + +typeid: cvqualopt basictype { $$ = appendstr ($1, $2); } +| typeid cvqualopt indirect_sym cvqualopt { $$ = appendstr ($1, $2, $3, $4);} +| cvqualopt genericid cvqualopt { $$ = appendstr ($1, $2, $3); } +| typename genericid { $$ = appendstr ($1, $2); } +| lambda_type { + $$ = gGenPtr->lambdaTypeName (std::auto_ptr<lambdaT>($1)).release(); +} +; + +indirect_sym: '*' { $$ = makestr (yytext); } +| '&' { $$ = makestr (yytext); } +; + +basictype: TOK_TYPE_KEYWORD { $$ = makestr (yytext); } +| basictype TOK_TYPE_KEYWORD { $$ = appendstr ($1, makestr (yytext)); } +; + +cvqualopt: /* empty */ { $$ = 0; } +| cvqualopt TOK_CV_QUAL { $$ = appendstr ($1, makestr (yytext)); } +; + +typename: TOK_TYPENAME { $$ = makestr (yytext); }; + +name_opt: /* empty */ { $$ = 0; } +| name +; + +name: TOK_GENERIC { $$ = makestr (yytext); } +; + +genericid: simple_generic { $$ = $1; } +| simple_generic TOK_SCOPE simple_generic { + $$ = appendstr ($1, makestr ("::"), $3); +} +; + +simple_generic: TOK_GENERIC { $$ = makestr (yytext); } +; + +statements: /* empty */ +| statements context +| statements lambda +; + +context: ctxorref '(' genericexpr ')' { + if (!gGenPtr->contextRef (yyout, std::auto_ptr<stringT> ($3), $1)) + { + YYABORT; + } + + resume_initial = 1; +} +; + +ctxorref: TOK_CONTEXT { $$ = false; } +| TOK_CONTEXT_REF { $$ = true; } +; + +genericexpr: TOK_GENERIC { $$ = makestr (yytext); } +| genericexpropt '(' genericexpropt ')' genericexpropt { + $$ = appendstr ($1, makestr ("("), $3, makestr (")"), $5); +} +| indirect_sym genericexpropt { $$ = appendstr ($1, $2); } +/* + Note - indirect_sym should actually require a genericexpr + (i.e. it's not optional). Unfortunately, that creates a + reduce/reduce conflict, since the parser can reduce the "X" + in "indirect_sym X" with either genericexpr or genericexpropt +*/ +; + +genericexpropt: { $$ = 0; } + | genericexpr +; + +%% + +namespace +{ + struct BlockInfo + { + BlockInfo *prev; + BlockInfo *next; + void *caller; + std::size_t size; + }; + + struct Stats + { + std::size_t blocks; + std::size_t bytes; + }; + + Stats gAlloc = {0}; + Stats gDealloc = {0}; + + BlockInfo *first = 0; +} + +#ifdef TRACK_MEMORY +void *operator new (std::size_t size) throw (std::bad_alloc) +{ + ++gAlloc.blocks; + gAlloc.bytes += size; + + BlockInfo *myPtr + = static_cast<BlockInfo *> (malloc (size + sizeof(*myPtr))); + + if (first) + { + first->prev = myPtr; + } + + myPtr->next = first; + myPtr->prev = 0; + myPtr->caller = __builtin_return_address (1); + first = myPtr; + + myPtr->size = size; + + return myPtr + 1; +} + +void operator delete (void *ptr) throw () +{ + if (ptr) + { + BlockInfo *myPtr = static_cast<BlockInfo *> (ptr); + --myPtr; + + ++gDealloc.blocks; + gDealloc.bytes += myPtr->size; + + if (myPtr->next) + { + myPtr->next->prev = myPtr->prev; + } + + if (myPtr->prev) + { + myPtr->prev->next = myPtr->next; + } + + else + { + first = myPtr->next; + } + + free (myPtr); + } +} + +void *operator new[] (std::size_t size) throw (std::bad_alloc) +{ + return operator new (size); +} + +void operator delete[] (void *ptr) throw () +{ + return operator delete (ptr); +} +#endif // TRACK_MEMORY + +extern "C" { + int yyerror (const char *s) + { + fflush (yyout); + fflush (stdout); + + fprintf (stderr + , "\nclamp: %s on line %d with token %s\n" + , s + , yylineno + , yytext); + + return 0; + } + + int yywarning (const char *s) + { + fflush (yyout); + fflush (stdout); + + fprintf (stderr + , "clamp: %s on line %d\n" + , s + , yylineno); + + return 0; + } +} + +bool parserBraceMatch (int pos) +{ + return gGenPtr->braceMatch (pos); +} + +int main (int argc, char *argv[]) +{ + int result; + + if (argc > 1) + { + yyin = fopen (argv[1], "r"); + + if (!yyin) + { + perror ("fopen"); + + return 1; + } + + ++argv; + --argc; + } + + yydebug = argc - 1; + + printf ("#include \"lambda_impl.clamp_h\"\n"); + + gGenPtr = new CodeGen; + + result = yyparse(); + + if (result == 0) + { + gGenPtr->spitItOut (); + } + + else + { + fprintf (stderr, "yyparse returned %d\n", result); + } + + delete gGenPtr; + + if (gAlloc.blocks != gDealloc.blocks) + { + using namespace std; + + fprintf (stderr + , "Memory leak detected. Dumping still allocated blocks:\n"); + + fflush (stderr); + + BlockInfo *scan = first; + + while (scan) + { + std::cerr + << "Address " << static_cast<void *>(scan) + << " size " << scan->size + << " caller " << scan->caller + << "\n"; + + scan = scan->next; + } + } + + return result; +} Added: clamp/trunk/src/clamp_support.cc =================================================================== --- clamp/trunk/src/clamp_support.cc (rev 0) +++ clamp/trunk/src/clamp_support.cc 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,241 @@ +// -*- mode:c++ -*- +// +// Module clamp_support.cc +// +// Copyright (c) 2002 Raoul M. Gough +// +// This material is provided "as is", with absolutely no warranty expressed +// or implied. Any use is at your own risk. +// +// Permission to use or copy this software for non-commercial purposes +// is hereby granted without fee, provided the above notices are +// retained on all copies. Permission to modify the code and to +// distribute modified code is granted, provided the above notices are +// retained, and a notice that the code was modified is included with +// the above copyright notice. +// +// History +// ======= +// 2002/ 2/10 rmg File creation +// +// version: $Id: clamp_support.cc,v 1.11 2002/09/16 17:09:45 Raoul Exp $ +// + +#include "clamp_support.hh" +#include <iostream> +// #include <ostream> + +using namespace std; + +namespace clamp +{ + lambdaT::lambdaT () + : ret_type (0) + , context (0) + , params (0) + , explicitContext (false) + , onHeap (false) + { + } + + template<typename T> + void safeAssign (auto_ptr<T> &to, T *from, bool force = false) + { + if (from || force) + { + to.reset (from); + } + } + + lambdaT *makelambda (lambdaT *lamp + , stringT *typestr + , paramListT *ctx + , paramListT *params + , bool onh) + { + if (lamp == 0) + { + lamp = new lambdaT; + } + + safeAssign (lamp->ret_type, typestr); + safeAssign (lamp->context, ctx); + safeAssign (lamp->params, params); + lamp->onHeap = onh; + + return lamp; + } + + lambdaT *shiftlambda (lambdaT *lamp + , paramListT *params) + { + // Release should be safe because it is only called if lamp is + // already non-null, in which case makelambda guarantees no-throw + lambdaT *result + = makelambda (lamp, 0, lamp ? lamp->params.release() : 0, params); + + result->explicitContext = true; + + return result; + } + + paramListT *appendplist (paramListT *front, paramListT *back) + { + if (front) + { + if (back) + { + front->splice (front->end(), *back); + delete back; + } + } + + else if (back) + { + front = back; + } + + return front; + } + + paramListT *makeplist (stringT *type, stringT *name, stringT *i) + { + auto_ptr<paramListT> listp (new paramListT); + + listp->push_back (boost::shared_ptr<paramT> (new paramT (type, name, i))); + + return listp.release(); + } + + bool plistInitialisers (const paramListT *list) + { + bool foundInit = false; + + if (list) + { + for (paramListT::const_iterator iter = list->begin() + ; (iter != list->end()) && (!foundInit) + ; ++iter) + { + foundInit = (*iter)->initialiser.get(); + } + } + + return foundInit; + } + + stringT *appendstr (stringT *s1, stringT *s2) + { + if (s1) + { + if (s2) + { + s1->append (" "); + s1->append (*s2); + + delete s2; + } + } + + else if (s2) + { + s1 = s2; + } + + return s1; + } + + stringT *appendstr (stringT *s1, stringT *s2, stringT *s3) + { + return appendstr (appendstr (s1, s2), s3); + } + + stringT *appendstr (stringT *s1, stringT *s2, stringT *s3, stringT *s4) + { + return appendstr (appendstr (s1, s2, s3), s4); + } + + stringT *appendstr (stringT *s1 + , stringT *s2 + , stringT *s3 + , stringT *s4 + , stringT *s5) + { + return appendstr (appendstr (s1, s2, s3, s4), s5); + } + + stringT *makestr (const char *cstr) + { + if (cstr) + { + return new stringT (cstr); + } + + else + { + return 0; + } + } + + stringT *makestr (const char *cstr, int length) + { + if (cstr) + { + return new stringT (cstr, length); + } + + else + { + return 0; + } + } + + std::ostream &operator<< (std::ostream &strm, const lambdaT &lam) + { + strm + << "lambdaT returning " + << lam.ret_type.get() + << " from"; + + if (lam.explicitContext) + { + strm + << " context " + << lam.context.get() + << " and"; + } + + strm + << " params " + << lam.params.get(); + + return strm; + } + + std::ostream &operator<< (std::ostream &strm, const paramT &p) + { + return strm + << "(type " + << p.type.get() + << " with name " + << p.name.get() + << ")"; + } + + std::ostream &operator<< (std::ostream &strm, const paramListT &pList) + { + for (paramListT::const_iterator iter = pList.begin() + ; iter != pList.end() + ; ++iter) + { + if (iter != pList.begin()) + { + strm << ", "; + } + + strm << iter->get(); + } + + return strm; + } +} Added: clamp/trunk/src/clamp_support.hh =================================================================== --- clamp/trunk/src/clamp_support.hh (rev 0) +++ clamp/trunk/src/clamp_support.hh 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,116 @@ +// -*- mode:c++ -*- +// +// Header file clamp_support.hh +// +// Copyright (c) 2002, 2003 Raoul M. Gough +// +// This material is provided "as is", with absolutely no warranty expressed +// or implied. Any use is at your own risk. +// +// Permission to use or copy this software for any purpose is hereby granted +// without fee, provided the above notices are retained on all copies. +// Permission to modify the code and to distribute modified code is granted, +// provided the above notices are retained, and a notice that the code was +// modified is included with the above copyright notice. +// +// History +// ======= +// 2002/ 2/ 7 rmg File creation +// +// version: $Id: clamp_support.hh,v 1.14 2003/09/30 22:06:22 Raoul Exp $ +// + +#ifndef clamp_support_rmg_20020207_included +#define clamp_support_rmg_20020207_included + +#include <string> +#include <list> +#include <memory> +#include <iosfwd> +#include "boost/smart_ptr.hpp" + +namespace clamp +{ + typedef std::string stringT; + + struct paramT + { + boost::shared_ptr<stringT> type; + boost::shared_ptr<stringT> name; + boost::shared_ptr<stringT> initialiser; + int ctx_param_num; + bool byReference; + + paramT (stringT *t, stringT *n, stringT *i, int ctx = 0, bool ref = false) + : type (t) + , name (n) + , initialiser (i) + , ctx_param_num (ctx) + , byReference (ref) + { + } + }; + + typedef std::list<boost::shared_ptr<paramT> > paramListT; + + struct lambdaT + { + std::auto_ptr<stringT> ret_type; + std::auto_ptr<paramListT> context; + std::auto_ptr<paramListT> params; + bool explicitContext; + bool onHeap; + + lambdaT (); + }; + + lambdaT *makelambda (lambdaT *lamp + , stringT *typestr + , paramListT *ctx + , paramListT *params + , bool onHeap = false); + + // + // Convert an implicit-context lambda into an explicit-context version + // by shifting the misplaced params into the correct context slot + // and adding the given parameters + // + lambdaT *shiftlambda (lambdaT *lamp + , paramListT *params); + + paramListT *makeplist (stringT *type, stringT *name, stringT *init); + + paramListT *appendplist (paramListT *front, paramListT *back); + + // Check if the plist contains any initialisers + bool plistInitialisers (const paramListT *); + + stringT *makestr (const char *cstr); + stringT *makestr (const char *cstr, int length); + + stringT *appendstr (stringT *, stringT *); + stringT *appendstr (stringT *, stringT *, stringT *); + stringT *appendstr (stringT *, stringT *, stringT *, stringT *); + stringT *appendstr (stringT *, stringT *, stringT *, stringT *, stringT *); + + /* + template<typename T> + std::ostream &operator<< (std::ostream &strm, const T *tptr) + { + if (tptr) + { + return strm << *tptr; + } + + else + { + return strm << "(null)"; + } + } + */ + + std::ostream &operator<< (std::ostream &, const lambdaT &); + std::ostream &operator<< (std::ostream &, const paramListT &); +} + +#endif // clamp_support_rmg_20020207_included Added: clamp/trunk/src/clamplex.h =================================================================== --- clamp/trunk/src/clamplex.h (rev 0) +++ clamp/trunk/src/clamplex.h 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,40 @@ +/* -*- mode:c -*- + * + * Header file clamplex.h + * + * Copyright (c) 2002 Raoul M. Gough + * + * This material is provided "as is", with absolutely no warranty expressed + * or implied. Any use is at your own risk. + * + * Permission to use or copy this software for any purpose is hereby granted + * without fee, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + * History + * ======= + * 2002/ 2/10 rmg File creation + */ + +#ifndef clamplex_rmg_20020210_included +#define clamplex_rmg_20020210_included + +#include <stdio.h> + +extern int resume_initial; +extern int openbraces; +extern void lexer_reprocess_last (); + +extern "C" { + int yyerror (const char *); + int yywarning (const char *); + int yylex (); + + extern char *yytext; + extern FILE *yyout; + extern int yylineno; +} + +#endif // clamplex_rmg_20020210_included Added: clamp/trunk/src/clamplex.lex =================================================================== --- clamp/trunk/src/clamplex.lex (rev 0) +++ clamp/trunk/src/clamplex.lex 2009-02-23 02:47:54 UTC (rev 1224) @@ -0,0 +1,192 @@ +/* -*- mode:c -*- + * + * Flex module clamplex.lex + * + * Copyright (c) 2002 Raoul M. Gough + * + * This material is provided "as is", with absolutely no warranty expressed + * or implied. Any use is at your own risk. + * + * Permission to use or copy this software for any purpose is hereby granted + * without fee, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + * History + * ======= + * 2002/ 2/ 6 rmg File creation + * + * version: $Id: clamplex.lex,v 1.13 2002/11/18 17:04:00 Raoul Exp $ + */ + +%{ + +#include <stdio.h> +#include "clamp_support.hh" + + using namespace clamp; + +#include "clamp.tab.h" + + int resume_initial = 0; + + int openbraces = 0; + + extern "C" { int yylex (); } + + extern bool parserBraceMatch (int); +%} + +%option nomain + +%x stringlit +%x charlit +%x comment +%x lambda +%x lambda_def +%x context + +FSLASH \/ +BSLASH \\ +DQUOTE \" +SQUOTE \' +STAR \* +LBRACE \{ +RBRACE \} +COLON \: + +%option yylineno + +%% + if (resume_initial) + { + BEGIN (INITIAL); + resume_initial = 0; + } + +<INITIAL>{ + {FSLASH}{FSLASH}.*\n ECHO; + + {DQUOTE} { + ECHO; + BEGIN(stringlit); + } + + {SQUOTE} { + ECHO; + BEGIN(charlit); + } + + {FSLASH}{STAR} { + ECHO; + BEGIN(comment); + } + + new[ \t\n][ \t\n]*lambda { + BEGIN(lambda); + return TOK_NEW_LAMBDA; + } + + lambda { + BEGIN(lambda); + return TOK_LAMBDA; + } + + __ctx[ \t\n]* { + BEGIN (context); + return TOK_CONTEXT; + } + + __ref[ \t\n]* { + BEGIN (context); + return TOK_CONTEXT_REF; + } + + {LBRACE} { + ECHO; + ++openbraces; + } + + {RBRACE} { + if (parserBraceMatch (openbraces--)) + { + return '}'; + } + + else + { + ECHO; + } + } +} + +<stringlit>{ + [^\"\\]* ECHO; + {BSLASH}. ECHO; + {DQUOTE} { + ECHO; + BEGIN(INITIAL); + } +} + +<charlit>{ + [^\'\\]* ECHO; + {BSLASH}. ECHO; + {SQUOTE} { + ECHO; + BEGIN(INITIAL); + } +} + +<comment>{ + {STAR}{FSLASH} { + ECHO; + BEGIN(INITIAL); + } +} + +<lambda>{ + const | + volatile return TOK_CV_QUAL; + + char | + int | + short | + long | + signed | + unsigned | + float | + double return TOK_TYPE_KEYWORD; + + typename return TOK_TYPENAME; + + lambda return TOK_LAMBDA; + + [^()*&,{}= \t\n]* return TOK_GENERIC; + + [ \t\n]* /* ignore whitespace */ + + {LBRACE} { + ++openbraces; + return yytext[... [truncated message content] |
From: <yan...@us...> - 2009-02-22 23:22:11
|
Revision: 1223 http://assorted.svn.sourceforge.net/assorted/?rev=1223&view=rev Author: yangzhang Date: 2009-02-22 22:10:27 +0000 (Sun, 22 Feb 2009) Log Message: ----------- added demo of htons conversion weirdness Added Paths: ----------- sandbox/trunk/src/cc/htons_conversion.cc Added: sandbox/trunk/src/cc/htons_conversion.cc =================================================================== --- sandbox/trunk/src/cc/htons_conversion.cc (rev 0) +++ sandbox/trunk/src/cc/htons_conversion.cc 2009-02-22 22:10:27 UTC (rev 1223) @@ -0,0 +1,13 @@ +// Demo of htons conversion weirdness. +// +// $ g++ conversion_weirdness.cc -O3 -Wconversion +// conversion_weirdness.cc: In function ‘int main()’: +// conversion_weirdness.cc:4: warning: conversion to ‘short unsigned int’ from ‘int’ may alter its value + +#include <arpa/inet.h> +int main() { + sockaddr_in sa; + unsigned short x = (unsigned short) htons((unsigned short)3); + sa.sin_port = x; + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-22 19:46:23
|
Revision: 1222 http://assorted.svn.sourceforge.net/assorted/?rev=1222&view=rev Author: yangzhang Date: 2009-02-22 19:46:08 +0000 (Sun, 22 Feb 2009) Log Message: ----------- - removed is_interactive - moved CPATH into C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH - made reattach also try to start a screen if no 'main' already available - added rel() to reload X configurations - added pushx() to store X configurations - added zww() for generic warnings - added zccw() for gcc + warnings - added more warnings to zppw() - removed `trash` Modified Paths: -------------- shell-tools/trunk/README shell-tools/trunk/src/bash-commons/bashrc.bash Modified: shell-tools/trunk/README =================================================================== --- shell-tools/trunk/README 2009-02-22 07:45:59 UTC (rev 1221) +++ shell-tools/trunk/README 2009-02-22 19:46:08 UTC (rev 1222) @@ -86,9 +86,6 @@ Useful for debugging programs that export environment variables to subprocesses. -`trash` Move files to a trash directory and group the bash - trashed files by their removal time. - `unison-merge` A frontend over unison to make conflict bash resolutions sane. Modified: shell-tools/trunk/src/bash-commons/bashrc.bash =================================================================== --- shell-tools/trunk/src/bash-commons/bashrc.bash 2009-02-22 07:45:59 UTC (rev 1221) +++ shell-tools/trunk/src/bash-commons/bashrc.bash 2009-02-22 19:46:08 UTC (rev 1222) @@ -44,8 +44,6 @@ # TODO move all interactive-only code to .bash_profile? or was it login? ( i # think latter ) -is_interactive="$PS1" - # Back up or restore vars. function reset_var { local var="$1" orig="ORIG_$var" @@ -125,11 +123,12 @@ # - LIBRARY_PATH is for gcc (static linking) prepend_std LD_LIBRARY_PATH lib /usr/local/lib prepend_std LIBRARY_PATH lib -# CPATH applies across all gcc languages; see also: -# - C_INCLUDE_PATH -# - CPLUS_INCLUDE_PATH -# - OBJC_INCLUDE_PATH -prepend_std CPATH include +# Don't use CPATH for general system headers, since that gets treated as -I +# instead of -isystem. +prepend_var CPATH $HOME/.local/pkg/cpp-commons/include:/opt/cpp-commons/include +prepend_std C_INCLUDE_PATH include +prepend_std CPLUS_INCLUDE_PATH include +prepend_std OBJC_INCLUDE_PATH include # bash @@ -606,18 +605,34 @@ find "${2:-.}" -name "$1" } -reattach() { - screen -d -r main -} - +# reattach rea() { - reattach + if ! screen -d -r main + then screen -S main + fi } +# reload configs rel() { . ~/.bashrc + if [[ -f ~/.xsessinfo/bash ]] + then . ~/.xsessinfo/bash + fi } +# push new x config to .sessinfo and to screen +pushx() { + mkdir -p ~/.xsessinfo/ + export | + egrep '^declare -x (SESSION_MANAGER|DISPLAY|DBUS_SESSION_BUS_ADDRESS)=' | + # for some reason, declare -x doesn't affect the "parent shell" even when + # sourced, so change that to export, which works. + sed 's/declare -x /export /' | + tee ~/.xsessinfo/bash | + perl -pe 's/export (\w+)=/screen -S main -X setenv $1 /g' | + bash +} + zcc() { local file="$1" shift @@ -630,14 +645,58 @@ ${WTF-wtf} g++ -Wall -g3 -o "${file%.*}" "$file" "$@" } +zww() { + local cmd="$1" file="$2" + shift; shift + "$cmd" "$file" -Wextra -Wconversion \ + -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings \ + -Winit-self -Wno-unused-parameter \ + -Wparentheses -Wmissing-format-attribute -Wfloat-equal \ + -Winline "$@" +} + +zccw() { + local file="$1" + shift + zww zcc "$file" "$@" +} + zppw() { local file="$1" shift - zpp "$file" -Wextra -Woverloaded-virtual -Wconversion \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings \ - -Winit-self -Wsign-promo -Wno-unused-parameter -Wc++0x-compat \ - -Wparentheses -Wmissing-format-attribute -Wfloat-equal \ - -Winline -Wsynth "$@" + zww zpp "$file" -Woverloaded-virtual -Wsign-promo -Wc++0x-compat -Wsynth \ + -Wall \ + -Werror \ + -Wextra \ + -Wstrict-null-sentinel \ + -Wno-old-style-cast \ + -Woverloaded-virtual \ + -Wsign-promo \ + -Wformat=2 \ + -Winit-self \ + -Wswitch-enum \ + -Wunused \ + -Wstrict-overflow \ + -Wfloat-equal \ + -Wundef \ + -Wunsafe-loop-optimizations \ + -Wpointer-arith \ + -Wcast-qual \ + -Wcast-align \ + -Wwrite-strings \ + -Wconversion \ + -Wlogical-op \ + -Wno-aggregate-return \ + -Wno-missing-declarations \ + -Wno-missing-field-initializers \ + -Wmissing-format-attribute \ + -Wpacked \ + -Wredundant-decls \ + -Winline \ + -Winvalid-pch \ + -Wlong-long \ + -Wvolatile-register-var \ + "$@" } #function set_title() { @@ -678,8 +737,8 @@ eval "$( dircolors -b )" -# -t 1 checks if we're in an interactive terminal -# TODO still want is_interactive above? +# -t 1 checks if fd 1 (stdout) is a terminal; if so then we're running +# interactively. if [[ -t 1 ]] ; then if have keychain then eval `keychain --eval --nogui id_dsa 2> /dev/null` 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-22 07:11:39
|
Revision: 1220 http://assorted.svn.sourceforge.net/assorted/?rev=1220&view=rev Author: yangzhang Date: 2009-02-22 07:11:34 +0000 (Sun, 22 Feb 2009) Log Message: ----------- added noncopyable demo Added Paths: ----------- sandbox/trunk/src/cc/noncopyable.cc Added: sandbox/trunk/src/cc/noncopyable.cc =================================================================== --- sandbox/trunk/src/cc/noncopyable.cc (rev 0) +++ sandbox/trunk/src/cc/noncopyable.cc 2009-02-22 07:11:34 UTC (rev 1220) @@ -0,0 +1,9 @@ +// $ g++ -Wall -g3 -o noncopyable noncopyable.cc -Wextra -Wconversion -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Winit-self -Wno-unused-parameter -Wparentheses -Wmissing-format-attribute -Wfloat-equal -Winline -Woverloaded-virtual -Wsign-promo -Wc++0x-compat -Wsynth -Wall -Werror -Wextra -Weffc++ -Wstrict-null-sentinel -Wno-old-style-cast -Woverloaded-virtual -Wsign-promo -Wformat=2 -Winit-self -Wswitch-enum -Wunused -Wstrict-overflow -Wfloat-equal -Wundef -Wunsafe-loop-optimizations -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wlogical-op -Wno-aggregate-return -Wno-missing-declarations -Wno-missing-field-initializers -Wmissing-noreturn -Wmissing-format-attribute -Wpacked -Wredundant-decls -Wunreachable-code -Winline -Winvalid-pch -Wlong-long -Wvolatile-register-var -Wstack-protector +// cc1plus: warnings being treated as errors +// noncopyable.cc:3: error: base class âass boost::noncopyable_::noncopyableâas a non-virtual destructor + +#include <boost/noncopyable.hpp> +using namespace boost; +class C : noncopyable { +}; +int main() { return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-22 06:49:49
|
Revision: 1219 http://assorted.svn.sourceforge.net/assorted/?rev=1219&view=rev Author: yangzhang Date: 2009-02-22 06:49:47 +0000 (Sun, 22 Feb 2009) Log Message: ----------- - moved a bunch of files around to get rid of the separation between boost-dependent and non-boost-dependent parts of the library - declared the library to require boost - removed libtask - updated the feature list - removed method_thread and other unnecessary thread utilities Modified Paths: -------------- cpp-commons/trunk/README cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/st/st.h cpp-commons/trunk/src/commons/threads.h Added Paths: ----------- cpp-commons/trunk/src/commons/delegates.h cpp-commons/trunk/src/commons/unique_ptr.hpp Removed Paths: ------------- cpp-commons/trunk/src/commons/boost/ cpp-commons/trunk/src/commons/task/ Modified: cpp-commons/trunk/README =================================================================== --- cpp-commons/trunk/README 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/README 2009-02-22 06:49:47 UTC (rev 1219) @@ -8,11 +8,13 @@ The C++ Commons is a general-purpose utility library for the C++ programming language. This is a library of header files, in the same spirit as [boost]. -Here are some of the features present in the library: +Features: - C functions for string manipulation - RAII utilities, such as for closing file descriptors and `finally` objects -- `array`: thin wrapper around arrays (`scoped_array` + size) +- smart arrays: sized arrays, "managed" (moveable, conditionally + scope-destroyed) arrays +- Howard Hinnant's C++03-emulated TR1 `unique_ptr.hpp` - `pool`: fixed-size object pools - bit manipulation - bundles of header includes @@ -35,14 +37,25 @@ - time utilities, including timers and simpler interfaces to system clocks - utilities for streams - utilities for [tamer] +- micro-utilities: noncopyable, expander annotations - x86 architecture-specific tools Setup ----- +Requirements: + +- [boost] 1.38.0 +- [GCC] 4 + Like [boost], just include these header files in your next C++ project, and you're ready to go! +Certain parts of the library have extra dependencies. (In particular, these +tend to be designed as supplementing the required libraries.) + +- [State Threads] 1.8 + Related Work ------------ Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/src/commons/array.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -1,10 +1,9 @@ #ifndef COMMONS_ARRAY_H #define COMMONS_ARRAY_H -#include <boost/scoped_array.hpp> -#include <commons/boost/unique_ptr.hpp> #include <commons/check.h> #include <commons/nullptr.h> +#include <commons/unique_ptr.hpp> #include <commons/utility.h> namespace commons { Copied: cpp-commons/trunk/src/commons/delegates.h (from rev 1216, cpp-commons/trunk/src/commons/boost/delegates.h) =================================================================== --- cpp-commons/trunk/src/commons/delegates.h (rev 0) +++ cpp-commons/trunk/src/commons/delegates.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -0,0 +1,69 @@ +#ifndef COMMONS_BOOST_DELEGATES_H +#define COMMONS_BOOST_DELEGATES_H + +#include <boost/function.hpp> +#include <boost/scoped_ptr.hpp> +#include <iostream> // for cerr + +namespace commons +{ + + using namespace boost; + using namespace std; + + typedef std::function<void()> fn; + + void + swallow(const fn f) { + try { f(); } + catch (std::exception &ex) { cerr << ex.what() << endl; } + } + + /** + * Delegate for running a 0-ary void function. + */ + void + run_function0(const void *p) + { + scoped_ptr<const fn> pf(reinterpret_cast<const fn*>(p)); + (*pf)(); + } + + /** + * NULL void*-returning delegate for running a 0-ary void function. + */ + void* + run_function0_null(void* p) + { + run_function0(p); + return NULL; + } + + // TODO: is there a way to do this? +// /** +// * Exception-returning delegate for running a 0-ary void function. +// */ +// void* +// run_function0_ex(void* p) +// { +// try { run_function0(p); } +// catch (std::exception &ex) { return std::exception(ex); } +// } + + /** + * A class that takes a functor and calls it on destruction, effectively + * giving you a `finally` clause. Particularly useful with clamp. + */ + //template<typename T> + typedef function0<void> T; + class finally { + public: + finally(T f): f_(f) {} + ~finally() { f_(); } + private: + T f_; + }; + +} + +#endif Property changes on: cpp-commons/trunk/src/commons/delegates.h ___________________________________________________________________ Added: svn:mergeinfo + Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -10,10 +10,10 @@ #include <st.h> #include <stx.h> #include <commons/array.h> +#include <commons/delegates.h> #include <commons/nullptr.h> // delegates.h must be included after sockets.h due to bind() conflicts. #include <commons/sockets.h> -#include <commons/boost/delegates.h> #include <commons/utility.h> #include <boost/foreach.hpp> #include <boost/function.hpp> Modified: cpp-commons/trunk/src/commons/threads.h =================================================================== --- cpp-commons/trunk/src/commons/threads.h 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/src/commons/threads.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -6,11 +6,17 @@ #include <sys/types.h> #include <unistd.h> +#include <boost/function.hpp> + #include <commons/check.h> +#include <commons/delegates.h> +#include <commons/nullptr.h> namespace commons { + using namespace boost; + /** * Get the current thread ID. Glibc does not provide a wrapper for this * system call. @@ -41,171 +47,22 @@ waitall(pthread_t* ts, int n) { for (int i = 0; i < n; i++) { - check(pthread_join(ts[i], NULL) == 0); + check(pthread_join(ts[i], nullptr) == 0); } } /** - * Helper for launching new threads. - */ - void* - runner(void *p) - { - void (*f)() = (void(*)()) p; - (*f)(); - return NULL; - } - - /** * Run a function in pthread. * \return The new pthread_t on success, 0 on failure. * TODO: Is it safe to treat the pthread_t as an integral type? */ pthread_t - spawn(void (*f)()) + spawn(const boost::function<void()>& f) { pthread_t t; - return pthread_create(&t, NULL, &runner, (void*) f) == 0 ? t : 0; + return pthread_create(&t, NULL, &run_function0_null, (void*) new boost::function<void()>(f)) == 0 ? t : 0; } - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C> pthread_t - method_thread(C *o, void (C::*m)()) - { - class runnable { - public: - C *o; - void (C::*m)(); - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)() = r->m; - delete r; - (o->*m)(); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C, class A> pthread_t - method_thread(C *o, void (C::*m)(A), A a) - { - class runnable { - public: - C *o; - void (C::*m)(A a); - A a; - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)(A ) = r->m; - A a = r->a; - delete r; - (o->*m)(a); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - r->a = a; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C, class A1, class A2> pthread_t - method_thread(C *o, void (C::*m)(A1 , A2 ), A1 a1, A2 a2) - { - class runnable { - public: - C *o; - void (C::*m)(A1 a1, A2 a2); - A1 a1; - A2 a2; - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)(A1 , A2 ) = r->m; - A1 a1 = r->a1; - A2 a2 = r->a2; - delete r; - (o->*m)(a1, a2); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - r->a1 = a1; - r->a2 = a2; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C, class A1, class A2, class A3> pthread_t - method_thread(C *o, void (C::*m)(A1 , A2, A3), A1 a1, A2 a2, A3 a3) - { - class runnable { - public: - C *o; - void (C::*m)(A1 a1, A2 a2, A3 a3); - A1 a1; - A2 a2; - A3 a3; - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)(A1, A2, A3) = r->m; - A1 a1 = r->a1; - A2 a2 = r->a2; - A3 a3 = r->a3; - delete r; - (o->*m)(a1, a2, a3); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - r->a1 = a1; - r->a2 = a2; - r->a3 = a3; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - } #endif Copied: cpp-commons/trunk/src/commons/unique_ptr.hpp (from rev 1216, cpp-commons/trunk/src/commons/boost/unique_ptr.hpp) =================================================================== --- cpp-commons/trunk/src/commons/unique_ptr.hpp (rev 0) +++ cpp-commons/trunk/src/commons/unique_ptr.hpp 2009-02-22 06:49:47 UTC (rev 1219) @@ -0,0 +1,535 @@ +/////////////////////////////////////////////////////////////////////////////// +// unique_ptr.hpp header file +// +// Copyright 2009 Howard Hinnant, Ion Gaztañaga. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// See http://www.boost.org/libs/foreach for documentation + +// This is a C++03 emulation of std::unique_ptr placed in namespace boost. +// Reference http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf +// for the latest unique_ptr specification, and +// reference http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html +// for any pending issues against this specification. + +#ifndef UNIQUE_PTR_HPP +#define UNIQUE_PTR_HPP + +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits.hpp> +#include <boost/static_assert.hpp> +#include <boost/mpl/if.hpp> + +namespace boost +{ + +namespace detail_unique_ptr +{ + +typedef char one; +struct two {one _[2];}; + +// An is_convertible<From, To> that considers From an rvalue (consistent with C++0X). +// This is a simplified version neglecting the types function, array, void and abstract types +// I had to make a special case out of is_convertible<T,T> to make move-only +// types happy. + +namespace is_conv_imp +{ +template <class T> one test1(const T&); +template <class T> two test1(...); +template <class T> one test2(T); +template <class T> two test2(...); +template <class T> T source(); +} + +template <class T1, class T2> +struct is_convertible +{ + static const bool value = sizeof(is_conv_imp::test1<T2>(is_conv_imp::source<T1>())) == 1; +}; + +template <class T> +struct is_convertible<T, T> +{ + static const bool value = sizeof(is_conv_imp::test2<T>(is_conv_imp::source<T>())) == 1; +}; + +template <class T> +class rv +{ + T& r_; + +public: + explicit rv(T& r) : r_(r) {} + T* operator->() {return &r_;} + T& operator*() {return r_;} +}; + +template <class T> +struct identity +{ + typedef T type; +}; + +} // detail_unique_ptr + +template <class T> +inline +typename enable_if_c +< + !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + T& +>::type +move(T& t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + const T& +>::type +move(const T& t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + T +>::type +move(T& t) +{ + return T(detail_unique_ptr::rv<T>(t)); +} + +template <class T> +inline +typename enable_if_c +< + is_reference<T>::value, + T +>::type +forward(typename detail_unique_ptr::identity<T>::type t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + !is_reference<T>::value, + T +>::type +forward(typename detail_unique_ptr::identity<T>::type& t) +{ + return move(t); +} + +template <class T> +inline +typename enable_if_c +< + !is_reference<T>::value, + T +>::type +forward(const typename detail_unique_ptr::identity<T>::type& t) +{ + return move(const_cast<T&>(t)); +} + +namespace detail_unique_ptr { + +// A move-aware but stripped-down compressed_pair which only optimizes storage for T2 +template <class T1, class T2, bool = is_empty<T2>::value> +class unique_ptr_storage +{ + T1 t1_; + T2 t2_; + + typedef typename add_reference<T2>::type T2_reference; + typedef typename add_reference<const T2>::type T2_const_reference; + + unique_ptr_storage(const unique_ptr_storage&); + unique_ptr_storage& operator=(const unique_ptr_storage&); +public: + operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} + + unique_ptr_storage() : t1_(), t2_() {} + + explicit unique_ptr_storage(T1 t1) + : t1_(move(t1)), t2_() {} + + unique_ptr_storage(T1 t1, T2 t2) + : t1_(move(t1)), t2_(forward<T2>(t2)) {} + + T1& first() {return t1_;} + const T1& first() const {return t1_;} + + T2_reference second() {return t2_;} + T2_const_reference second() const {return t2_;} +}; + +template <class T1, class T2> +class unique_ptr_storage<T1, T2, true> + : private T2 +{ + T1 t1_; + typedef T2 t2_; + + unique_ptr_storage(const unique_ptr_storage&); + unique_ptr_storage& operator=(const unique_ptr_storage&); +public: + operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} + + unique_ptr_storage() : t1_() {} + + explicit unique_ptr_storage(T1 t1) + : t1_(move(t1)) {} + + unique_ptr_storage(T1 t1, T2 t2) + : t2_(move(t2)), t1_(move(t1)) {} + + T1& first() {return t1_;} + const T1& first() const {return t1_;} + + T2& second() {return *this;} + const T2& second() const {return *this;} +}; + +template <class T1, class T2, bool b> +inline +void +swap(unique_ptr_storage<T1, T2, b>& x, unique_ptr_storage<T1, T2, b>& y) +{ + using std::swap; + swap(x.first(), y.first()); + swap(x.second(), y.second()); +} + +} // detail_unique_ptr + +template <class T> +struct default_delete +{ + default_delete() {} + template <class U> + default_delete(const default_delete<U>&, + typename enable_if_c<detail_unique_ptr::is_convertible<U*, T*>::value>::type* = 0) + {} + + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete ptr; + } +}; + +template <class T> +struct default_delete<T[]> +{ + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete [] ptr; + } + +private: + + template <class U> void operator()(U*) const; +}; + +namespace detail_unique_ptr +{ + +namespace pointer_type_imp +{ + +template <class U> static two test(...); +template <class U> static one test(typename U::pointer* = 0); + +} // pointer_type_imp + +template <class T> +struct has_pointer_type +{ + static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1; +}; + +namespace pointer_type_imp +{ + +template <class T, class D, bool = has_pointer_type<D>::value> +struct pointer_type +{ + typedef typename D::pointer type; +}; + +template <class T, class D> +struct pointer_type<T, D, false> +{ + typedef T* type; +}; + +} // pointer_type_imp + +template <class T, class D> +struct pointer_type +{ + typedef typename pointer_type_imp::pointer_type<T, + typename boost::remove_reference<D>::type>::type type; +}; + +} // detail_unique_ptr + +template <class T, class D = default_delete<T> > +class unique_ptr +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; + +private: + detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; + + typedef typename add_reference<deleter_type>::type deleter_reference; + typedef typename add_reference<const deleter_type>::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + +public: + operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} + unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} + unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + + unique_ptr() + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p) + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + unique_ptr(pointer p, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type d) + : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} + + template <class U, class E> + unique_ptr(unique_ptr<U, E> u, + typename enable_if_c + < + !boost::is_array<U>::value && + detail_unique_ptr::is_convertible<typename unique_ptr<U>::pointer, pointer>::value && + detail_unique_ptr::is_convertible<E, deleter_type>::value && + ( + !is_reference<deleter_type>::value || + is_same<deleter_type, E>::value + ) + >::type* = 0) + : ptr_(u.release(), forward<D>(forward<E>(u.get_deleter()))) {} + + ~unique_ptr() {reset();} + + unique_ptr& operator=(int nat::*) + { + reset(); + return *this; + } + + template <class U, class E> + unique_ptr& + operator=(unique_ptr<U, E> u) + { + reset(u.release()); + ptr_.second() = move(u.get_deleter()); + return *this; + } + + typename add_reference<T>::type operator*() const {return *get();} + pointer operator->() const {return get();} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} +}; + +template <class T, class D> +class unique_ptr<T[], D> +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; + +private: + detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; + + typedef typename add_reference<deleter_type>::type deleter_reference; + typedef typename add_reference<const deleter_type>::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + +public: + operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} + unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} + unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + + unique_ptr() + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p) + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + unique_ptr(pointer p, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type d) + : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} + + ~unique_ptr() {reset();} + + T& operator[](size_t i) const {return get()[i];} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} +private: + template <class U> + explicit unique_ptr(U, + typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); + + template <class U> + unique_ptr(U, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type, + typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); +}; + +template<class T, class D> +inline +void +swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) +{ + x.swap(y); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return x.get() == y.get(); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(x == y); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return x.get() < y.get(); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(y < x); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return y < x; +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(x < y); +} + +} // boost + +#endif // UNIQUE_PTR_HPP Property changes on: cpp-commons/trunk/src/commons/unique_ptr.hpp ___________________________________________________________________ Added: svn:mergeinfo + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-22 06:40:44
|
Revision: 1218 http://assorted.svn.sourceforge.net/assorted/?rev=1218&view=rev Author: yangzhang Date: 2009-02-22 06:40:38 +0000 (Sun, 22 Feb 2009) Log Message: ----------- added method_thread demo Added Paths: ----------- sandbox/trunk/src/cc/method_thread.cc Added: sandbox/trunk/src/cc/method_thread.cc =================================================================== --- sandbox/trunk/src/cc/method_thread.cc (rev 0) +++ sandbox/trunk/src/cc/method_thread.cc 2009-02-22 06:40:38 UTC (rev 1218) @@ -0,0 +1,141 @@ +// Demo of how to start a thread in a method. +// This code originally came from PDOS projects. + + /** + * Run a method in pthread. + * \return The new pthread_t on success, 0 on failure. + */ + template <class C> pthread_t + method_thread(C *o, void (C::*m)()) + { + class runnable { + public: + C *o; + void (C::*m)(); + static void *run(void *vvv) { + runnable *r = (runnable*)vvv; + C *o = r->o; + void (C::*m)() = r->m; + delete r; + (o->*m)(); + return 0; + } + }; + runnable *r = new runnable; + r->o = o; + r->m = m; + pthread_t th; + if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ + return th; + } + return 0; + } + + /** + * Run a method in pthread. + * \return The new pthread_t on success, 0 on failure. + */ + template <class C, class A> pthread_t + method_thread(C *o, void (C::*m)(A), A a) + { + class runnable { + public: + C *o; + void (C::*m)(A a); + A a; + static void *run(void *vvv) { + runnable *r = (runnable*)vvv; + C *o = r->o; + void (C::*m)(A ) = r->m; + A a = r->a; + delete r; + (o->*m)(a); + return 0; + } + }; + runnable *r = new runnable; + r->o = o; + r->m = m; + r->a = a; + pthread_t th; + if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ + return th; + } + return 0; + } + + /** + * Run a method in pthread. + * \return The new pthread_t on success, 0 on failure. + */ + template <class C, class A1, class A2> pthread_t + method_thread(C *o, void (C::*m)(A1 , A2 ), A1 a1, A2 a2) + { + class runnable { + public: + C *o; + void (C::*m)(A1 a1, A2 a2); + A1 a1; + A2 a2; + static void *run(void *vvv) { + runnable *r = (runnable*)vvv; + C *o = r->o; + void (C::*m)(A1 , A2 ) = r->m; + A1 a1 = r->a1; + A2 a2 = r->a2; + delete r; + (o->*m)(a1, a2); + return 0; + } + }; + runnable *r = new runnable; + r->o = o; + r->m = m; + r->a1 = a1; + r->a2 = a2; + pthread_t th; + if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ + return th; + } + return 0; + } + + /** + * Run a method in pthread. + * \return The new pthread_t on success, 0 on failure. + */ + template <class C, class A1, class A2, class A3> pthread_t + method_thread(C *o, void (C::*m)(A1 , A2, A3), A1 a1, A2 a2, A3 a3) + { + class runnable { + public: + C *o; + void (C::*m)(A1 a1, A2 a2, A3 a3); + A1 a1; + A2 a2; + A3 a3; + static void *run(void *vvv) { + runnable *r = (runnable*)vvv; + C *o = r->o; + void (C::*m)(A1, A2, A3) = r->m; + A1 a1 = r->a1; + A2 a2 = r->a2; + A3 a3 = r->a3; + delete r; + (o->*m)(a1, a2, a3); + return 0; + } + }; + runnable *r = new runnable; + r->o = o; + r->m = m; + r->a1 = a1; + r->a2 = a2; + r->a3 = a3; + pthread_t th; + if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ + return th; + } + return 0; + } + 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:46
|
Revision: 1217 http://assorted.svn.sourceforge.net/assorted/?rev=1217&view=rev Author: yangzhang Date: 2009-02-22 06:33:43 +0000 (Sun, 22 Feb 2009) Log Message: ----------- added extra warnings and fixed issues they pointed out Modified Paths: -------------- ydb/trunk/src/Makefile ydb/trunk/src/main.lzz.clamp ydb/trunk/src/p2.cc ydb/trunk/src/ser.cc ydb/trunk/src/ser.h Modified: ydb/trunk/src/Makefile =================================================================== --- ydb/trunk/src/Makefile 2009-02-22 06:33:36 UTC (rev 1216) +++ ydb/trunk/src/Makefile 2009-02-22 06:33:43 UTC (rev 1217) @@ -29,7 +29,7 @@ PPROF := -lprofiler endif ifneq ($(OPT),) - OPT := -O3 + OPT := -O3 -Wdisabled-optimization else OPT := -g3 endif @@ -42,12 +42,52 @@ LDLIBS := -lstx -lst -lresolv -lprotobuf -lgtest \ -lboost_program_options-gcc43-mt -lboost_thread-gcc43-mt \ -lboost_serialization-gcc43-mt $(PPROF) -CXXFLAGS := $(OPT) -pthread $(GPROF) -Wall -Werror -Wextra -Woverloaded-virtual \ - -Wconversion -Wignored-qualifiers \ - -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings \ - -Winit-self -Wsign-promo -Wunused-parameter -Wc++0x-compat \ - -Wparentheses -Wmissing-format-attribute -Wfloat-equal \ - -Winline -Wsynth -Wno-old-style-cast -std=gnu++0x $(PB) $(CXXFLAGS) + +CXXFLAGS := $(OPT) -pthread $(GPROF) \ + -Wall \ + -Werror \ + -Wextra \ + -Wstrict-null-sentinel \ + -Wno-old-style-cast \ + -Woverloaded-virtual \ + -Wsign-promo \ + -Wformat=2 \ + -Winit-self \ + -Wswitch-enum \ + -Wunused \ + -Wstrict-overflow \ + -Wfloat-equal \ + -Wundef \ + -Wunsafe-loop-optimizations \ + -Wpointer-arith \ + -Wcast-qual \ + -Wcast-align \ + -Wwrite-strings \ + -Wconversion \ + -Wlogical-op \ + -Wno-aggregate-return \ + -Wno-missing-declarations \ + -Wno-missing-field-initializers \ + -Wmissing-format-attribute \ + -Wpacked \ + -Wredundant-decls \ + -Winline \ + -Winvalid-pch \ + -Wlong-long \ + -Wvolatile-register-var \ + -std=gnu++0x \ + $(PB) \ + $(CXXFLAGS) + + # -Wmissing-noreturn \ + # -Weffc++ \ + # -pedantic \ + # -Wshadow \ + # -Wswitch-default \ + # -Wpadded \ + # -Wunreachable-code \ + # -Wstack-protector \ + PBCXXFLAGS := $(OPT) -Wall -Werror $(GPROF) all: $(TARGET) @@ -83,7 +123,7 @@ $(COMPILE.cc) $(PBHDRS) $(OUTPUT_OPTION) $< clean: - rm -f $(GENSRCS) $(GENHDRS) $(OBJS) $(TARGET) main.lzz *.clamp_h serperf + rm -f $(GENSRCS) $(GENHDRS) $(OBJS) $(TARGET) main.lzz *.clamp_h distclean: clean rm -f all.h all.h.gch Modified: ydb/trunk/src/main.lzz.clamp =================================================================== --- ydb/trunk/src/main.lzz.clamp 2009-02-22 06:33:36 UTC (rev 1216) +++ ydb/trunk/src/main.lzz.clamp 2009-02-22 06:33:43 UTC (rev 1217) @@ -457,8 +457,8 @@ len = ntohl(len); // Parse the message body. - if (len < 4096) { - char buf[len]; + if (len <= 4096) { + char buf[4096]; GETMSG(buf); } else { //cout << "receiving large msg; heap-allocating " << len << " bytes" << endl; @@ -1429,7 +1429,7 @@ * have marked themselves as interruptible. */ void handle_sig_sync() { - stfd fd = checkerr(st_netfd_open(sig_pipe[0])); + st_closing fd(checkerr(st_netfd_open(sig_pipe[0]))); while (true) { int sig; checkeqnneg(st_read(fd, &sig, sizeof sig, ST_UTIME_NO_TIMEOUT), Modified: ydb/trunk/src/p2.cc =================================================================== --- ydb/trunk/src/p2.cc 2009-02-22 06:33:36 UTC (rev 1216) +++ ydb/trunk/src/p2.cc 2009-02-22 06:33:43 UTC (rev 1217) @@ -64,7 +64,7 @@ end_ -= diff; } // read; advance end_ - STAT(readtime, readcnt, int res = ::read(fd(), end_, rem());) + STAT(readtime, readcnt, ssize_t res = ::read(fd(), end_, rem());) int e = errno; errno = 0; //cout << "read res " << res << endl; @@ -125,7 +125,7 @@ size_t rem() { return buf_.end() - end_; } arr getbuf(uint32_t req) { - uint32_t tot = req + sizeof req; + uint32_t tot = uint32_t(req + sizeof req); check(tot > 0); check(tot <= buf_.size()); //cout << "getbuf req " << req << endl; @@ -151,7 +151,7 @@ void write() { // perform the write - STAT(writetime, writecnt, int res = ::write(fd(), start_, end_ - start_);) + STAT(writetime, writecnt, ssize_t res = ::write(fd(), start_, end_ - start_);) if (res < 0) { close(fd()); throw exception(); } //cout << "write res " << res << " amt " << amt() << endl; // advance start_ @@ -182,7 +182,7 @@ void handle_write() { //cout << "writing" << endl; uint32_t npairs = batch_size; - uint32_t len = 2 * sizeof(uint32_t) * npairs; + uint32_t len = uint32_t(2 * sizeof(uint32_t) * npairs); arr a = w_.getbuf(len); buf_ = a; if (buf_ == nullptr) return; @@ -234,7 +234,7 @@ //if (verbose) cout << current_time_millis() << ": count " << counter_ << endl; if (counter_ > thresh) { long long end = current_time_millis(); - double rate = double(counter_) / (end - start_) * 1000; + double rate = counter_ / double(end - start_) * 1000; cout << "rate " << rate << " pairs/s " << rate / 5 << " tps; readcount " << readcount_ << endl; throw exception(); } Modified: ydb/trunk/src/ser.cc =================================================================== --- ydb/trunk/src/ser.cc 2009-02-22 06:33:36 UTC (rev 1216) +++ ydb/trunk/src/ser.cc 2009-02-22 06:33:43 UTC (rev 1217) @@ -28,7 +28,7 @@ uint32_t len = 0; str.append(sizeof len, '\0'); check(batch.AppendToString(&str)); - len = str.size() - sizeof len; + len = uint32_t(str.size() - sizeof len); copy((char*) &len, (char*) &len + sizeof len, str.begin()); os(str.data(), str.size()); } Modified: ydb/trunk/src/ser.h =================================================================== --- ydb/trunk/src/ser.h 2009-02-22 06:33:36 UTC (rev 1216) +++ ydb/trunk/src/ser.h 2009-02-22 06:33:43 UTC (rev 1217) @@ -4,6 +4,7 @@ #include <commons/array.h> #include <commons/exceptions.h> #include <commons/st/st.h> +#include <commons/utility.h> #include <iomanip> #include <iostream> #include "ydb.pb.h" @@ -26,6 +27,7 @@ class writer { + NONCOPYABLE(writer) private: commons::array<char> a_; char *p_; 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 00:14:36
|
Revision: 1215 http://assorted.svn.sourceforge.net/assorted/?rev=1215&view=rev Author: yangzhang Date: 2009-02-22 00:14:14 +0000 (Sun, 22 Feb 2009) Log Message: ----------- fixed all warnings Modified Paths: -------------- ydb/trunk/src/Makefile ydb/trunk/src/main.lzz.clamp ydb/trunk/src/ser.h Modified: ydb/trunk/src/Makefile =================================================================== --- ydb/trunk/src/Makefile 2009-02-21 23:55:46 UTC (rev 1214) +++ ydb/trunk/src/Makefile 2009-02-22 00:14:14 UTC (rev 1215) @@ -42,13 +42,12 @@ LDLIBS := -lstx -lst -lresolv -lprotobuf -lgtest \ -lboost_program_options-gcc43-mt -lboost_thread-gcc43-mt \ -lboost_serialization-gcc43-mt $(PPROF) -# The -Wno- warnings are for boost. CXXFLAGS := $(OPT) -pthread $(GPROF) -Wall -Werror -Wextra -Woverloaded-virtual \ - -Wconversion -Wno-conversion -Wno-ignored-qualifiers \ + -Wconversion -Wignored-qualifiers \ -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings \ - -Winit-self -Wsign-promo -Wno-unused-parameter -Wc++0x-compat \ + -Winit-self -Wsign-promo -Wunused-parameter -Wc++0x-compat \ -Wparentheses -Wmissing-format-attribute -Wfloat-equal \ - -Wno-inline -Wsynth -Wno-old-style-cast -std=gnu++0x $(PB) $(CXXFLAGS) + -Winline -Wsynth -Wno-old-style-cast -std=gnu++0x $(PB) $(CXXFLAGS) PBCXXFLAGS := $(OPT) -Wall -Werror $(GPROF) all: $(TARGET) Modified: ydb/trunk/src/main.lzz.clamp =================================================================== --- ydb/trunk/src/main.lzz.clamp 2009-02-21 23:55:46 UTC (rev 1214) +++ ydb/trunk/src/main.lzz.clamp 2009-02-22 00:14:14 UTC (rev 1215) @@ -57,7 +57,7 @@ using namespace ydb::msg; #define GETMSG(buf) \ -checkeqnneg(st_read_fully(src, buf, len, timeout), (int) len); \ +checkeqnneg(st_read_fully(src, buf, len, timeout), int(len)); \ if (stop_time != nullptr) \ *stop_time = current_time_millis(); \ check(msg.ParseFromArray(buf, len)); @@ -94,7 +94,8 @@ /** * Convenience function for calculating percentages. */ -double pct(double sub, double tot) { return 100 * sub / tot; } +template<typename T> +double pct(T sub, T tot) { return 100 * double(sub) / double(tot); } /** * Convenience class for performing long-jumping break. @@ -300,10 +301,10 @@ * Helper for getting the cached ByteSize of a message. */ template <typename T> -int +size_t pb_size(const T &msg) { // GetCachedSize returns 0 if no cached size. - int len = msg.GetCachedSize(); + size_t len = msg.GetCachedSize(); return len == 0 ? msg.ByteSize() : len; } @@ -314,7 +315,7 @@ void ser(ostream &s, const T &msg) { - uint32_t len = htonl(pb_size(msg)); + uint32_t len = htonl(uint32_t(pb_size(msg))); s.write(reinterpret_cast<const char*>(&len), sizeof len); check(msg.SerializeToOstream(&s)); } @@ -741,7 +742,7 @@ { long long time_diff = stop_time - start_time; int count_diff = stop_count - start_count; - double rate = double(count_diff) * 1000 / time_diff; + double rate = count_diff * 1000 / double(time_diff); cout << action << " " << count_diff << " txns [" << start_count << ".." << stop_count << "] in " << time_diff << " ms [" @@ -1097,7 +1098,7 @@ * from process_txns. */ void -recover_joiner(st_netfd_t listener, const mii &map, const int &seqno, +recover_joiner(st_netfd_t listener, st_channel<shared_ptr<Recovery> > &send_states) { st_netfd_t joiner; @@ -1334,8 +1335,8 @@ ref(send_states), ref(backlog), init.txnseqno(), mypos, init.node_size()); st_joining join_proc(my_spawn(process_fn, "process_txns")); - st_joining join_rec(my_spawn(bind(recover_joiner, listener, ref(map), - ref(seqno), ref(send_states)), + st_joining join_rec(my_spawn(bind(recover_joiner, listener, + ref(send_states)), "recover_joiner")); try { Modified: ydb/trunk/src/ser.h =================================================================== --- ydb/trunk/src/ser.h 2009-02-21 23:55:46 UTC (rev 1214) +++ ydb/trunk/src/ser.h 2009-02-22 00:14:14 UTC (rev 1215) @@ -64,11 +64,12 @@ } } void show() { - cout << (void*) p_; + cout << static_cast<void*>(p_); for (size_t i = 0; i < a_.size(); ++i) - cout << " " << hex << setfill('0') << setw(2) << (int)(unsigned char)(a_.get()[i]); + cout << " " << hex << setfill('0') << setw(2) + << int(static_cast<unsigned char>(a_.get()[i])); cout << endl; - cout << (void*) p_; + cout << static_cast<void*>(p_); for (size_t i = 0; i < a_.size(); ++i) cout << " " << setfill(' ') << setw(2) << (i == pos() ? "^^" : ""); cout << endl; @@ -124,14 +125,14 @@ Txn(stream &s) : s_(s), r_(s.get_reader()), w_(s.get_writer()), off_(w_.pos()), op_(s), nop_(unset), seqno_(unset) {} - void Clear() { w_.reserve(0*50); nop_ = unset; seqno_ = unset; off_ = w_.pos(); } + void Clear() { nop_ = unset; seqno_ = unset; off_ = w_.pos(); } void set_seqno(int x) { w_.write(x); } int seqno() const { return seqno_ == unset ? seqno_ = r_.read<int>() : seqno_; } void start_op() { if (nop_ == unset) nop_ = 0; w_.skip<typeof(nop_)>(); } Op *add_op() { ++nop_; return &op_; } void fin_op() { w_.write(nop_, off_ + sizeof(int)); } int op_size() const { if (nop_ == unset) nop_ = r_.read<typeof(nop_)>(); return nop_; } - const Op &op(int o) const { return op_; } + const Op &op(int) const { return op_; } }; class TxnBatch @@ -145,7 +146,7 @@ mutable short ntxn_; public: TxnBatch(stream &s) : s_(s), r_(s.get_reader()), w_(s.get_writer()), off_(w_.pos()), txn_(s), ntxn_(unset) {} - void Clear() { w_.reserve(0*100); txn_.Clear(); ntxn_ = unset; off_ = w_.pos(); } + void Clear() { txn_.Clear(); ntxn_ = unset; off_ = w_.pos(); } void start_txn() { if (ntxn_ == unset) ntxn_ = 0; w_.skip<typeof(ntxn_)>(); } Txn *add_txn() { ++ntxn_; txn_.Clear(); return &txn_; } void fin_txn() { w_.write(ntxn_, off_); } @@ -154,33 +155,33 @@ ntxn_ = r_.read<typeof(ntxn_)>(); return ntxn_; } - const Txn &txn(int t) const { txn_.Clear(); return txn_; } - bool AppendToString(string *s) const { throw_operation_not_supported(); } - bool SerializeToString(string *s) const { throw_operation_not_supported(); } - bool SerializeToOstream(ostream *s) const { throw_operation_not_supported(); } - bool ParseFromArray(void *p, size_t len) { throw_operation_not_supported(); } + const Txn &txn(int) const { txn_.Clear(); return txn_; } + bool AppendToString(string*) const { throw_operation_not_supported(); } + bool SerializeToString(string*) const { throw_operation_not_supported(); } + bool SerializeToOstream(ostream*) const { throw_operation_not_supported(); } + bool ParseFromArray(void*, size_t) { throw_operation_not_supported(); } size_t GetCachedSize() const { throw_operation_not_supported(); } size_t ByteSize() const { throw_operation_not_supported(); } }; template<typename T> void start_txn(T &batch); -template<> void start_txn(ydb::pb::TxnBatch &batch) {} +template<> void start_txn(ydb::pb::TxnBatch &) {} template<> void start_txn(ydb::msg::TxnBatch &batch) { batch.start_txn(); } template<typename T> void fin_txn(T &batch); -template<> void fin_txn(ydb::pb::TxnBatch &batch) {} +template<> void fin_txn(ydb::pb::TxnBatch &) {} template<> void fin_txn(ydb::msg::TxnBatch &batch) { batch.fin_txn(); } template<typename T> void start_op(T &txn); -template<> void start_op(ydb::pb::Txn &txn) {} +template<> void start_op(ydb::pb::Txn &) {} template<> void start_op(ydb::msg::Txn &txn) { txn.start_op(); } template<typename T> void fin_op(T &txn); -template<> void fin_op(ydb::pb::Txn &txn) {} +template<> void fin_op(ydb::pb::Txn &) {} template<> void fin_op(ydb::msg::Txn &txn) { txn.fin_op(); } template<typename T> T *new_TxnBatch(stream &s); -template<> ydb::pb::TxnBatch *new_TxnBatch(stream &s) { return new ydb::pb::TxnBatch(); } +template<> ydb::pb::TxnBatch *new_TxnBatch(stream &) { return new ydb::pb::TxnBatch(); } template<> ydb::msg::TxnBatch *new_TxnBatch(stream &s) { return new ydb::msg::TxnBatch(s); } struct pb_types { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-21 23:55:58
|
Revision: 1214 http://assorted.svn.sourceforge.net/assorted/?rev=1214&view=rev Author: yangzhang Date: 2009-02-21 23:55:46 +0000 (Sat, 21 Feb 2009) Log Message: ----------- updated conversions with -Wconversion demo Modified Paths: -------------- sandbox/trunk/src/cc/conversions.cc Modified: sandbox/trunk/src/cc/conversions.cc =================================================================== --- sandbox/trunk/src/cc/conversions.cc 2009-02-21 09:01:45 UTC (rev 1213) +++ sandbox/trunk/src/cc/conversions.cc 2009-02-21 23:55:46 UTC (rev 1214) @@ -1,6 +1,7 @@ // Demo of conversions. #include <iostream> +#include <cstdlib> #include <string> using namespace std; @@ -34,5 +35,16 @@ // C++ decides the "best" function to call by ranking all the possible calls. Standard conversions rank better than user-defined conversions, so #1 is called. f(string("hello")); f("hello"); + + long long l = 0; + // Enable -Wconversion, and you'll get: + // + // warning: conversion to ‘double’ from ‘long long int’ may alter its value + // + // Must explicitly convert the latter l with double(l). + // + // double d = double(l) * 1000 / l; + double d = double(l) * 1000 / double(l); + cout << d << endl; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-21 09:01:56
|
Revision: 1213 http://assorted.svn.sourceforge.net/assorted/?rev=1213&view=rev Author: yangzhang Date: 2009-02-21 09:01:45 +0000 (Sat, 21 Feb 2009) Log Message: ----------- added smartptrs demo Modified Paths: -------------- sandbox/trunk/src/cc/smartptrs.cc Modified: sandbox/trunk/src/cc/smartptrs.cc =================================================================== --- sandbox/trunk/src/cc/smartptrs.cc 2009-02-20 22:43:34 UTC (rev 1212) +++ sandbox/trunk/src/cc/smartptrs.cc 2009-02-21 09:01:45 UTC (rev 1213) @@ -1,6 +1,24 @@ #include <boost/scoped_array.hpp> +#include <boost/scoped_ptr.hpp> +// NOT what we want: +// #include <boost/interprocess/smart_ptr/unique_ptr.hpp> +#include <memory> +#include <commons/boost/unique_ptr.hpp> using namespace boost; +// using namespace boost::interprocess; +using namespace std; int main() { scoped_array<int> a(new int[5]); + scoped_array<int> b; + swap(a,b); + + unique_ptr<int[]> u(new int[5]); + + auto_ptr<int> p(new int(3)); + + // This doesn't work. + // scoped_ptr<int[]> p(new int[5]); + + const scoped_ptr<int> s(new int[5]); return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-20 23:22:53
|
Revision: 1212 http://assorted.svn.sourceforge.net/assorted/?rev=1212&view=rev Author: yangzhang Date: 2009-02-20 22:43:34 +0000 (Fri, 20 Feb 2009) Log Message: ----------- added demo of boost iostreams Added Paths: ----------- sandbox/trunk/src/cc/boost_iostreams.cc Added: sandbox/trunk/src/cc/boost_iostreams.cc =================================================================== --- sandbox/trunk/src/cc/boost_iostreams.cc (rev 0) +++ sandbox/trunk/src/cc/boost_iostreams.cc 2009-02-20 22:43:34 UTC (rev 1212) @@ -0,0 +1,6 @@ +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filtering_stream.hpp> +using namespace boost::iostreams; +int main() { + filtering_ostream out; +} 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:44:26
|
Revision: 1211 http://assorted.svn.sourceforge.net/assorted/?rev=1211&view=rev Author: yangzhang Date: 2009-02-20 19:44:17 +0000 (Fri, 20 Feb 2009) Log Message: ----------- - falling back to pb for 0-node cases - removed swallower - using google dense_hash_map - optimized/simplified the function pointers - fixed the accidental total exclusion of local (0-node) processing - using operation_not_supported exceptions Modified Paths: -------------- ydb/trunk/README ydb/trunk/src/main.lzz.clamp ydb/trunk/src/ser.h Modified: ydb/trunk/README =================================================================== --- ydb/trunk/README 2009-02-20 19:37:33 UTC (rev 1210) +++ ydb/trunk/README 2009-02-20 19:44:17 UTC (rev 1211) @@ -388,10 +388,17 @@ - 3: 122K/122K/97K - DONE commit - DONE add zero-copy structs/(de-)serialization + - -1: 245K (same as before; actually using pb's) + - 0: 320K (same as before; actually using pb's) + - 1: 300K + - 2: 300K + - 3: 300K Period 2/17- - DONE removed class outstream +- TODO get raw-buffer working in wal, 0-node +- TODO add raw-buffer versions of the response message classes as well - TODO refactor st_reader, etc. to be generic opportunistic buffered readers - TODO see how streambuf read/write is actually implemented (whether it's too slow) @@ -402,8 +409,15 @@ - TODO implement new recovery (add buffer swapping, add buffers to a list) - TODO async (threaded) wal - TODO 0-node 0-copy (don't need to use threads, just process each batch immed) -- TODO google dense hash map +- DONE google dense hash map + - big improvement, again not in the direction we'd like + - 0: 550K + - 1: 490K + - 2: 485K + - 3: 475K +- TODO reuse the serialization buffer in the pb path of ydb + - TODO show aries-write - TODO checkpointing + replaying log from replicas (not from disk) - TODO scale-up on multicore Modified: ydb/trunk/src/main.lzz.clamp =================================================================== --- ydb/trunk/src/main.lzz.clamp 2009-02-20 19:37:33 UTC (rev 1210) +++ ydb/trunk/src/main.lzz.clamp 2009-02-20 19:44:17 UTC (rev 1211) @@ -63,13 +63,16 @@ check(msg.ParseFromArray(buf, len)); #end -#define map_t unordered_map +//#define map_t unordered_map //#define map_t map -//#define map_t dense_hash_map +#define map_t dense_hash_map typedef pair<int, int> pii; typedef map_t<int, int> mii; typedef string ser_t; +template<typename T> void init_map(T &map) {} +template<> void init_map(dense_hash_map<int, int> &map) { map.set_empty_key(-1); map.set_deleted_key(-2); } + // Configuration. st_utime_t timeout; int chkpt, accept_joiner_seqno, issuing_interval, min_ops, max_ops, @@ -550,23 +553,17 @@ }); reader r(nullptr); - //function<void(const void*, size_t)> fn = use_wal ? - // lambda(const void *buf, size_t len) { g_wal->logbuf(buf, len); } : - // lambda(const void *buf, size_t len) { - // }; - //if (use_wal) fn = lambda(const void *buf, size_t len) {}; - //else fn = lambda(const void *buf, size_t len) { g_wal->logbuf(buf, len); }; - // TODO why doesn't this work? - // else fn = boost::bind(&wal::logbuf, g_wal); + function<void(const void*, size_t)> fn; + if (use_wal) + fn = boost::bind(&wal::logbuf, g_wal, _1, _2); + else + fn = lambda(const void *buf, size_t len) { + foreach (st_netfd_t dst, __ref(fds)) + checkeqnneg(st_write(dst, buf, len, ST_UTIME_NO_TIMEOUT), + static_cast<ssize_t>(len)); + }; - writer w(lambda(const void *buf, size_t len) { - if (__ref(use_wal)) - g_wal->logbuf(buf, len); - else - foreach (st_netfd_t dst, __ref(fds)) - checkeqnneg(st_write(dst, buf, len, ST_UTIME_NO_TIMEOUT), - static_cast<ssize_t>(len)); - }, buf_size); + writer w(fn, buf_size); stream s(r,w); scoped_ptr<TxnBatch> pbatch(new_TxnBatch<TxnBatch>(s)); TxnBatch batch = *pbatch; @@ -651,7 +648,7 @@ if (batch.txn_size() == 0) w.reset(); // Broadcast. - if (!fds.empty() && !suppress_txn_msgs) { + if (Types::is_pb() && !fds.empty() && !suppress_txn_msgs) { bcastmsg(fds, batch); } else if (use_wal) { g_wal->log(batch); @@ -846,7 +843,9 @@ st_reader reader(leader); vector<st_netfd_t> leader_v(1, leader); - writer w(lambda(const void*, size_t) { throw std::exception(); }, buf_size); + writer w(lambda(const void*, size_t) { + throw operation_not_supported("process_txns should not be writing"); + }, buf_size); stream s(reader, w); try { @@ -1184,9 +1183,9 @@ const function<void()> f = use_pb ? bind(issue_txns<pb_types>, ref(newreps), ref(seqno), ref(accept_joiner)) : bind(issue_txns<rb_types>, ref(newreps), ref(seqno), ref(accept_joiner)); - st_thread_t swallower = my_spawn(bind(swallow, f), "issue_txns"); + st_thread_t issue_txns_thread = my_spawn(f, "issue_txns"); foreach (const replica_info &r, replicas) newreps.push(r); - st_joining join_swallower(swallower); + st_joining join_issue_txns(issue_txns_thread); finally fin(lambda () { cout << "LEADER SUMMARY" << endl; @@ -1264,7 +1263,7 @@ } // Initialize database state. - mii map; + mii &map = g_map; int seqno = -1; finally f(lambda () { cout << "REPLICA SUMMARY" << endl; @@ -1586,7 +1585,7 @@ check(max_ops > 0); check(max_ops >= min_ops); - if (minreps == 0) use_pb = true; // XXX + if (minreps == 0 && !use_wal) use_pb = true; // XXX } catch (std::exception &ex) { cerr << ex.what() << endl << endl << desc << endl; return 1; @@ -1663,6 +1662,9 @@ } }); + // Initialize the map. + init_map(g_map); + // Which role are we? if (is_leader) { run_leader(minreps, leader_port); @@ -1682,5 +1684,4 @@ * Compile-time options: * * - map, unordered_map, dense_hash_map - * - SERIALIZATION METHOD */ Modified: ydb/trunk/src/ser.h =================================================================== --- ydb/trunk/src/ser.h 2009-02-20 19:37:33 UTC (rev 1210) +++ ydb/trunk/src/ser.h 2009-02-20 19:44:17 UTC (rev 1211) @@ -2,6 +2,7 @@ #define YDB_MSG_H #include <commons/array.h> +#include <commons/exceptions.h> #include <commons/st/st.h> #include <iomanip> #include <iostream> @@ -36,7 +37,7 @@ assert(size_t(p - mark_ + n) <= a_.size()); flush(); size_t diff = mark_ - a_.get(); - memmove(a_.get(), mark_, diff); + memmove(a_.get(), mark_, p_ - mark_); unsent_ = mark_ = a_.get(); p_ -= diff; p -= diff; @@ -154,12 +155,12 @@ return ntxn_; } const Txn &txn(int t) const { txn_.Clear(); return txn_; } - bool AppendToString(string *s) const { throw std::exception(); } - bool SerializeToString(string *s) const { throw std::exception(); } - bool SerializeToOstream(ostream *s) const { throw std::exception(); } - bool ParseFromArray(void *p, size_t len) { throw std::exception(); } - size_t GetCachedSize() const { throw std::exception(); } - size_t ByteSize() const { throw std::exception(); } + bool AppendToString(string *s) const { throw_operation_not_supported(); } + bool SerializeToString(string *s) const { throw_operation_not_supported(); } + bool SerializeToOstream(ostream *s) const { throw_operation_not_supported(); } + bool ParseFromArray(void *p, size_t len) { throw_operation_not_supported(); } + size_t GetCachedSize() const { throw_operation_not_supported(); } + size_t ByteSize() const { throw_operation_not_supported(); } }; template<typename T> void start_txn(T &batch); 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-20 19:04:12
|
Revision: 1209 http://assorted.svn.sourceforge.net/assorted/?rev=1209&view=rev Author: yangzhang Date: 2009-02-20 19:04:02 +0000 (Fri, 20 Feb 2009) Log Message: ----------- demo of how to use boost::bind for partial function application Added Paths: ----------- sandbox/trunk/src/cc/boost_bind_members.cc Added: sandbox/trunk/src/cc/boost_bind_members.cc =================================================================== --- sandbox/trunk/src/cc/boost_bind_members.cc (rev 0) +++ sandbox/trunk/src/cc/boost_bind_members.cc 2009-02-20 19:04:02 UTC (rev 1209) @@ -0,0 +1,15 @@ +// Demo of how to use bind for partial function application. +#include <boost/bind.hpp> +#include <boost/function.hpp> +using namespace boost; +struct X { + void f() {} + void g(int i) {} +} x; +void h(int i) {} +int main() { + function<void()> f = bind(&X::f, &x); + function<void(int)> g = bind(&X::g, &x, _1); // NOTE: the _1 is required! + function<void(int)> h = bind(h, _1); // NOTE: same with ordinary functions + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-20 17:26:37
|
Revision: 1208 http://assorted.svn.sourceforge.net/assorted/?rev=1208&view=rev Author: yangzhang Date: 2009-02-20 17:26:35 +0000 (Fri, 20 Feb 2009) Log Message: ----------- added quick demo of how to append to a string (for Rong) Added Paths: ----------- sandbox/trunk/src/cc/strings_append.cc Added: sandbox/trunk/src/cc/strings_append.cc =================================================================== --- sandbox/trunk/src/cc/strings_append.cc (rev 0) +++ sandbox/trunk/src/cc/strings_append.cc 2009-02-20 17:26:35 UTC (rev 1208) @@ -0,0 +1,11 @@ +#include <string> +#include <iostream> +using namespace std; +static const char c = 'A'; +int main() { + string s; + s += c; + s.append(5, c); + cout << s << endl; + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-20 08:06:34
|
Revision: 1207 http://assorted.svn.sourceforge.net/assorted/?rev=1207&view=rev Author: yangzhang Date: 2009-02-20 08:06:28 +0000 (Fri, 20 Feb 2009) Log Message: ----------- quick fix: fall back to pb whenever minreps == 0 Modified Paths: -------------- ydb/trunk/src/Makefile ydb/trunk/src/main.lzz.clamp ydb/trunk/src/ser.h Modified: ydb/trunk/src/Makefile =================================================================== --- ydb/trunk/src/Makefile 2009-02-20 06:22:02 UTC (rev 1206) +++ ydb/trunk/src/Makefile 2009-02-20 08:06:28 UTC (rev 1207) @@ -48,7 +48,7 @@ -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings \ -Winit-self -Wsign-promo -Wno-unused-parameter -Wc++0x-compat \ -Wparentheses -Wmissing-format-attribute -Wfloat-equal \ - -Wno-inline -Wsynth -std=gnu++0x $(PB) $(CXXFLAGS) + -Wno-inline -Wsynth -Wno-old-style-cast -std=gnu++0x $(PB) $(CXXFLAGS) PBCXXFLAGS := $(OPT) -Wall -Werror $(GPROF) all: $(TARGET) Modified: ydb/trunk/src/main.lzz.clamp =================================================================== --- ydb/trunk/src/main.lzz.clamp 2009-02-20 06:22:02 UTC (rev 1206) +++ ydb/trunk/src/main.lzz.clamp 2009-02-20 08:06:28 UTC (rev 1207) @@ -299,6 +299,7 @@ template <typename T> int pb_size(const T &msg) { + // GetCachedSize returns 0 if no cached size. int len = msg.GetCachedSize(); return len == 0 ? msg.ByteSize() : len; } @@ -563,7 +564,8 @@ g_wal->logbuf(buf, len); else foreach (st_netfd_t dst, __ref(fds)) - checkeqnneg(st_write(dst, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); + checkeqnneg(st_write(dst, buf, len, ST_UTIME_NO_TIMEOUT), + static_cast<ssize_t>(len)); }, buf_size); stream s(r,w); scoped_ptr<TxnBatch> pbatch(new_TxnBatch<TxnBatch>(s)); @@ -611,6 +613,7 @@ if (fds.empty()) { --seqno; process_txn<Types>(g_map, txn, seqno, nullptr); + w.reset(); } // Checkpoint. @@ -648,7 +651,6 @@ if (batch.txn_size() == 0) w.reset(); // Broadcast. -#ifdef USE_PB if (!fds.empty() && !suppress_txn_msgs) { bcastmsg(fds, batch); } else if (use_wal) { @@ -657,7 +659,6 @@ string s; ser(s, batch); } -#endif if (fds.empty()) w.reset(); @@ -1584,6 +1585,8 @@ check(min_ops > 0); check(max_ops > 0); check(max_ops >= min_ops); + + if (minreps == 0) use_pb = true; // XXX } catch (std::exception &ex) { cerr << ex.what() << endl << endl << desc << endl; return 1; Modified: ydb/trunk/src/ser.h =================================================================== --- ydb/trunk/src/ser.h 2009-02-20 06:22:02 UTC (rev 1206) +++ ydb/trunk/src/ser.h 2009-02-20 08:06:28 UTC (rev 1207) @@ -158,6 +158,8 @@ bool SerializeToString(string *s) const { throw std::exception(); } bool SerializeToOstream(ostream *s) const { throw std::exception(); } bool ParseFromArray(void *p, size_t len) { throw std::exception(); } + size_t GetCachedSize() const { throw std::exception(); } + size_t ByteSize() const { throw std::exception(); } }; template<typename T> void start_txn(T &batch); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-20 06:22:10
|
Revision: 1206 http://assorted.svn.sourceforge.net/assorted/?rev=1206&view=rev Author: yangzhang Date: 2009-02-20 06:22:02 +0000 (Fri, 20 Feb 2009) Log Message: ----------- - removed the parse/ser calls - renamed ydb.o -> ydb.pb.o - got pb path working in ser - added notes to reuse serialization buffers for pb path in ydb - added some more notes/todos Modified Paths: -------------- ydb/trunk/README ydb/trunk/src/Makefile ydb/trunk/src/main.lzz.clamp ydb/trunk/src/ser.cc ydb/trunk/src/ser.h Modified: ydb/trunk/README =================================================================== --- ydb/trunk/README 2009-02-20 05:52:31 UTC (rev 1205) +++ ydb/trunk/README 2009-02-20 06:22:02 UTC (rev 1206) @@ -398,6 +398,8 @@ - TODO try making a streambuf for st_write, then try it in conj with struct-less pb - DONE dynamic switch between pb and zero-copy +- TODO fix pb recovery +- TODO implement new recovery (add buffer swapping, add buffers to a list) - TODO async (threaded) wal - TODO 0-node 0-copy (don't need to use threads, just process each batch immed) - TODO google dense hash map Modified: ydb/trunk/src/Makefile =================================================================== --- ydb/trunk/src/Makefile 2009-02-20 05:52:31 UTC (rev 1205) +++ ydb/trunk/src/Makefile 2009-02-20 06:22:02 UTC (rev 1206) @@ -9,7 +9,7 @@ PBS := $(wildcard *.proto) PBHDRS := $(foreach pb,$(PBS),$(patsubst %.proto,%.pb.h,$(pb))) PBSRCS := $(foreach pb,$(PBS),$(patsubst %.proto,%.pb.cc,$(pb))) -PBOBJS := $(foreach pb,$(PBS),$(patsubst %.proto,%.o,$(pb))) +PBOBJS := $(foreach pb,$(PBS),$(patsubst %.proto,%.pb.o,$(pb))) GENHDRS := $(LZZHDRS) $(PBHDRS) GENSRCS := $(LZZSRCS) $(PBSRCS) @@ -56,12 +56,12 @@ $(TARGET): $(OBJS) $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@ +%.pb.o: %.pb.cc %.pb.h + $(CXX) -c $(PBCXXFLAGS) $(OUTPUT_OPTION) $< + %.o: %.cc $(PBHDRS) $(COMPILE.cc) $(OUTPUT_OPTION) $< -%.o: %.pb.cc %.pb.h - $(CXX) -c $(PBCXXFLAGS) $(OUTPUT_OPTION) $< - %.cc %.hh: %.lzz lzz -hx hh -sx cc -hl -sl -hd -sd $< python -c 'pars = file("lambda_impl.clamp_h").read().split("\n\n"); hh = file("main.hh").read(); print >> file("main.cc", "a"), pars[-1]; print >> file("main.hh", "w"), "\n\n".join(pars[:-1] + [hh])' @@ -98,7 +98,7 @@ ### -serperf: serperf.o ydb.o +serperf: serperf.o ydb.pb.o $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION) # serperf.cc ydb.pb.h @@ -106,5 +106,5 @@ p2: p2.cc $(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION) -ser: ser.cc ser.h ydb.o +ser: ser.cc ser.h ydb.pb.o $(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION) Modified: ydb/trunk/src/main.lzz.clamp =================================================================== --- ydb/trunk/src/main.lzz.clamp 2009-02-20 05:52:31 UTC (rev 1205) +++ ydb/trunk/src/main.lzz.clamp 2009-02-20 06:22:02 UTC (rev 1206) @@ -377,7 +377,7 @@ */ template<typename T> void -bcastmsg_sync(const vector<st_netfd_t> &dsts, const T &msg) +bcastmsg_sync(const vector<st_netfd_t> &dsts, const T &msg /*, ser_t &s */) { ser_t s; ser(s, msg); @@ -394,7 +394,7 @@ */ template<typename T> void -bcastmsg(const vector<st_netfd_t> &dsts, const T &msg) +bcastmsg(const vector<st_netfd_t> &dsts, const T &msg /* XXX optimize this , ser_t &s */) { if (use_bcast_async) bcastmsg_async(dsts, msg); else bcastmsg_sync(dsts, msg); @@ -407,6 +407,7 @@ void sendmsg(st_netfd_t dst, const T &msg) { + // XXX optimize this vector<st_netfd_t> dsts(1, dst); bcastmsg(dsts, msg); } Modified: ydb/trunk/src/ser.cc =================================================================== --- ydb/trunk/src/ser.cc 2009-02-20 05:52:31 UTC (rev 1205) +++ ydb/trunk/src/ser.cc 2009-02-20 06:22:02 UTC (rev 1206) @@ -22,6 +22,17 @@ } }; +template<typename TxnBatch> +void push(TxnBatch &batch, string &str, outstream &os) { + str.clear(); + uint32_t len = 0; + str.append(sizeof len, '\0'); + check(batch.AppendToString(&str)); + len = str.size() - sizeof len; + copy((char*) &len, (char*) &len + sizeof len, str.begin()); + os(str.data(), str.size()); +} + template<typename types> void producer(st_netfd_t dst) { @@ -55,7 +66,7 @@ } fin_txn(batch); if (show) cout << w.pos() << '/' << w.size() << endl; - ser(batch, str); + if (types::is_pb()) push(batch, str, os); } batch.Clear(); start_txn(batch); @@ -63,6 +74,7 @@ w.mark(); w.show(); w.flush(); + if (types::is_pb()) push(batch, str, os); } template<typename types> @@ -81,8 +93,13 @@ scoped_ptr<TxnBatch> p(new_TxnBatch<TxnBatch>(s)); TxnBatch &batch = *p; while (true) { - batch.Clear(); - parse(batch, str); + if (types::is_pb()) { + uint32_t len = r.read<uint32_t>(); + managed_array<char> a = r.read(len); + check(batch.ParseFromArray(a.get(), len)); + } else { + batch.Clear(); + } if (show) cout << "ntxn " << batch.txn_size() << endl; if (batch.txn_size() == 0) break; for (int t = 0; t < batch.txn_size(); ++t) { @@ -107,6 +124,7 @@ st_init(); bool use_pb = argc > 1 && string("-p") == argv[1]; bool is_leader = argc == (use_pb ? 2 : 1); + cout << "use_pb " << use_pb << " is_leader " << is_leader << endl; if (is_leader) { st_netfd_t listener = st_tcp_listen(7654); st_netfd_t dst = checkerr(st_accept(listener, nullptr, nullptr, @@ -116,7 +134,7 @@ else producer<rb_types>(dst); } else { - st_netfd_t src = st_tcp_connect(argv[1], 7654, ST_UTIME_NO_TIMEOUT); + st_netfd_t src = st_tcp_connect(argv[use_pb ? 2 : 1], 7654, ST_UTIME_NO_TIMEOUT); if (use_pb) consumer<pb_types>(src); else Modified: ydb/trunk/src/ser.h =================================================================== --- ydb/trunk/src/ser.h 2009-02-20 05:52:31 UTC (rev 1205) +++ ydb/trunk/src/ser.h 2009-02-20 06:22:02 UTC (rev 1206) @@ -160,14 +160,6 @@ bool ParseFromArray(void *p, size_t len) { throw std::exception(); } }; -template<typename T> void parse(T &batch, const string &str); -template<> void parse(ydb::pb::TxnBatch &batch, const string &str) { check(batch.ParseFromString(str)); } -template<> void parse(ydb::msg::TxnBatch &batch, const string &str) {} - -template<typename T> void ser(T &batch, string &str); -template<> void ser(ydb::pb::TxnBatch &batch, string &str) { check(batch.SerializeToString(&str)); } -template<> void ser(ydb::msg::TxnBatch &batch, string &str) {} - template<typename T> void start_txn(T &batch); template<> void start_txn(ydb::pb::TxnBatch &batch) {} template<> void start_txn(ydb::msg::TxnBatch &batch) { batch.start_txn(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-20 05:52:39
|
Revision: 1205 http://assorted.svn.sourceforge.net/assorted/?rev=1205&view=rev Author: yangzhang Date: 2009-02-20 05:52:31 +0000 (Fri, 20 Feb 2009) Log Message: ----------- fixed overflow bug; tweaks Modified Paths: -------------- cpp-commons/trunk/src/commons/st/st.h Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-20 01:41:23 UTC (rev 1204) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-20 05:52:31 UTC (rev 1205) @@ -432,7 +432,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, to), static_cast<ssize_t>(req)); + checkeqnneg(st_read_fully(fd_, p + amt(), req - amt(), to), static_cast<ssize_t>(req - amt())); start_ = end_ = buf_.get(); return p; } @@ -447,8 +447,7 @@ // Keep reading until we have enough. while (amt() < req) { - ssize_t res = st_read(fd_, end_, rem(), to); - checknneg(res); + ssize_t res = checknnegerr(st_read(fd_, end_, rem(), to)); if (res == 0) break; else end_ += res; } @@ -486,8 +485,7 @@ // Keep reading until we have enough. while (amt() < req) { - ssize_t res = st_read(fd_, end_, rem(), to); - checknneg(res); + ssize_t res = checknnegerr(st_read(fd_, end_, rem(), to)); if (res == 0) break; else end_ += res; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-20 03:22:10
|
Revision: 1204 http://assorted.svn.sourceforge.net/assorted/?rev=1204&view=rev Author: yangzhang Date: 2009-02-20 01:41:23 +0000 (Fri, 20 Feb 2009) Log Message: ----------- - upgraded pb-switching from static to dynamic (using template hackery) - added --use-pb - added batches of types, etc. - broke recovery; need to fix this/speed it up - updated ser; this was playground for moving to dynamic switching - fixed writer::show() - fixed start_op/txn and add_op/txn so that the start_ operations would initialize the counts to 0 - fixed the clamp preprocessing so as to separate the fwd decls from the defs - updated README with new TODOs Modified Paths: -------------- ydb/trunk/README ydb/trunk/src/Makefile ydb/trunk/src/main.lzz.clamp ydb/trunk/src/ser.cc ydb/trunk/src/ser.h Modified: ydb/trunk/README =================================================================== --- ydb/trunk/README 2009-02-19 23:02:34 UTC (rev 1203) +++ ydb/trunk/README 2009-02-20 01:41:23 UTC (rev 1204) @@ -391,9 +391,15 @@ Period 2/17- -- TODO dynamic switch between pb and zero-copy +- DONE removed class outstream +- TODO refactor st_reader, etc. to be generic opportunistic buffered readers +- TODO see how streambuf read/write is actually implemented (whether it's too + slow) +- TODO try making a streambuf for st_write, then try it in conj with + struct-less pb +- DONE dynamic switch between pb and zero-copy - TODO async (threaded) wal -- TODO 0-node 0-copy (need to use threads) +- TODO 0-node 0-copy (don't need to use threads, just process each batch immed) - TODO google dense hash map - TODO show aries-write Modified: ydb/trunk/src/Makefile =================================================================== --- ydb/trunk/src/Makefile 2009-02-19 23:02:34 UTC (rev 1203) +++ ydb/trunk/src/Makefile 2009-02-20 01:41:23 UTC (rev 1204) @@ -62,12 +62,10 @@ %.o: %.pb.cc %.pb.h $(CXX) -c $(PBCXXFLAGS) $(OUTPUT_OPTION) $< -%.cc: %.lzz +%.cc %.hh: %.lzz lzz -hx hh -sx cc -hl -sl -hd -sd $< + python -c 'pars = file("lambda_impl.clamp_h").read().split("\n\n"); hh = file("main.hh").read(); print >> file("main.cc", "a"), pars[-1]; print >> file("main.hh", "w"), "\n\n".join(pars[:-1] + [hh])' -%.hh: %.lzz - lzz -hx hh -sx cc -hl -sl -hd -sd $< - %.pb.cc: %.proto protoc --cpp_out=. $< @@ -75,7 +73,7 @@ protoc --cpp_out=. $< %.lzz: %.lzz.clamp - clamp < $< | sed "`echo -e '1i#src\n1a#end'`" > $@ + clamp < $< | sed '1d' > $@ main.o: ser.h Modified: ydb/trunk/src/main.lzz.clamp =================================================================== --- ydb/trunk/src/main.lzz.clamp 2009-02-19 23:02:34 UTC (rev 1203) +++ ydb/trunk/src/main.lzz.clamp 2009-02-20 01:41:23 UTC (rev 1204) @@ -28,14 +28,12 @@ #include <unistd.h> // pipe, write #include <vector> #include "ydb.pb.h" -//#define USE_PB #include "ser.h" #define function boost::function #define foreach BOOST_FOREACH #define shared_ptr boost::shared_ptr #define ref boost::ref -#define REUSE_SER using namespace boost; using namespace boost::archive; @@ -55,11 +53,8 @@ using ydb::pb::Init; using ydb::pb::Join; using ydb::pb::SockAddr; -#ifdef USE_PB using namespace ydb::pb; -#else using namespace ydb::msg; -#endif #define GETMSG(buf) \ checkeqnneg(st_read_fully(src, buf, len, timeout), (int) len); \ @@ -82,7 +77,7 @@ size_t accept_joiner_size, buf_size; bool verbose, yield_during_build_up, yield_during_catch_up, dump, show_updates, count_updates, stop_on_recovery, general_txns, profile_threads, - debug_threads, multirecover, disk, debug_memory, use_wal, + debug_threads, multirecover, disk, debug_memory, use_wal, use_pb, suppress_txn_msgs, use_bcast_async, fake_bcast, force_ser, fake_exec; long long timelim, read_thresh, write_thresh; @@ -534,10 +529,14 @@ /** * Keep issuing transactions to the replicas. */ +template<typename Types> void issue_txns(st_channel<replica_info> &newreps, int &seqno, st_bool &accept_joiner) { + typedef typename Types::TxnBatch TxnBatch; + typedef typename Types::Txn Txn; + typedef typename Types::Op Op; Op_OpType types[] = {Op::read, Op::write, Op::del}; vector<st_netfd_t> fds; @@ -566,7 +565,8 @@ checkeqnneg(st_write(dst, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); }, buf_size); stream s(r,w); - TxnBatch batch NPBONLY((s)); + scoped_ptr<TxnBatch> pbatch(new_TxnBatch<TxnBatch>(s)); + TxnBatch batch = *pbatch; for (int t = 0; t < batch_size; ++t) batch.add_txn(); while (!stop_hub) { @@ -589,12 +589,12 @@ } // Generate some random transactions. - NPBONLY(batch.start_txn()); + start_txn(batch); for (int t = 0; t < batch_size; ++t) { Txn &txn = *batch.add_txn(); txn.set_seqno(seqno); int count = randint(min_ops, max_ops + 1); - NPBONLY(txn.start_op()); + start_op(txn); for (int o = 0; o < count; ++o) { Op *op = txn.add_op(); int rtype = general_txns ? randint(3) : 1, @@ -604,12 +604,12 @@ op->set_key(rkey); op->set_value(rvalue); } - NPBONLY(txn.fin_op()); + fin_op(txn); // Process immediately if not bcasting. if (fds.empty()) { --seqno; - process_txn(g_map, txn, seqno, nullptr); + process_txn<Types>(g_map, txn, seqno, nullptr); } // Checkpoint. @@ -643,8 +643,8 @@ ++seqno; } - NPBONLY(batch.fin_txn()); - NPBONLY(if (batch.txn_size() == 0) w.reset()); + fin_txn(batch); + if (batch.txn_size() == 0) w.reset(); // Broadcast. #ifdef USE_PB @@ -669,13 +669,13 @@ // This means "The End." w.mark(); batch.Clear(); - NPBONLY(batch.start_txn()); + start_txn(batch); Txn &txn = *batch.add_txn(); txn.set_seqno(-1); - NPBONLY(txn.start_op()); - NPBONLY(txn.fin_op()); - NPBONLY(batch.fin_txn()); - PBONLY(bcastmsg(fds, batch)); + start_op(txn); + fin_op(txn); + fin_txn(batch); + if (Types::is_pb()) bcastmsg(fds, batch); w.mark(); w.flush(); } @@ -684,9 +684,12 @@ * Process a transaction: update DB state (incl. seqno) and send response to * leader. */ +template<typename Types> void -process_txn(mii &map, const Txn &txn, int &seqno, Response *res) +process_txn(mii &map, const typename Types::Txn &txn, int &seqno, Response *res) { + typedef typename Types::Txn Txn; + typedef typename Types::Op Op; //wal &wal = *g_wal; checkeq(txn.seqno(), seqno + 1); seqno = txn.seqno(); @@ -770,6 +773,17 @@ } #end +template<typename Txn> shared_ptr<ydb::pb::Txn> to_pb_Txn(Txn txn); +template<> shared_ptr<ydb::pb::Txn> to_pb_Txn(ydb::pb::Txn txn) { + return shared_ptr<ydb::pb::Txn>(new ydb::pb::Txn(txn)); +} +template<> shared_ptr<ydb::pb::Txn> to_pb_Txn(ydb::msg::Txn txn) { + shared_ptr<ydb::pb::Txn> ptxn(new ydb::pb::Txn()); + ptxn->set_seqno(txn.seqno()); + // XXX FIXME + return ptxn; +} + /** * Actually do the work of executing a transaction and sending back the reply. * @@ -795,12 +809,17 @@ * * \param[in] wal The WAL. */ +template<typename Types> void process_txns(st_netfd_t leader, mii &map, int &seqno, st_channel<shared_ptr<Recovery> > &send_states, - st_channel<shared_ptr<Txn> > &backlog, int init_seqno, + st_channel<shared_ptr<ydb::pb::Txn> > &backlog, int init_seqno, int mypos, int nnodes) { + typedef typename Types::TxnBatch TxnBatch; + typedef typename Types::Txn Txn; + typedef typename Types::Op Op; + bool caught_up = init_seqno == 0; long long start_time = current_time_millis(), time_caught_up = caught_up ? start_time : -1; @@ -829,7 +848,8 @@ stream s(reader, w); try { - TxnBatch batch NPBONLY((s)); + scoped_ptr<TxnBatch> pbatch(new_TxnBatch<TxnBatch>(s)); + TxnBatch batch = *pbatch; ResponseBatch resbatch; while (true) { long long before_read = -1; @@ -838,8 +858,8 @@ } { st_intr intr(stop_hub); - PBONLY(readmsg(reader, batch)); - NPBONLY(batch.Clear()); + if (Types::is_pb()) readmsg(reader, batch); + else batch.Clear(); } if (read_thresh > 0) { long long read_time = current_time_millis() - before_read; @@ -866,13 +886,14 @@ caught_up = true; } Response *res = resbatch.add_res(); - process_txn(map, txn, seqno, res); + process_txn<Types>(map, txn, seqno, res); action = "processed"; } else { if (first_seqno == -1) first_seqno = txn.seqno(); // Queue up for later processing once a snapshot has been received. - backlog.push(shared_ptr<Txn>(new Txn(txn))); + // XXX + backlog.push(to_pb_Txn(txn)); action = "backlogged"; } @@ -1158,8 +1179,9 @@ st_bool accept_joiner; int seqno = 0; st_channel<replica_info> newreps; - const function0<void> f = bind(issue_txns, ref(newreps), ref(seqno), - ref(accept_joiner)); + const function<void()> f = use_pb ? + bind(issue_txns<pb_types>, ref(newreps), ref(seqno), ref(accept_joiner)) : + bind(issue_txns<rb_types>, ref(newreps), ref(seqno), ref(accept_joiner)); st_thread_t swallower = my_spawn(bind(swallow, f), "issue_txns"); foreach (const replica_info &r, replicas) newreps.push(r); st_joining join_swallower(swallower); @@ -1302,12 +1324,15 @@ } // Process txns. - st_channel<shared_ptr<Txn> > backlog; - st_joining join_proc(my_spawn(bind(process_txns, leader, ref(map), - ref(seqno), ref(send_states), - ref(backlog), init.txnseqno(), - mypos, init.node_size()), - "process_txns")); + st_channel<shared_ptr<ydb::pb::Txn> > backlog; + const function<void()> process_fn = use_pb ? + bind(process_txns<pb_types>, leader, ref(map), ref(seqno), + ref(send_states), ref(backlog), init.txnseqno(), mypos, + init.node_size()) : + bind(process_txns<rb_types>, leader, ref(map), ref(seqno), + ref(send_states), ref(backlog), init.txnseqno(), mypos, + init.node_size()); + st_joining join_proc(my_spawn(process_fn, "process_txns")); st_joining join_rec(my_spawn(bind(recover_joiner, listener, ref(map), ref(seqno), ref(send_states)), "recover_joiner")); @@ -1361,8 +1386,9 @@ int mid_seqno = seqno; while (!backlog.empty()) { + using ydb::pb::Txn; shared_ptr<Txn> p = backlog.take(); - process_txn(map, *p, seqno, nullptr); + process_txn<pb_types>(map, *p, seqno, nullptr); if (p->seqno() % chkpt == 0) { if (verbose) cout << "processed txn " << p->seqno() << " off the backlog; " @@ -1488,6 +1514,8 @@ "count operations that touch (update/read/delete) an existing key") ("general-txns,g", po::bool_switch(&general_txns), "issue read and delete transactions as well as the default of (only) insertion/update transactions (for leader only)") + ("use-pb", po::bool_switch(&use_pb), + "use protocol buffers instead of raw buffers") ("wal", po::bool_switch(&use_wal), "enable ARIES write-ahead logging") ("force-ser", po::bool_switch(&force_ser), Modified: ydb/trunk/src/ser.cc =================================================================== --- ydb/trunk/src/ser.cc 2009-02-19 23:02:34 UTC (rev 1203) +++ ydb/trunk/src/ser.cc 2009-02-20 01:41:23 UTC (rev 1204) @@ -1,17 +1,11 @@ #include "ser.h" #include <commons/st/st.h> +#include <boost/scoped_ptr.hpp> -//#define USE_PB -using ydb::msg::reader; -using ydb::msg::writer; -using ydb::msg::stream; using namespace commons; using namespace std; -#ifdef USE_PB +using namespace ydb::msg; using namespace ydb::pb; -#else -using namespace ydb::msg; -#endif const int nreps = 2; @@ -22,13 +16,18 @@ public: outstream(const vector<st_netfd_t> &dsts) : dsts(dsts) {} void operator()(const void *buf, size_t len) { + cout << "writing " << len << endl; foreach (st_netfd_t dst, dsts) checkeqnneg(st_write(dst, buf, len, ST_UTIME_NO_TIMEOUT), ssize_t(len)); } }; +template<typename types> void producer(st_netfd_t dst) { + typedef typename types::TxnBatch TxnBatch; + typedef typename types::Txn Txn; + typedef typename types::Op Op; vector<st_netfd_t> dsts(1, dst); outstream os(dsts); writer w(os, 90); @@ -36,48 +35,56 @@ stream s(r,w); string str; const bool show = true; - TxnBatch batch NPBONLY((s)); + scoped_ptr<TxnBatch> p(new_TxnBatch<TxnBatch>(s)); + TxnBatch &batch = *p; for (int i = 0; i < nreps; ++i) { w.mark(); batch.Clear(); - NPBONLY(batch.start_txn()); + start_txn(batch); for (int t = 0; t < 2; ++t) { Txn &txn = *batch.add_txn(); txn.set_seqno(t + 5); - NPBONLY(txn.start_op()); + start_op(txn); for (int o = 0; o < 2; ++o) { Op &op = *txn.add_op(); op.set_type (Op::del); op.set_key (3 * (o+1)); op.set_value(4 * (o+1)); } - NPBONLY(txn.fin_op()); + fin_op(txn); } - NPBONLY(batch.fin_txn()); + fin_txn(batch); if (show) cout << w.pos() << '/' << w.size() << endl; - PBONLY(check(batch.SerializeToString(&str))); + ser(batch, str); } batch.Clear(); - NPBONLY(batch.start_txn()); - NPBONLY(batch.fin_txn()); + start_txn(batch); + fin_txn(batch); w.mark(); + w.show(); w.flush(); } +template<typename types> void consumer(st_netfd_t src) { + typedef typename types::TxnBatch TxnBatch; + typedef typename types::Txn Txn; + typedef typename types::Op Op; vector<st_netfd_t> v; outstream os(v); writer w(os, 90); reader r(src); stream s(r,w); + string str; // XXX const bool show = true; - TxnBatch batch NPBONLY((s)); - for (int i = 0; i < nreps; ++i) { + scoped_ptr<TxnBatch> p(new_TxnBatch<TxnBatch>(s)); + TxnBatch &batch = *p; + while (true) { batch.Clear(); - PBONLY(check(batch.ParseFromString(str))); + parse(batch, str); if (show) cout << "ntxn " << batch.txn_size() << endl; - //if (batch.txn_size() == 0) break; + if (batch.txn_size() == 0) break; for (int t = 0; t < batch.txn_size(); ++t) { const Txn &txn = batch.txn(t); if (show) cout << "txn seqno " << txn.seqno() << " " << txn.seqno() << endl; @@ -98,15 +105,22 @@ int main(int argc, char **argv) { st_init(); - bool is_leader = argc == 1; + bool use_pb = argc > 1 && string("-p") == argv[1]; + bool is_leader = argc == (use_pb ? 2 : 1); if (is_leader) { st_netfd_t listener = st_tcp_listen(7654); st_netfd_t dst = checkerr(st_accept(listener, nullptr, nullptr, ST_UTIME_NO_TIMEOUT)); - producer(dst); + if (use_pb) + producer<pb_types>(dst); + else + producer<rb_types>(dst); } else { st_netfd_t src = st_tcp_connect(argv[1], 7654, ST_UTIME_NO_TIMEOUT); - consumer(src); + if (use_pb) + consumer<pb_types>(src); + else + consumer<rb_types>(src); } return 0; } Modified: ydb/trunk/src/ser.h =================================================================== --- ydb/trunk/src/ser.h 2009-02-19 23:02:34 UTC (rev 1203) +++ ydb/trunk/src/ser.h 2009-02-20 01:41:23 UTC (rev 1204) @@ -7,16 +7,6 @@ #include <iostream> #include "ydb.pb.h" -#ifdef USE_PB -#define PBSWITCH(a,b) a -#define PBONLY(x) x -#define NPBONLY(x) -#else -#define PBSWITCH(a,b) b -#define PBONLY(x) -#define NPBONLY(x) x -#endif - #define BEGIN_NAMESPACE(ns) namespace ns { #define END_NAMESPACE } @@ -75,7 +65,7 @@ void show() { cout << (void*) p_; for (size_t i = 0; i < a_.size(); ++i) - cout << " " << hex << setfill('0') << setw(2) << int(mark_[i]); + cout << " " << hex << setfill('0') << setw(2) << (int)(unsigned char)(a_.get()[i]); cout << endl; cout << (void*) p_; for (size_t i = 0; i < a_.size(); ++i) @@ -136,8 +126,8 @@ void Clear() { w_.reserve(0*50); nop_ = unset; seqno_ = unset; off_ = w_.pos(); } void set_seqno(int x) { w_.write(x); } int seqno() const { return seqno_ == unset ? seqno_ = r_.read<int>() : seqno_; } - void start_op() { w_.skip<typeof(nop_)>(); } - Op *add_op() { if (nop_ == unset) nop_ = 0; ++nop_; return &op_; } + void start_op() { if (nop_ == unset) nop_ = 0; w_.skip<typeof(nop_)>(); } + Op *add_op() { ++nop_; return &op_; } void fin_op() { w_.write(nop_, off_ + sizeof(int)); } int op_size() const { if (nop_ == unset) nop_ = r_.read<typeof(nop_)>(); return nop_; } const Op &op(int o) const { return op_; } @@ -155,8 +145,8 @@ public: TxnBatch(stream &s) : s_(s), r_(s.get_reader()), w_(s.get_writer()), off_(w_.pos()), txn_(s), ntxn_(unset) {} void Clear() { w_.reserve(0*100); txn_.Clear(); ntxn_ = unset; off_ = w_.pos(); } - void start_txn() { w_.skip<typeof(ntxn_)>(); } - Txn *add_txn() { if (ntxn_ == unset) ntxn_ = 0; ++ntxn_; txn_.Clear(); return &txn_; } + void start_txn() { if (ntxn_ == unset) ntxn_ = 0; w_.skip<typeof(ntxn_)>(); } + Txn *add_txn() { ++ntxn_; txn_.Clear(); return &txn_; } void fin_txn() { w_.write(ntxn_, off_); } int txn_size() const { if (ntxn_ == unset) @@ -167,8 +157,52 @@ bool AppendToString(string *s) const { throw std::exception(); } bool SerializeToString(string *s) const { throw std::exception(); } bool SerializeToOstream(ostream *s) const { throw std::exception(); } + bool ParseFromArray(void *p, size_t len) { throw std::exception(); } }; +template<typename T> void parse(T &batch, const string &str); +template<> void parse(ydb::pb::TxnBatch &batch, const string &str) { check(batch.ParseFromString(str)); } +template<> void parse(ydb::msg::TxnBatch &batch, const string &str) {} + +template<typename T> void ser(T &batch, string &str); +template<> void ser(ydb::pb::TxnBatch &batch, string &str) { check(batch.SerializeToString(&str)); } +template<> void ser(ydb::msg::TxnBatch &batch, string &str) {} + +template<typename T> void start_txn(T &batch); +template<> void start_txn(ydb::pb::TxnBatch &batch) {} +template<> void start_txn(ydb::msg::TxnBatch &batch) { batch.start_txn(); } + +template<typename T> void fin_txn(T &batch); +template<> void fin_txn(ydb::pb::TxnBatch &batch) {} +template<> void fin_txn(ydb::msg::TxnBatch &batch) { batch.fin_txn(); } + +template<typename T> void start_op(T &txn); +template<> void start_op(ydb::pb::Txn &txn) {} +template<> void start_op(ydb::msg::Txn &txn) { txn.start_op(); } + +template<typename T> void fin_op(T &txn); +template<> void fin_op(ydb::pb::Txn &txn) {} +template<> void fin_op(ydb::msg::Txn &txn) { txn.fin_op(); } + +template<typename T> T *new_TxnBatch(stream &s); +template<> ydb::pb::TxnBatch *new_TxnBatch(stream &s) { return new ydb::pb::TxnBatch(); } +template<> ydb::msg::TxnBatch *new_TxnBatch(stream &s) { return new ydb::msg::TxnBatch(s); } + +struct pb_types { + typedef ydb::pb::TxnBatch TxnBatch; + typedef ydb::pb::Txn Txn; + typedef ydb::pb::Op Op; + static bool is_pb() { return true; } +}; + +// rb = raw buffer +struct rb_types { + typedef ydb::msg::TxnBatch TxnBatch; + typedef ydb::msg::Txn Txn; + typedef ydb::msg::Op Op; + static bool is_pb() { return false; } +}; + END_NAMESPACE END_NAMESPACE This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-02-19 23:15:10
|
Revision: 1203 http://assorted.svn.sourceforge.net/assorted/?rev=1203&view=rev Author: yangzhang Date: 2009-02-19 23:02:34 +0000 (Thu, 19 Feb 2009) Log Message: ----------- added fn ptrs bug demo Added Paths: ----------- sandbox/trunk/src/cc/lzz/fnptrs.lzz sandbox/trunk/src/cc/lzz/fnptrs.mk Added: sandbox/trunk/src/cc/lzz/fnptrs.lzz =================================================================== --- sandbox/trunk/src/cc/lzz/fnptrs.lzz (rev 0) +++ sandbox/trunk/src/cc/lzz/fnptrs.lzz 2009-02-19 23:02:34 UTC (rev 1203) @@ -0,0 +1,5 @@ +// lzz 2.8.0 doesn't work with function pointers. +// fnptrs.lzz:1:21: Syntax error before 'int'. +// fnptrs.lzz:1:24: Inserting '<identifier>' before ')'. +struct C { int (*f)(int); }; +int main() { return 0; } Added: sandbox/trunk/src/cc/lzz/fnptrs.mk =================================================================== --- sandbox/trunk/src/cc/lzz/fnptrs.mk (rev 0) +++ sandbox/trunk/src/cc/lzz/fnptrs.mk 2009-02-19 23:02:34 UTC (rev 1203) @@ -0,0 +1,3 @@ +all: fnptrs +fnptrs.cc: fnptrs.lzz + lzz -hx hh -sx cc -hl -sl -hd -sd $< This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |