The Future of C++ ?

A

Alf P. Steinbach

* Tony:
The question was rhetorical.

That wasn't a question (note the absence of any question mark).

Conceptual PLONK.

That means, I'll not be responding to your articles except perhaps to
resque others from misunderstandings.
 
N

Noah Roberts

Howard said:
Ok, I have to put this into perspective.

I just got through reading a post here complaining that discussing
hash_map was off topic for comp.lang.c++ because it isn't in the
standard.

I think if you go back and reread what was said you'll find that nobody
said what you are saying was said.
 
C

Chris Thomasson

Kai-Uwe Bux said:
Chris said:
Course in Java: [...]
And we can process concurrently...
C++ is very useful because

I can use it with Assembly Language to create a high-end synchronization
algorithms. I can use to create a full blown Java VM... I can use C++ to
prototype virtually anything for that matter. Can't use Java for any of
that.

I would like to see the C++ course completion of which will enable you to
create a full blown Java VM. Do you seriously suggest that, say, as a term
paper?

I think I could put together a couple of courses that would teach a student
how to make use of lock-free data-structures' in the context of a virtual
machine. The course would have a prerequisite for basic SPARC or IA-32
Assembly Language skills and fairly advanced knowledge in data-structures
and C or C++; I suggest a course that teaches how to implement the Standard
C++ template library. The virtual machine would of course have a weak cache
coherency, and a very clear memory model... I could go on and on, but it off
topic.

;^)
 
E

Earl Purple

Alf said:
I pulled that quote from <url:
http://www.research.att.com/~bs/hopl2.pdf>, where he further writes that
"Exceptions were considered in the original design of C++, but were
postponed because there wasn't time to do a thorough job of exploring
the design and implementation issues. Exceptions were considered
essential for error handling in programs composed out of separately
designed libraries. The actual design of the C++ exception mechanism
stretched from 1984 to 1989."

Now go do your own research... ;-)

I agree we need exceptions in the language and they are a useful
feature. But do we really need exceptions to be type-oriented ?
Couldn't we all manage with just one exception class?

We do try..catch somewhere and where we catch we can examine the
exception if appropriate and take the right action, possibly rethrowing
it or throwing a new one.

Most of the time I have seen developers who write their own exception
classes tend to put in a numeric value as well as text. I sometimes
embed the numeric value into the string with a tab separator to have
that effect, but I find on the whole I am throwing only standard
exceptions and that runtime_error actually suffices.

If the one exception class used a code as well as text, some of the
error codes could be standard.

Now, I ask, what would be the difference in overhead to having one
exception class and typed exceptions with regards to the compiler and
the code generated etc. Would the systems that currently reject C++
exceptions start using the one class?

For the sake of portable code, we could employ the current syntax and
have this one exception class derive from std::runtime_error.

Compilers on the smaller system would probably give an error if the
detected any type being thrown other than the one exception class.
 
E

Earl Purple

Tony said:
What percentage of exceptions get handled anyway (that is, in a way other than abort)?

I don't know about percentages but in applications I write, many are
handled by logging the error. The task in hand is usually aborted but
the task isn't necessarily the whole program. You can't shutdown a
server every time a task fails.

A typical example might be a broken link to a remote server. If the
remote server is down, you log the exception and then subsequently you
might be able to reconnect. Perhaps not every action you do uses that
server anyway.
 
N

Noah Roberts

Earl said:
I agree we need exceptions in the language and they are a useful
feature. But do we really need exceptions to be type-oriented ?
Couldn't we all manage with just one exception class?

We do try..catch somewhere and where we catch we can examine the
exception if appropriate and take the right action, possibly rethrowing
it or throwing a new one.

I suspect that allowing the compiler to create a table based on type
and jumping to the correct handler instead of comparing to a string to
find out what error condition you are dealing with is faster. I have
no real numbers to back up that claim though...only an assumption based
on the O().
Most of the time I have seen developers who write their own exception
classes tend to put in a numeric value as well as text. I sometimes
embed the numeric value into the string with a tab separator to have
that effect, but I find on the whole I am throwing only standard
exceptions and that runtime_error actually suffices.

Certainly deriving from a standard exception is appropriate and usually
allows you to create your own with a minimum of extra code and no
changes to the interface.
If the one exception class used a code as well as text, some of the
error codes could be standard.

I still suspect that the static typing jump is faster than a runtime
comparison of exception codes.
Now, I ask, what would be the difference in overhead to having one
exception class and typed exceptions with regards to the compiler and
the code generated etc. Would the systems that currently reject C++
exceptions start using the one class?

You might get a little space savings in your executable at the cost of
some speed overhead created by checking error codes. I don't expect a
really great difference either way though. Might be worth testing...
 
R

Ramon F Herrera

blangela said:
If you had asked me 5 years ago about the future of C++, I would have
told you that its future was assured for many years to come. Recently,
I have been starting to wonder.

I have been teaching C++ at a local polytechnical school here in
Vancouver, Canada for approximately 8 years. Six years ago, at the
height (or should I say volume?) of the internet bubble, I had 80+
students per semester in my C++ course. Now I am fortunate to have 15
students per semester. What has changed? I believe that students are
no longer interested in learning C++. They would rather learn .NET
languages or Java (my colleages who teach these courses seem to be very
busy!). I believe it is because these other languages are easier to
learn and/or are perceived to be more relevant today.

I do believe that C++ is more difficult to learn than many of these
other languages. Despite my best efforts to make them exciting, I see
the eyes of my students start to glaze over when I start explaining
pointers. When I ask them to tokenize an english sentence (using the
strtok() function) and print the token in reverse order (they need to
declare an array of type char * and save the addresses of the tokens in
this array), I experience near panic from many of my students. But
these concepts need to be taught in a responsible C++ course. As was
pointed out to me recently, Microsoft still requires applicants to
demonstrate a very good knowledge of string manipulation using C-style
strings (none of these fancy string class objects!) when recruiting C++
programmers.

The ironic part is there is still a large demand for C++ developers
here in Vancouver. In fact, the company that I believe employs the
most developers here in Vancouver, employs almost entirely C++
programmers. This company, Electronic Arts (if you have not heard of
them, I guarantee that your kids have -- they create video games) is
only one of several gaming companies here in Vancouver that employ
primarily C++ programmers. Other companies like Kodak, MDSA, Nokia,
MDSI, etc. also employ large numbers of C++ programmers. Not
surprisingly, I have talked to several companies here in Vancouver who
are complaining that they are having difficulty finding C++ developers
and are looking at trying to recruit from abroad (eastern Europe
primarily).

I believe that many of these companies will be forced to migrate away
from C++ in the near future, simply because they will not be able to
find C++ programmers in the future. Soon the baby boomer C++
programmers will begin to retire, then the proverbial @@@@ will really
start to hit the fan!

Please tell me I am wrong, and paint me a view of the future which
includes C++.

Here we have some opinions from the horse's mouth.

http://www.technologyreview.com/InfoTech/17831/

-Ramon
 
E

Earl Purple

Noah said:
I suspect that allowing the compiler to create a table based on type
and jumping to the correct handler instead of comparing to a string to
find out what error condition you are dealing with is faster. I have
no real numbers to back up that claim though...only an assumption based
on the O().

It may or may not be faster. If the standard exception has an
enumerated code as well as text though, you can do a switch on the code
or on bits set in the code, which is a lot faster than parsing strings.

Much of the time, you don't care what exception happened though. You
want to log the text as a task failure and continue. You might already
know what to do by when it was thrown rather than what was thrown.

In addition, it is important to note that exception throwing should be
rare and it is unlikely that you are going to performance test based on
it, especially if the extra action is a minor one such as parsing a
string or checking the bits of an integer.
I still suspect that the static typing jump is faster than a runtime
comparison of exception codes.

I doubt it is, and even if so, it is probably not enough to justify the
overhead.
You might get a little space savings in your executable at the cost of
some speed overhead created by checking error codes. I don't expect a
really great difference either way though. Might be worth testing...

Just a little space savings? We are talking about a whole community
here that does not use exceptions at all because of the enormous
overhead. I am just wondering how much of this overhead is
type-checking based. Remember that the types are checked at the time
the exceptions are thrown and caught, not at compile time.

Having just the one exception still gives you the advantage over having
none at all, i.e. it will jump out of the block at the point the error
occurs, thus you can be sure that, at a point in a block of code, that
no error has occurred up to this point. It will mean there is no need
to create objects in a "zombie" state because you couldn't throw from
its constructor.
 
N

Noah Roberts

Earl said:
Just a little space savings? We are talking about a whole community
here that does not use exceptions at all because of the enormous
overhead.

Yeah, I've talked to those people. As far as I can tell not a one has
any objective information to back up the claim that there even is any
overhead much less enormous overhead. Some have minimal experience
with some compiler they used in the 90's that handled exceptions poorly
and have never bothered to look at anything more modern...those are the
_most_ informed.
 
C

Chris Thomasson

Mirek Fidler said:
Well, before going into details....

Have you found a way how to implement lock-free reference counting
usable e.g. for COW string? (with "weak" guarantee for string itself)?

If yes, what is the idea, if you are willing to share?


http://groups.google.com/group/comp.lang.c++.moderated/msg/a08aa9fe4d0d823e

In order for this to work I have to add CAS to the library... Humm, Well,
here is the source code for the CAS functions:


(mingw-gas)
--------------


..align 16
# int refcount_ia32_cas(
# refcount_ia32_t* volatile*,
# refcount_ia32_t*,
# refcount_ia32_t*)
..globl _refcount_ia32_cas
_refcount_ia32_cas:
MOVL 4(%ESP), %ECX
TESTL %ECX, %ECX
JE refcount_ia32_cas_failed
MOVL 8(%ESP), %EAX
MOVL 12(%ESP), %EDX
LOCK CMPXCHGL %EDX, (%ECX)
CMPL %EAX, 8(%ESP)
JNE refcount_ia32_cas_failed
MOVL $1, %EAX
RETL

refcount_ia32_cas_failed:
XORl %EAX, %EAX
RETL




..align 16
# int refcount_ia32_add_cas_weak(
# refcount_ia32_t* volatile*,
# refcount_ia32_t*,
# refcount_ia32_t*,
# int)
..globl _refcount_ia32_add_cas_weak
_refcount_ia32_add_cas_weak:
MOVL 4(%ESP), %ECX
TESTL %ECX, %ECX
JE refcount_ia32_cas_failed

MOVL 12(%ESP), %EDX
TESTL %EDX, %EDX
JE refcount_ia32_add_cas_weak_execute
MOVL 16(%ESP), %EAX
CMPL $0, %EAX
JLE refcount_ia32_add_cas_weak_execute
LOCK XADDL %EAX, (%EDX)

refcount_ia32_add_cas_weak_execute:
MOVL 8(%ESP), %EAX
LOCK CMPXCHG %EDX, (%ECX)
CMPL %EAX, 8(%ESP)
JNE refcount_ia32_add_cas_weak_dec
MOVL $1, %EAX
RETL

refcount_ia32_add_cas_weak_dec:
TESTL %EDX, %EDX
JE refcount_ia32_add_cas_weak_failed

CMPL $0, 16(%ESP)
JLE refcount_ia32_add_cas_weak_failed
LOCK DECL (%EDX)

refcount_ia32_add_cas_weak_failed:
XORL %EAX, %EAX
RETL


If you want to use CAS with my refcount library now, just stick the posted
source code in the refcount-ia32-mingw.asm file and assemble... Then create
the declarations in the refcount-ia32.h file, and add the proper member
functions to the refcount-sys.hpp and refcount.hpp files... Simple...

;^)


I am going to add the CAS to my library very soon, I will definitely keep
you posted. Okay?


:^)
 
C

Chris Thomasson

ACK! Those were crappy old versions...


Here is the newest ones:



..align 16
# int refcount_ia32_cas(
# refcount_ia32_t* volatile*,
# refcount_ia32_t*,
# refcount_ia32_t*)
..globl _refcount_ia32_cas
_refcount_ia32_cas:
MOVL 4(%ESP), %ECX
TESTL %ECX, %ECX
JE refcount_ia32_cas_failed
MOVL 8(%ESP), %EAX
MOVL 12(%ESP), %EDX
LOCK CMPXCHGL %EDX, (%ECX)
JNE refcount_ia32_cas_failed
MOVL $1, %EAX
RETL

refcount_ia32_cas_failed:
XORl %EAX, %EAX
RETL




..align 16
# int refcount_ia32_add_cas_weak(
# refcount_ia32_t* volatile*,
# refcount_ia32_t*,
# refcount_ia32_t*,
# int)
..globl _refcount_ia32_add_cas_weak
_refcount_ia32_add_cas_weak:
MOVL 4(%ESP), %ECX
TESTL %ECX, %ECX
JE refcount_ia32_cas_failed

MOVL 12(%ESP), %EDX
TESTL %EDX, %EDX
JE refcount_ia32_add_cas_weak_execute
MOVL 16(%ESP), %EAX
CMPL $0, %EAX
JLE refcount_ia32_add_cas_weak_execute
LOCK XADDL %EAX, (%EDX)

refcount_ia32_add_cas_weak_execute:
MOVL 8(%ESP), %EAX
LOCK CMPXCHG %EDX, (%ECX)
JNE refcount_ia32_add_cas_weak_dec
MOVL $1, %EAX
RETL

refcount_ia32_add_cas_weak_dec:
TESTL %EDX, %EDX
JE refcount_ia32_add_cas_weak_failed

CMPL $0, 16(%ESP)
JLE refcount_ia32_add_cas_weak_failed
LOCK DECL (%EDX)

refcount_ia32_add_cas_weak_failed:
XORL %EAX, %EAX
RETL



Can you notice the difference between the crap code and this code? Hint...
It has something to do with redundant condition codes...


;^)
 
M

Mirek Fidler

ACK! Those were crappy old versions...

Well, I must say that you are posting a lot of links to code, but
little explanation, I hope you would not mind if I place several stupid
beginner questions to get myself oriented... (I also do not have enough
time to harvest all informations over inet).
LOCK CMPXCHGL %EDX, (%ECX)
LOCK XADDL %EAX, (%EDX)

LOCK CMPXCHG %EDX, (%ECX)
LOCK DECL (%EDX)

Are these considered lock-free? Or they are used in "slow path" only?

If they are consideed lock-free, is there a performance difference
between CAS (LOCK CMPXCHGL %EDX, (%ECX)) and atomic increment/decrement
(LOCK DECL (%EDX))?

Mirek
 
C

Chris Thomasson

Mirek Fidler said:
Well, I must say that you are posting a lot of links to code, but
little explanation, I hope you would not mind if I place several stupid
beginner questions to get myself oriented... (I also do not have enough
time to harvest all informations over inet).




Are these considered lock-free?

Yes. They do assert the bus lock signal, but that different than using a
mutex:

http://groups.google.de/group/comp.programming.threads/msg/1fd5c6aa62e8f876
(this might clear some thing up for you...)



Or they are used in "slow path" only?

The only place where my algorithm makes use of a lock is in the
refcount_ia32_add_load_strong(...) function, and when the
refcount_ia32_sub_strong(...) drops the reference count to zero. Other than
that, everything is 100% lock-free.



If they are consideed lock-free, is there a performance difference
between CAS (LOCK CMPXCHGL %EDX, (%ECX)) and atomic increment/decrement
(LOCK DECL (%EDX))?

Not really. Except you can't use atomic increment/decrement alone to get
strong thread safety.
 
M

Mirek Fidler

Chris said:
Yes. They do assert the bus lock signal, but that different than using a
mutex:

Actually, I always thought that basic Win32 mutex (CRITICAL_SECTION) is
(in fast path) nothing more than single CAS operation...

Anyway, "LOCK CMPXCHGL %EDX, (%ECX)" is still about 400 times slower
than regular non-LOCK-ed operation, AFAIK.

I was sort of hoping that you found a way around this LOCK :)
Not really. Except you can't use atomic increment/decrement alone to get
strong thread safety.

Confused a bit again.

Say I have COW String, I am serializing the accesses to it (mutex for
both read and write), I always thought that atomic increment/decrement
of shared count is enough to keep me safe?

Does strong safety here mean that I would be able to read and/or write
the String without locking?

( Who needs it? :) )

Thanks for explaining.
 
J

Joe Seigh

Mirek said:
Chris Thomasson wrote:


Actually, I always thought that basic Win32 mutex (CRITICAL_SECTION) is
(in fast path) nothing more than single CAS operation...

Anyway, "LOCK CMPXCHGL %EDX, (%ECX)" is still about 400 times slower
than regular non-LOCK-ed operation, AFAIK.

I was sort of hoping that you found a way around this LOCK :)

Branch logic is almost as expensive as an inline LOCK. In multi-core
will become the norm, unconditional LOCK is probably the most efficient.
Confused a bit again.

Say I have COW String, I am serializing the accesses to it (mutex for
both read and write), I always thought that atomic increment/decrement
of shared count is enough to keep me safe?

Does strong safety here mean that I would be able to read and/or write
the String without locking?

( Who needs it? :) )

Maybe not for String, but for the more complex data structures like
collections lock-free beats anything else out there in solving
the reader/writer problem.
 
C

Chris Thomasson

Mirek Fidler said:
[...]
Yes. They do assert the bus lock signal, but that different than using a
mutex:

Actually, I always thought that basic Win32 mutex (CRITICAL_SECTION) is
(in fast path) nothing more than single CAS operation...

Consider the fact that the interlocked instruction used for CRITICAL_SECTION
does not operate on the shared data you want to alter. It only operates on
the lock state. And, you have to take into account that a lock has to be
unlocked. Thats another interlocked instruction.

So, if you measure a 100% uncontended lock-free operation vs. a 100%
unconteded lock-based operation you get this:



lock-free update if a word
------------------------

1 interlocked instruction




lock-based update of a word
-----------------------------

2 interlocked instructions
1 store




-- The interlocked instruction in the lock-free performed the update
directly to the word.


-- The interlocked instructions in the lock-based performed the update on
the locks internal state. The store instruction actually updated the word...


IMO, the lock-free stuff is a winner... Now if you take contention into
account, well, the lock-based stuff might have to park threads in the
kernel! The lock-free will not...


Is this making any sense to you? I don't think that I am a very good
teacher, but I try... So try to bear with me here...

;^)




Anyway, "LOCK CMPXCHGL %EDX, (%ECX)" is still about 400 times slower
than regular non-LOCK-ed operation, AFAIK.

I was sort of hoping that you found a way around this LOCK :)


Confused a bit again.

Say I have COW String, I am serializing the accesses to it (mutex for
both read and write), I always thought that atomic increment/decrement
of shared count is enough to keep me safe?

If you perform the atomic increments under the protection of the lock, then
you will be fine.



Does strong safety here mean that I would be able to read and/or write
the String without locking?

Once you acquire a strong reference to you string object, you can do
lock-free COW via. CAS.
 
M

Mirek Fidler

lock-free update if a word
lock-based update of a word

OK, as store is probably negligible, lock-free algorithm means saveing
one interlocked instruction, right?

BTW, do you have some info how really are expensive those atomic
operations?

I have seen numbers from 20 times more expensive to 1000 times more
expensive than non-atomic versions.
Is this making any sense to you? I don't think that I am a very good
teacher, but I try... So try to bear with me here...

Yes. Actually, after understanding the basic concept (that lock-free
still uses atomic operations, so it is lock-free, not LOCK-free), rest
is simple :)
Once you acquire a strong reference to you string object, you can do
lock-free COW via. CAS.

But is not it more expensive in reality for String class? Without
explicit serialization, I can lock only variables that are shared
across threads, with 'strong reference', CAS costs will be omnipotent,
right?
 
C

Chris Thomasson

Once you acquire a strong reference to you string object, you can do
lock-free COW via. CAS.

The basic idea is:


pseudo-code
---------------

typedef std::string mystring_t;
typedef vzsync::ptr::global<mystring_t> mystring_gptr_t;
typedef mystring_gptr_t::local_t mystring_lptr_t;


static mystring_gptr_t s_buf(new mystring_t("hello"));


void do_cow_cas(mystring_t const &src) {
mystring_lptr_t xchg(new mystring_t), cmp;

do {
cmp = s_buf;
if (cmp) {
xchg->append(src);
}
} while(s_buf.cas(cmp, xchg));
}


or you can do a 100% lock-free swap like this:

void do_swap_weak(mystring_lptr_t &dest, mystring_t const &src) {
dest->append(src);
s_buf = dest;
}


There are more tricks... However, are you having trouble understanding the
pseudo-code?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top