On Sun, May 23, 2010 at 11:12:22PM -0700, Niels Mayer wrote:
On Sun, May 23, 2010 at 1:55 PM,
<fons(a)kokkinizita.net> wrote:
I find this sort of thing absolutely beyond comprehension.
It's impossible to understand without knowing the boost::
abstractions, templates and god knows what else.
IMNSHO, the way any software works should be understandable by
a) knowing the language, b) reading the code, at least up to the
point that the reader can have an good idea of the big picture,
of data structures and control flow, only excluding application
domain specific details which require special expertise anyway.
If libraries are used to somehow extend the language rather for
encapsulating application domain specific algorithms, the net
result is code that is utterly unreadable to anyone who happens
not to use the same libraries. This is true for libs such as STL
and to a larger degree, boost.
Exactly.
The issue is that advanced programming concepts are being shoehorned
into a programming paradigm, and language, that is not supportive of
that paradigm. For example, functional programming, which Paul Davis
admits is difficult without garbage collection:
paul argued about the usage of shared_ptr vs. plain C.
shared_ptr is a form of garbage collection.
its definitely part of c++0x stl.
and yes. doing functional programming in c++ without shared_ptr would be
pretty much impossible.
i also can't begin to imagine how to
implement scoped-lifetime objects in C. even without exceptions (which admittedly do cause
some conceptual pain in C++), the ability to know that wherever you return from within a
function, relevant local objects will be cleaned up has a significant simplifying effect
on the design of a function.
Which is why I brought up clojure. Assuming that we get part of the
"real-timeness" of our RT programming by using multiple processors
wisely, and given that we're hitting physics clock-speed limitations
towards further performance increases in single-threaded processing...
the winners will be those that can reliably and scalably orchestrate
multiple slower processors to run fast.
The functionality of "parallel" and "cloud" computation is
fundamental
to Clojure as a language. Instead of being add-on libraries, and even
worse, "design patterns" and "programming by cut and paste," which
is
what most complicated library usage ends up being, especially if it is
a language extension.
for me the stl is an integral part of c++.
and adding language features for things which can be implemented as part
of the STL, escapes my understanding.
c++ is a strongly typed language. it doesnt need language extensions, to
model promises and futures.
it needed a language extension for closures. it got that.
clojure is dynamic. so you need some language extension to classify
the dynamic types. i could reverse all this arguing, and argue that a
dynamically typed language is not the right tool if your dynamic types
need to end up being different types.
because std::promise<boost::any> is different from boost::any
If there are issues with these constructs or concepts, it'll get fixed
in the language; if implementations don't measure up, there will be a
language standard and reference implementations by which to compare
and dictate what's correct and documented behavior versus bug. If the
language ends up being widely used, then there will be plenty of
documentation and education on formerly esoteric concepts that are now
part of a language (much like how C++ and Java made "object oriented"
to be well understood, "promise" and "future" will be standard
cocepts
for the languages that get popular for parallel computation).
likewise i predict, that people will be using promises in c++ too, once
c++0x starts to be adopted.
and people WILL pretty quickly jump onto the std::thread train.
http://www.michaelharrison.ws/weblog/?p=239
.....
>
> Clojure offers more than one option for achieving concurrency. Whereas CommonJS
embraces asynchronous processes, Clojure offers the programmer a choice of synchronized or
asynchronized tools for concurrency. And whereas JavaScript doesn’t offer you the
opportunity to spawn your own threads, Clojure most definitely offers you threads. Clojure
1.1 has added abstractions for promises and futures, and Clojure’s multithreaded
environment colors their usage.
>
> In Clojure, as in CommonJS, a promise is also a stand-in for an
asynchronously-computed value. As Rich Hickey explains in his change notes for the 1.1
release: (
http://github.com/richhickey/clojure/blob/1.1.x/changes.txt )
>
> A promise is a synchronization construct that can be used to deliver a value from
one thread to another. Until the value has been delivered, any attempt to dereference the
promise will block.
>
> A future, however, represents a unit of computation that can be executed on another
thread.
>
> Futures represent asynchronous computations. They are a way to get code to run in
another thread, and obtain the result.
>
> Sean Devlin, the creator of the excellent screencasts at Full Disclojure (
http://vimeo.com/channels/fulldisclojure ), has a screencast covering promises and futures
(
http://www.vimeo.com/8320428 ) He offers some examples:....
same thing with c++ promises...
......
Again IMNSHO, a programming language should be
used 'as is',
without trying to extend it or introduce concepts that are
not part of it ('shared_ptr', 'promise' (whatever that means),
'spromise' (whatever that means), etc.). All the rest is just
obfusciation, and useful only to some niche of 'believers'.
It's not obfuscation. It's the wrong-language-for-the-job desperately
attempting to represent a well-known, computer science concept:
it was pretty much the same code as the clojure example.
just in strongly typed language.
the shared_ptr is the c++ way of opting in for garbage collection.
and this is the only point that might be the c++ problem. it would
probably smarter to opt-out of garbage collection.
since one wants GC most of the time. but thats not how c++ evolved.
http://en.wikipedia.org/wiki/Futures_and_promises
In computer science, future, promise,
and delay refer to constructs used for synchronization in some concurrent programming
languages. They describe an object that acts as a proxy for a result that is initially not
known, usually because the computation of its value has not yet completed.
The difference is that the example I posted -- 13 lines of clojure --
uses "promise" and "future" as built-in, semantically
well-understood
language primitives along with some "markup" to distinguish different
mutable storage types associated with variable names
http://stackoverflow.com/questions/1028318/clojure-mutable-storage-types:
right. bolting "types" onto a dynamically typed language ;)
* Vars are like regular old variables in
imperative languages. (avoid when possible)
* Atoms are like Vars but with thread-sharing safety that allows for immediate reading and
safe setting.
* An Agent is like an Atom but rather than blocking it spawns a new thread to calculate
its value, only blocks if in the middle of changing a value, and can let other threads
know that it's finished assigning.
* Refs are shared locations that lock themselves in transactions. Instead of making the
programmer decide what happens during race conditions for every piece of locked code, we
just start up a transaction and let Clojure handle all the lock conditions between the
refs in that transaction.
Thus clojure has the needed functionality built-in to the language,
including new types of variables. It is designed to be used "as is"
and there are many excellent examples on programming in clojure, as
well as several books.
It's quite neat, IMHO, especially because some of the brightest minds
in the industry inadvertently worked on the compiler for it. (the Java
JIT) and millions of users have debugged it for the last few decades.
That's a lot of leverage for a new language.
there has been an interesting demo of the dalvik vm on google io.
http://www.youtube.com/googledevelopers#p/a/CF01A789E62F2454/0/IY3U2GXhz44
its demoed around 9:45
you see a game running in the new dalvik with a JIT and the old dalvik
without.
the game was modified to flash red when the framerate drops below 30fps.
while the overall throughput of JIT vm is higher. it flashes a few times
before the cpu load gets too high for the non JIT vm to go into deep
red.
when speaking strict RT performance the non-JIT vm performs better.
the java JIT is probably better. but i doubt that anybody bothered to
implement swapping in the new code in a lock free way.
--
torben Hohn