Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #5850 > unrolled thread
| Started by | jakash3 <jakashthree@gmail.com> |
|---|---|
| First post | 2011-05-30 16:29 -0700 |
| Last post | 2011-06-01 03:16 -0700 |
| Articles | 16 — 9 participants |
Back to article view | Back to comp.lang.c++
pthread memory leaks jakash3 <jakashthree@gmail.com> - 2011-05-30 16:29 -0700
Re: pthread memory leaks Ian Collins <ian-news@hotmail.com> - 2011-05-31 11:50 +1200
Re: pthread memory leaks Ian Collins <ian-news@hotmail.com> - 2011-05-31 11:52 +1200
Re: pthread memory leaks Puppet_Sock <puppet_sock@hotmail.com> - 2011-05-31 06:46 -0700
Re: pthread memory leaks jakash3 <jakashthree@gmail.com> - 2011-05-30 17:00 -0700
Re: pthread memory leaks Ian Collins <ian-news@hotmail.com> - 2011-05-31 12:02 +1200
Re: pthread memory leaks jakash3 <jakashthree@gmail.com> - 2011-05-30 17:05 -0700
Re: pthread memory leaks yatremblay@bel1lin202.(none) (Yannick Tremblay) - 2011-06-06 09:38 +0000
Re: pthread memory leaks Stuart Redmann <DerTopper@web.de> - 2011-05-31 00:16 -0700
Re: pthread memory leaks "Chris M. Thomasson" <cristom@charter.net> - 2011-06-10 15:46 -0700
Re: pthread memory leaks Adam Skutt <askutt@gmail.com> - 2011-05-31 03:20 -0700
Re: pthread memory leaks Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-06-01 08:27 +0000
Re: pthread memory leaks Miles Bader <miles@gnu.org> - 2011-06-01 17:39 +0900
Re: pthread memory leaks Ian Collins <ian-news@hotmail.com> - 2011-06-01 21:05 +1200
Re: pthread memory leaks Adam Skutt <askutt@gmail.com> - 2011-06-01 03:27 -0700
Re: pthread memory leaks Adam Skutt <askutt@gmail.com> - 2011-06-01 03:16 -0700
| From | jakash3 <jakashthree@gmail.com> |
|---|---|
| Date | 2011-05-30 16:29 -0700 |
| Subject | pthread memory leaks |
| Message-ID | <9430fe32-d385-49a3-b925-daf3cd421789@j13g2000pro.googlegroups.com> |
I'm experimenting with signals and conditional variables to implement
thread suspension. The following appears to execute without any
problems but valgrind reports memory leaks.
What can I do to stop the memory leaks? Is there some type of pthread
related memory free function I'm forgetting?
=================================
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
pthread_mutex_t m;
pthread_cond_t c;
void freeze(int sig) {
pthread_mutex_lock(&m);
pthread_cond_wait(&c, &m);
pthread_mutex_unlock(&m);
}
void quit(int sig) { pthread_exit(0); }
void* tfunc(void* param) {
while (1) {
puts("hi");
sleep(1);
}
return NULL;
}
int main() {
pthread_mutex_init(&m, NULL);
pthread_cond_init(&c, NULL);
struct sigaction s;
memset(&s, 0, sizeof(struct sigaction));
/*
* SIGUSR1 signal for thread suspend
* and SIGUSR2 signal for thread exit
*/
s.sa_handler = &freeze;
s.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1, &s, NULL);
s.sa_handler = &quit;
sigaction(SIGUSR2, &s, NULL);
pthread_t t;
pthread_create(&t, NULL, &tfunc, (void*)NULL);
pthread_detach(t);
getchar();
/* suspend */
pthread_kill(t, SIGUSR1);
getchar();
/* resume */
pthread_cond_signal(&c);
getchar();
/* terminate */
pthread_kill(t, SIGUSR2);
pthread_mutex_destroy(&m);
pthread_cond_destroy(&c);
return 0;
}
=================================
valgrind output:
=================================
==2993==
==2993== HEAP SUMMARY:
==2993== in use at exit: 144 bytes in 1 blocks
==2993== total heap usage: 1 allocs, 0 frees, 144 bytes allocated
==2993==
==2993== LEAK SUMMARY:
==2993== definitely lost: 0 bytes in 0 blocks
==2993== indirectly lost: 0 bytes in 0 blocks
==2993== possibly lost: 144 bytes in 1 blocks
==2993== still reachable: 0 bytes in 0 blocks
==2993== suppressed: 0 bytes in 0 blocks
==2993== Rerun with --leak-check=full to see details of leaked memory
==2993==
==2993== For counts of detected and suppressed errors, rerun with: -v
==2993== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 21 from
8)
=================================
[toc] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-05-31 11:50 +1200 |
| Message-ID | <94ioqnFr2iU10@mid.individual.net> |
| In reply to | #5850 |
On 05/31/11 11:29 AM, jakash3 wrote:
> I'm experimenting with signals and conditional variables to implement
> thread suspension. The following appears to execute without any
> problems but valgrind reports memory leaks.
> What can I do to stop the memory leaks? Is there some type of pthread
> related memory free function I'm forgetting?
You'd be better of on a Linux or Unix group for this kind of question.
However there are a few C++ specific issues:
> =================================
> #include<pthread.h>
> #include<signal.h>
> #include<unistd.h>
> #include<cstdio>
> #include<cstring>
> #include<cstdlib>
>
> pthread_mutex_t m;
> pthread_cond_t c;
>
> void freeze(int sig) {
> pthread_mutex_lock(&m);
> pthread_cond_wait(&c,&m);
> pthread_mutex_unlock(&m);
> }
> void quit(int sig) { pthread_exit(0); }
>
> void* tfunc(void* param) {
> while (1) {
> puts("hi");
As you have included the C++ versions of the C library headers, fictions
form them like puts should be written std::puts. Some compilers put
them in the namespace, while others (like gcc) declare them in and out
of the namespace, which is a pain.
> sleep(1);
> }
> return NULL;
> }
This are all assigned to C function pointers, so they should be declared
as extern "C" (gcc ignores this).
<snip code>
> valgrind output:
> =================================
> ==2993==
> ==2993== HEAP SUMMARY:
> ==2993== in use at exit: 144 bytes in 1 blocks
> ==2993== total heap usage: 1 allocs, 0 frees, 144 bytes allocated
> ==2993==
> ==2993== LEAK SUMMARY:
> ==2993== definitely lost: 0 bytes in 0 blocks
> ==2993== indirectly lost: 0 bytes in 0 blocks
> ==2993== possibly lost: 144 bytes in 1 blocks
Note this is an in use block, not an actual leak. Probably an internal
I/O buffer.
--
Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-05-31 11:52 +1200 |
| Message-ID | <94ioujFr2iU11@mid.individual.net> |
| In reply to | #5851 |
On 05/31/11 11:50 AM, Ian Collins wrote: > As you have included the C++ versions of the C library headers, fictions fictions? functions! -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Puppet_Sock <puppet_sock@hotmail.com> |
|---|---|
| Date | 2011-05-31 06:46 -0700 |
| Message-ID | <1eb1d378-5f2a-49c4-a1ce-dc8d371896a2@w21g2000yqm.googlegroups.com> |
| In reply to | #5852 |
On May 30, 7:52 pm, Ian Collins <ian-n...@hotmail.com> wrote: > On 05/31/11 11:50 AM, Ian Collins wrote: > > > As you have included the C++ versions of the C library headers, fictions > > fictions? functions! Dram spall chucker. Socks
[toc] | [prev] | [next] | [standalone]
| From | jakash3 <jakashthree@gmail.com> |
|---|---|
| Date | 2011-05-30 17:00 -0700 |
| Message-ID | <078e7033-8005-41c3-a075-d77815d10cdd@e17g2000prj.googlegroups.com> |
| In reply to | #5851 |
On May 30, 4:50 pm, Ian Collins <ian-n...@hotmail.com> wrote: > > Note this is an in use block, not an actual leak. Probably an internal > I/O buffer. > > -- > Ian Collins Thank you for responding. You're right, I didn't look at the output close enough. It reported 144 bytes possibly, not definitely, lost. This is good, because I'm making a posix/win32 class for multithreading.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-05-31 12:02 +1200 |
| Message-ID | <94iph6Fr2iU12@mid.individual.net> |
| In reply to | #5853 |
On 05/31/11 12:00 PM, jakash3 wrote: > On May 30, 4:50 pm, Ian Collins<ian-n...@hotmail.com> wrote: >> >> Note this is an in use block, not an actual leak. Probably an internal >> I/O buffer. > > Thank you for responding. > You're right, I didn't look at the output close enough. It reported > 144 bytes possibly, not definitely, lost. > This is good, because I'm making a posix/win32 class for > multithreading. Have you looked at boost thread? -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | jakash3 <jakashthree@gmail.com> |
|---|---|
| Date | 2011-05-30 17:05 -0700 |
| Message-ID | <b5371b7f-e6cb-4da7-92db-87944822be69@s16g2000prf.googlegroups.com> |
| In reply to | #5854 |
On May 30, 5:02 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> Have you looked at boost thread?
>
> --
> Ian Collins
Yes, It doesn't appear to have thread suspension. I hope to implement
this for my thread class:
class Thread {
public:
#ifdef _WIN32
HANDLE tid;
#else
pthread_t tid;
#endif
void* (*sub)(void*);
Thread();
~Thread();
Thread(void* (*tfunc)(void*));
Thread& operator= (void* (*tfunc)(void*));
Thread& operator= (Thread t);
bool operator!= (void* (*tfunc)(void*));
bool operator!= (Thread t);
bool operator== (void* (*tfunc)(void*));
bool operator== (Thread t);
bool start(void* param = 0);
void* term(void* (*quit)(void*) = 0, void* param = 0);
bool stop();
bool cont();
bool join(void ** ret);
};
[toc] | [prev] | [next] | [standalone]
| From | yatremblay@bel1lin202.(none) (Yannick Tremblay) |
|---|---|
| Date | 2011-06-06 09:38 +0000 |
| Message-ID | <isi770$ade$1@dont-email.me> |
| In reply to | #5855 |
In article <b5371b7f-e6cb-4da7-92db-87944822be69@s16g2000prf.googlegroups.com>,
jakash3 <jakashthree@gmail.com> wrote:
>On May 30, 5:02 pm, Ian Collins <ian-n...@hotmail.com> wrote:
>> Have you looked at boost thread?
>>
>Yes, It doesn't appear to have thread suspension. I hope to implement
>this for my thread class:
Boost thread has designed decisions in its interface. I would say
that most of these design decisions are to encourage the users
to use multi-threading in a saner and safer manner than when starting
with the full low-level capabilities of pthread or Windows threads.
For example:
>class Thread {
>public:
>#ifdef _WIN32
> HANDLE tid;
>#else
> pthread_t tid;
>#endif
> void* (*sub)(void*);
> Thread();
> ~Thread();
> Thread(void* (*tfunc)(void*));
> Thread& operator= (void* (*tfunc)(void*));
> Thread& operator= (Thread t);
Please clarify what you intend here? Is this a normal assignment
operator? If so, what does it mean to "assign" an existing thread to
another?
You are defining an operator= without defining a copy-constructor
which is a typical no-no, unless you really can explain why.
If you define a copy-constructor, you also need to really understand
what it means.
Note: boost thread clearly define them as move operations, not copies.
And you would probably need to either pass by reference or need that
copy constructor.
> bool operator!= (void* (*tfunc)(void*));
> bool operator!= (Thread t);
> bool operator== (void* (*tfunc)(void*));
> bool operator== (Thread t);
> bool start(void* param = 0);
> void* term(void* (*quit)(void*) = 0, void* param = 0);
> bool stop();
> bool cont();
> bool join(void ** ret);
>};
[toc] | [prev] | [next] | [standalone]
| From | Stuart Redmann <DerTopper@web.de> |
|---|---|
| Date | 2011-05-31 00:16 -0700 |
| Message-ID | <cb777f8c-9047-4e8d-9f75-00e6c7048999@l18g2000yql.googlegroups.com> |
| In reply to | #5850 |
On 31 Mai, 01:29, jakash3 wrote: > I'm experimenting with signals and conditional variables to implement > thread suspension. [snip] Just out of curiosity: When I tried to write some platform-independent code that worked with multiple threads I was quite amazed that there is no equivalent for Win32 Events under Unix. I guess that this is the problem you are trying to deal with? (sorry, I know too little of the pthread API to fully understand your code) Thanks, Stuart
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <cristom@charter.net> |
|---|---|
| Date | 2011-06-10 15:46 -0700 |
| Message-ID | <j9xIp.2221$x11.2108@newsfe09.iad> |
| In reply to | #5889 |
"Stuart Redmann" <DerTopper@web.de> wrote in message
news:cb777f8c-9047-4e8d-9f75-00e6c7048999@l18g2000yql.googlegroups.com...
> On 31 Mai, 01:29, jakash3 wrote:
>> I'm experimenting with signals and conditional variables to implement
>> thread suspension.
>
> [snip]
>
> Just out of curiosity: When I tried to write some platform-independent
> code that worked with multiple threads I was quite amazed that there
> is no equivalent for Win32 Events under Unix.
FWIW, Windows events can be emulated under POSIX Threads...
> I guess that this is the
> problem you are trying to deal with? (sorry, I know too little of the
> pthread API to fully understand your code)
IPC aside for a moment, one could try something simple like the following
pseudo-code for a windows auto-reset event:
_______________________________________________________
struct win_auto_reset_event
{
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
bool m_set; // = true/false
void set()
{
pthread_mutex_lock(&m_mutex);
m_set = true;
pthread_mutex_unlock(&m_mutex);
pthread_cond_signal(&m_cond);
}
void wait()
{
pthread_mutex_lock(&m_mutex);
while (! m_set) pthread_cond_wait(&m_cond, &m_mutex);
m_set = false;
pthread_mutex_unlock(&m_mutex);
}
};
_______________________________________________________
and this pseudo-code for a windows manual-reset event:
_______________________________________________________
struct win_manual_reset_event
{
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
bool m_set; // = true/false
void set()
{
pthread_mutex_lock(&m_mutex);
m_set = true;
pthread_mutex_unlock(&m_mutex);
pthread_cond_broadcast(&m_cond);
}
void reset()
{
pthread_mutex_lock(&m_mutex);
m_set = false;
pthread_mutex_unlock(&m_mutex);
}
void wait()
{
pthread_mutex_lock(&m_mutex);
while (! m_set) pthread_cond_wait(&m_cond, &m_mutex);
pthread_mutex_unlock(&m_mutex);
}
};
_______________________________________________________
[toc] | [prev] | [next] | [standalone]
| From | Adam Skutt <askutt@gmail.com> |
|---|---|
| Date | 2011-05-31 03:20 -0700 |
| Message-ID | <211062bc-81c2-40d2-b6f2-ebd587ff179c@n10g2000vby.googlegroups.com> |
| In reply to | #5850 |
On May 30, 7:29 pm, jakash3 <jakashth...@gmail.com> wrote: > I'm experimenting with signals and conditional variables to implement > thread suspension. Don't. It will only work on Linux, and even then, you'll run into many subtle and difficult to debug issues. Threads and signals simply do not mix, period. Even if you get your internal signal delivery working, you still have to make sure you properly cope with externally delivered signals as well, which can be tricky or outright impossible. As an added bonus, I'm ignoring the inherit difficult of writing correct threaded code with shared state where you can arbitrarily suspend processes. For example, what happens if you're holding a mutex and get sent the suspend signal? If you don't block it while holding the mutex, your code will deadlock. Make sure you really need suspension before you proceed further (legitimate cases for halting execution in this fashion are rare). If you really need it, make sure it cannot be done cooperatively or in another fashion. If you absolutely must have suspension, the only reliable way to do is to switch to a multi-process model and use the builtin SIGSTOP / SIGCONT signals. Note that even those may not quite work in the way you expect. > > valgrind output: > ================================= > ==2993== > ==2993== HEAP SUMMARY: > ==2993== in use at exit: 144 bytes in 1 blocks > ==2993== total heap usage: 1 allocs, 0 frees, 144 bytes allocated > ==2993== > ==2993== LEAK SUMMARY: > ==2993== definitely lost: 0 bytes in 0 blocks > ==2993== indirectly lost: 0 bytes in 0 blocks > ==2993== possibly lost: 144 bytes in 1 blocks > ==2993== still reachable: 0 bytes in 0 blocks > ==2993== suppressed: 0 bytes in 0 blocks > ==2993== Rerun with --leak-check=full to see details of leaked memory > ==2993== > ==2993== For counts of detected and suppressed errors, rerun with: -v > ==2993== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 21 from > 8) > ================================= Your code doesn't have any obvious memory leaks. I'm pretty sure the 144 bytes in question are TLS releated. glibc is awful about cleaning up after its own messes. Adam
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2011-06-01 08:27 +0000 |
| Message-ID | <slrniubtuo.gtj.grahn+nntp@frailea.sa.invalid> |
| In reply to | #5896 |
On Tue, 2011-05-31, Adam Skutt wrote: > On May 30, 7:29 pm, jakash3 <jakashth...@gmail.com> wrote: >> I'm experimenting with signals and conditional variables to implement >> thread suspension. > > Don't. It will only work on Linux, and even then, you'll run into > many subtle and difficult to debug issues. Threads and signals simply > do not mix, period. Even if you get your internal signal delivery > working, you still have to make sure you properly cope with externally > delivered signals as well, which can be tricky or outright > impossible. A short offtopic question to that: with signals being such an integral part of Linux, aren't you really saying Linux and threads don't mix? Or are you taking differences beween Linux and other Unixes into account here? I'm asking because I recently read an article where the author asserted that mixing signals and pthreads [specifically on Linux] is much simpler than people think. (No, I don't have the URL handy, and no, I don't trust that author absolutely.) /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o .
[toc] | [prev] | [next] | [standalone]
| From | Miles Bader <miles@gnu.org> |
|---|---|
| Date | 2011-06-01 17:39 +0900 |
| Message-ID | <buovcwq54ir.fsf@dhlpc061.dev.necel.com> |
| In reply to | #5945 |
Jorgen Grahn <grahn+nntp@snipabacken.se> writes: > A short offtopic question to that: with signals being such an integral > part of Linux, aren't you really saying Linux and threads don't mix? > Or are you taking differences beween Linux and other Unixes into > account here? AFAIK, it's not that you can't use them together at all, it's just that you have to be aware of certain limitations on what is guaranteed (so relying on what seems to happen in practice on a given implementation might not be very portable). Signals are a "rough" tool, threads are a "fine" one, and the intersection is a bit fuzzy... if fuzzy's OK, then no prob, but... -miles -- Dictionary, n. A malevolent literary device for cramping the growth of a language and making it hard and inelastic. This dictionary, however, is a most useful work.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-06-01 21:05 +1200 |
| Message-ID | <94mdmsF12lU6@mid.individual.net> |
| In reply to | #5945 |
On 06/ 1/11 08:27 PM, Jorgen Grahn wrote: > On Tue, 2011-05-31, Adam Skutt wrote: >> On May 30, 7:29 pm, jakash3<jakashth...@gmail.com> wrote: >>> I'm experimenting with signals and conditional variables to implement >>> thread suspension. >> >> Don't. It will only work on Linux, and even then, you'll run into >> many subtle and difficult to debug issues. Threads and signals simply >> do not mix, period. Even if you get your internal signal delivery >> working, you still have to make sure you properly cope with externally >> delivered signals as well, which can be tricky or outright >> impossible. > > A short offtopic question to that: with signals being such an integral > part of Linux, aren't you really saying Linux and threads don't mix? > Or are you taking differences beween Linux and other Unixes into > account here? Maybe you are think of the older Linux Threads (where a thread was process), used before Linux adopted POSIX threads? > I'm asking because I recently read an article where the author > asserted that mixing signals and pthreads [specifically on Linux] is > much simpler than people think. (No, I don't have the URL handy, and > no, I don't trust that author absolutely.) It generally is, just so long as you don't try and use any pthread call in a signal handler! One of the most convenient uses is to dedicate a thread to handling the process' signals. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Adam Skutt <askutt@gmail.com> |
|---|---|
| Date | 2011-06-01 03:27 -0700 |
| Message-ID | <08bc7438-ecdf-4c28-bb19-8c3524b07c84@l6g2000vbn.googlegroups.com> |
| In reply to | #5950 |
On Jun 1, 5:05 am, Ian Collins <ian-n...@hotmail.com> wrote: > It generally is, just so long as you don't try and use any pthread call > in a signal handler! One of the most convenient uses is to dedicate a > thread to handling the process' signals. Which is great if you just want to ensure external signals get consistently directed to a safe place. It doesn't solve the problem in general, however, and doesn't enable the use of signals for inter- thread communication like the original posted wished to do. Adam
[toc] | [prev] | [next] | [standalone]
| From | Adam Skutt <askutt@gmail.com> |
|---|---|
| Date | 2011-06-01 03:16 -0700 |
| Message-ID | <0821ea81-36a8-493f-8248-ecee38956fb8@v31g2000vbs.googlegroups.com> |
| In reply to | #5945 |
On Jun 1, 4:27 am, Jorgen Grahn <grahn+n...@snipabacken.se> wrote: > On Tue, 2011-05-31, Adam Skutt wrote: > > On May 30, 7:29 pm, jakash3 <jakashth...@gmail.com> wrote: > >> I'm experimenting with signals and conditional variables to implement > >> thread suspension. > > > Don't. It will only work on Linux, and even then, you'll run into > > many subtle and difficult to debug issues. Threads and signals simply > > do not mix, period. Even if you get your internal signal delivery > > working, you still have to make sure you properly cope with externally > > delivered signals as well, which can be tricky or outright > > impossible. > > A short offtopic question to that: with signals being such an integral > part of Linux, aren't you really saying Linux and threads don't mix? > Or are you taking differences beween Linux and other Unixes into > account here? Nope, I'm saying you get to pick one of the two features and use that feature and not the other. Threads are fine. Signals are fine. Both is a recipe for disaster. Moreover, even if you get it working on Linux, it probably won't work well on any other UNIX. Signal handling semantics for threads are horribly ill defined in several ways: * Systems are free to use certain signals to implement threading functionality, but there's no way to figure out what they are at runtime. * The behavior between cancellation and signal handling is terribly ill-defined. Even Linux has races here that can cause the cancellation to get lost. It also radically alters what you can and cannot do in a signal handler. Cancellation is probably best avoided in C++ anyway (it's incompatible with exceptions and RAII), but it serves to illustrate the problem, and some of the signal issues occur even when not using cancellation. http://www.slamb.org/projects/cancellation_tests/ contains a brief summary of the issues. * Historical bugs and other implementation issues, like the LinuxThreads signal alt stack bug, which means signals have to be masked out whenever you call pthread_create() until the child thread creates its own alt stack. Good luck tracking all of these issues down. > > I'm asking because I recently read an article where the author > asserted that mixing signals and pthreads [specifically on Linux] is > much simpler than people think. (No, I don't have the URL handy, and > no, I don't trust that author absolutely.) It's one of those things that sounds simple but turns out not to be in practice. The issues aren't the least bit obvious and require careful thought; the fact that no one has a 100% working, bug free implementation should tell you how complicated it really is! Adam
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web